框架 day69 SpringMVC高级(Validation校验,数据回显,上传,json数据交互,RESTful支持,拦截器) - Go语言中文社区

框架 day69 SpringMVC高级(Validation校验,数据回显,上传,json数据交互,RESTful支持,拦截器)


第二天:高级知识

Validation校验方法(了解)

数据回显掌握

 

统一异常处理器掌握

上传图片(上传商品图片)掌握

json转换掌握

restFUL支持了解

拦截器掌握

 

1       注解开发-高级

 

 

 
1.1   Validation(了解)

 

         b/s系统中对http请求数据的校验多数在客户端进行,这也是出于简单及用户体验性上考虑,但是在一些安全性要求高的系统中服务端校验是不可缺少的,本节主要学习springmvc实现控制层添加校验。

         Spring3支持JSR-303验证框架,JSR-303 是JAVA EE 6 中的一项子规范,叫做BeanValidation,官方参考实现是Hibernate Validator(与Hibernate ORM 没有关系),JSR 303 用于对Java Bean 中的字段的值进行验证。

        

        

1.1.1        需求

         在商品信息修改提交时对商品信息内容进行校验,例如商品名称必须输入,价格合法性校验。

 

1.1.2        加入jar包

 

 

1.1.3        配置validator

 

<!-- 校验器 -->
<bean id="validator"
		class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
		<!-- 校验器-->
		<property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
		<!-- 指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessages.properties -->
		<property name="validationMessageSource" ref="messageSource" />
	</bean>
<!-- 校验错误信息配置文件 -->
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<!-- 资源文件名-->
		<property name="basenames">   
       	 <list>    
            <value>classpath:CustomValidationMessages</value> 
       	 </list>   
    	</property>
		<!-- 资源文件编码格式 -->
		<property name="fileEncodings" value="utf-8" />
		<!-- 对资源文件内容缓存时间,单位秒 -->
		<property name="cacheSeconds" value="120" />
	</bean>


 

 

1.1.4        将validator加到处理器适配器

 

1.1.4.1     配置方式1

	<mvc:annotation-driven validator="validator"> </mvc:annotation-driven>


1.1.4.2     配置方式2(自学)

<!-- 自定义webBinder -->
	<bean id="customBinder"
		class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
		<property name="validator" ref="validator" />
	</bean>


 

<!-- 注解适配器 -->
	<bean
		class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="webBindingInitializer" ref="customBinder"></property>
	</bean>

1.1.5        添加验证规则

 

public class Items {
    private Integer id;
    @Size(min=1,max=30,message="{item.name.length.error}")
    private String name;
    
    @NotEmpty(message="{pic.is.null}")
    private String pic;

 

1.1.6        错误消息文件CustomValidationMessages


item.name.length.error=商品名称在1到30个字符之间
pic.is.null=请上传图片


 

如果在eclipse中编辑properties文件无法看到中文则参考“Eclipse开发环境配置-indigo.docx”添加propedit插件。

 

1.1.7        捕获错误

 

修改Controller方法:

// 商品修改提交
	@RequestMapping("/editItemSubmit")
	public String editItemSubmit(@Validated @ModelAttribute("item") Items items,BindingResult result,
			@RequestParam("pictureFile") MultipartFile[] pictureFile,Model model)
			throws Exception {
	//如果存在校验错误则转到商品修改页面
		if (result.hasErrors()) {
			List<ObjectError> errors = result.getAllErrors();
			for(ObjectError objectError:errors){
				System.out.println(objectError.getCode());
				System.out.println(objectError.getDefaultMessage());
			}
			return "item/editItem";
		}


 

注意:添加@Validated表示在对items参数绑定时进行校验,校验信息写入BindingResult中,在要校验的pojo后边添加BingdingResult,一个BindingResult对应一个pojo,且BingdingResult放在pojo的后边。

 

商品修改页面显示错误信息:

页头:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>


在需要显示错误信息地方:

<spring:hasBindErrors name="item">
<c:forEach items="${errors.allErrors}" var="error">
	${error.defaultMessage }<br/>
</c:forEach>
</spring:hasBindErrors>


说明:

<spring:hasBindErrorsname="item">表示如果item参数绑定校验错误下边显示错误信息。

 

上边的方法也可以改为:

在controller方法中将error通过model放在request域,在页面上显示错误信息:

 

controller方法:

if(bindingResult.hasErrors()){
			model.addAttribute("errors", bindingResult);
}


页面:

<c:forEach items="${errors.allErrors}" var="error">
	${error.defaultMessage }<br/>
</c:forEach>


 

 

 

 

1.1.8        分组校验

如果两处校验使用同一个Items类则可以设定校验分组,通过分组校验可以对每处的校验个性化。

 

需求:商品修改提交只校验商品名称长度

 

定义分组:

分组就是一个标识,这里定义一个接口:

public interface ValidGroup1 {

}
public interface ValidGroup2 {

}

 

指定分组校验:

public class Items {
    private Integer id;
//这里指定分组ValidGroup1,此@Size校验只适用ValidGroup1校验
    @Size(min=1,max=30,message="{item.name.length.error}",groups={ValidGroup1.class})
    private String name;

// 商品修改提交
	@RequestMapping("/editItemSubmit")
	public String editItemSubmit(@Validated(value={ValidGroup1.class}) @ModelAttribute("item") Items items,BindingResult result,
			@RequestParam("pictureFile") MultipartFile[] pictureFile,Model model)
			throws Exception {


在@Validated中添加value={ValidGroup1.class}表示商品修改使用了ValidGroup1分组校验规则,也可以指定多个分组中间用逗号分隔,

@Validated(value={ValidGroup1.class,ValidGroup2.class})

 

1.1.9        校验注解


@Null  被注释的元素必须为 null  

@NotNull   被注释的元素必须不为 null  

@AssertTrue     被注释的元素必须为 true  

@AssertFalse    被注释的元素必须为 false  

@Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值  

@Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值  

@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值  

@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值  

@Size(max=, min=)   被注释的元素的大小必须在指定的范围内  

@Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内  

@Past  被注释的元素必须是一个过去的日期  

@Future    被注释的元素必须是一个将来的日期  

@Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式  

Hibernate Validator 附加的constraint  

@NotBlank(message =)   验证字符串非null,且长度必须大于0  

@Email 被注释的元素必须是电子邮箱地址  

@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内  

@NotEmpty  被注释的字符串的必须非空  

@Range(min=,max=,message=)  被注释的元素必须在合适的范围内

 

1.2   数据回显


1.2.1        需求

表单提交失败需要再回到表单页面重新填写,原来提交的数据需要重新在页面上显示。

 

1.2.2        简单数据类型

对于简单数据类型,如:Integer、String、Float等使用Model将传入的参数再放到request域实现显示。

如下:

	@RequestMapping(value="/editItems",method={RequestMethod.GET})
	public String editItems(Model model,Integer id)throws Exception{
		
		//传入的id重新放到request域
		model.addAttribute("id", id);


 

1.2.3        pojo类型

springmvc默认支持pojo数据回显,springmvc自动将形参中的pojo重新放回request域中,request的key为pojo的类名(首字母小写),如下:

	@RequestMapping("/editItemSubmit")
	public String editItemSubmit(Integer id,ItemsCustom itemsCustom)throws Exception{


springmvc自动将itemsCustom放回request,相当于调用下边的代码:

model.addAttribute("itemsCustom",itemsCustom);

 

jsp页面:

 

页面中的从“itemsCustom”中取数据。

 

如果key不是pojo的类名(首字母小写),可以使用@ModelAttribute完成数据回显。


@ModelAttribute作用如下:


1、绑定请求参数到pojo并且暴露为模型数据传到视图页面

此方法可实现数据回显效果。

// 商品修改提交
	@RequestMapping("/editItemSubmit")
	public String editItemSubmit(Model model,@ModelAttribute("item") ItemsCustom itemsCustom)


页面:

<tr>
	<td>商品名称</td>
	<td><input type="text" name="name" value="${item.name }"/></td>
</tr>
<tr>
	<td>商品价格</td>
	<td><input type="text" name="price" value="${item.price }"/></td>
</tr>


 

如果不用@ModelAttribute也可以使用model.addAttribute("item", itemsCustom)完成数据回显。

 

 

2、将方法返回值暴露为模型数据传到视图页面

//商品分类
	@ModelAttribute("itemtypes")
	public Map<String, String> getItemTypes(){
		
		Map<String, String> itemTypes = new HashMap<String,String>();
		itemTypes.put("101", "数码");
		itemTypes.put("102", "母婴");
		
		return itemTypes;
	}


页面:

商品类型:
<select name="itemtype">
	<c:forEach items="${itemtypes }" var="itemtype">
		<option value="${itemtype.key }">${itemtype.value }</option>		
	</c:forEach>
</select>


 

1.3   异常处理器

 

         springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。

        

1.3.1        异常处理思路

         系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

         系统的dao、service、controller出现都通过throwsException向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:

 

 

 

1.3.2        自定义异常类

         为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。

	public class CustomException extends Exception {

	/** serialVersionUID*/
	private static final long serialVersionUID = -5212079010855161498L;
	
	public CustomException(String message){
		super(message);
		this.message = message;
	}

	//异常信息
	private String message;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}


 

 

1.3.3        自定义异常处理器

 

public class CustomExceptionResolver implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {

		ex.printStackTrace();

		CustomException customException = null;
		
		//如果抛出的是系统自定义异常则直接转换
		if(ex instanceof CustomException){
			customException = (CustomException)ex;
		}else{
			//如果抛出的不是系统自定义异常则重新构造一个未知错误异常。
			customException = new CustomException("未知错误,请与系统管理 员联系!");
		}
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("message", customException.getMessage());
		modelAndView.setViewName("error");

		return modelAndView;
	}

}


 

1.3.4        错误页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>错误页面</title>

</head>
<body>
您的操作出现错误如下:<br/>
${message }
</body>

</html>


 

 

1.3.5        异常处理器配置

在springmvc.xml中添加:

 

<!-- 异常处理器 -->
	<bean id="handlerExceptionResolver" class="cn.itcast.ssm.controller.exceptionResolver.CustomExceptionResolver"/>

 

1.3.6        异常测试

修改商品信息,id输入错误提示商品信息不存在。

 

修改controller方法“editItem”,调用service查询商品信息,如果商品信息为空则抛出异常:

// 调用service查询商品信息
		Items item = itemService.findItemById(id);
		
		if(item == null){
			throw new CustomException("商品信息不存在!");
		}


在service中抛出异常方法同上。

 

1.3.7        扩展知识

1、异常处理器可以配置多个,如下配置两个异常处理器:

 

 

配置多个异常处理器的目的是针对不同的异常类型分别进行处理,并且springmvc在执行异常处理器时是按配置的顺序去执行的,但是需要注意的是除最后一个异常处理器返回ModelAndView外,其它的异常处理器返回null,springmvc源代码如下:

 

 

 

 

1.4   上传图片

1.4.1        配置虚拟目录

在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:

<ContextdocBase="F:developuploadtemp" path="/pic" reloadable="false"/>

 

访问http://localhost:8080/pic即可访问F:developuploadtemp下的图片。

 

也可以通过eclipse配置:

 

 

 

 

1.4.2        配置解析器

<!-- 文件上传 -->
	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设置上传文件的最大尺寸为5MB -->
		<property name="maxUploadSize">
			<value>5242880</value>
		</property>
	</bean>


 

1.4.3        jar包

CommonsMultipartResolver解析器依赖commons-fileupload和commons-io,加入如下jar包:


 

1.4.4        图片上传

    controller:

//商品修改提交
	@RequestMapping("/editItemSubmit")
	public String editItemSubmit(Items items, MultipartFile pictureFile)throws Exception{
		
		//原始文件名称
		String pictureFile_name =  pictureFile.getOriginalFilename();
		//新文件名称
		String newFileName = UUID.randomUUID().toString()+pictureFile_name.substring(pictureFile_name.lastIndexOf("."));
		
		//上传图片
		File uploadPic = new java.io.File("F:/develop/upload/temp/"+newFileName);
		
		if(!uploadPic.exists()){
			uploadPic.mkdirs();
		}
		//向磁盘写文件
		pictureFile.transferTo(uploadPic);

.....


    页面:

 

<form id="itemForm"
		action="${pageContext.request.contextPath }/item/editItemSubmit.action"
		method="post" enctype="multipart/form-data">
		<input type="hidden" name="pic" value="${item.pic }" />


file的name与controller形参一致:

			<tr>
				<td>商品图片</td>
				<td><c:if test="${item.pic !=null}">
						<img src="/pic/${item.pic}" width=100 height=100 />
						<br />
					</c:if> <input type="file" name="pictureFile" /></td>
			</tr>


1.5   json数据交互

1.5.1        @RequestBody

作用:

@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

 

本例子应用:

@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象

 

1.5.2        @ResponseBody

作用:

该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

 

本例子应用:

@ResponseBody注解实现将controller方法返回对象转换为json响应给客户端

 

1.5.3        请求json,响应json实现:

1.5.3.1     环境准备

Springmvc默认用MappingJacksonHttpMessageConverter对json数据进行转换,需要加入jackson的包,如下:


1.5.3.2     配置json转换器

在注解适配器中加入messageConverters

<!--注解适配器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="messageConverters">
		<list>
		<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
		</list>
		</property>
	</bean>

 

注意:如果使用<mvc:annotation-driven /> 则不用定义上边的内容。

 

 

1.5.3.3     controller编写

// 商品修改提交json信息,响应json信息
	@RequestMapping("/editItemSubmit_RequestJson")
	public @ResponseBody Items editItemSubmit_RequestJson(@RequestBody Items items) throws Exception {
		System.out.println(items);
		//itemService.saveItem(items);
		return items;

	}


 

1.5.3.4     页面js方法编写:

引入 js:

<script type="text/javascript"

src="${pageContext.request.contextPath}/js/jquery-1.4.4.min.js"></script>

//请求json响应json
	function request_json(){
		$.ajax({
			type:"post",
			url:"${pageContext.request.contextPath }/item/editItemSubmit_RequestJson.action",
			contentType:"application/json;charset=utf-8",
			data:'{"name":"测试商品","price":99.9}',
			success:function(data){
				alert(data);
			}
		});
	}


 

1.5.3.5     测试结果:

 

 

从上图可以看出请求的数据是json格式

 

 

1.5.4        请key/value,响应json实现:

表单默认请求application/x-www-form-urlencoded格式的数据即key/value,通常有post和get两种方法,响应json数据是为了方便客户端处理,实现如下:

 

1.5.4.1     环境准备

同第一个例子

 

1.5.4.2     controller编写

 

	// 商品修改提交,提交普通form表单数据,响应json
	@RequestMapping("/editItemSubmit_ResponseJson")
	public @ResponseBody Items editItemSubmit_ResponseJson(Items items) throws Exception {

		System.out.println(items);

//		itemService.saveItem(items);
		return items;
	}

 

1.5.4.3     页面js方法编写:

 

function formsubmit(){
	var user = " name=测试商品&price=99.9";
	alert(user);
	  $.ajax(
		{
			type:'post',//这里改为get也可以正常执行
			url:'${pageContext.request.contextPath}/item/ editItemSubmit_RequestJson.action',
//ContentType没指定将默认为:application/x-www-form-urlencoded
			data:user,
			success:function(data){
				alert(data.name);
			}
			
		}	
	)
}

 

从上边的js代码看出,已去掉ContentType的定义,ContentType默认为:application/x-www-form-urlencoded格式。

 

 

1.5.4.4     测试结果

 略

从上图可以看出请求的数据是标准的key/value格式。

 

 

1.5.5        小结

实际开发中常用第二种方法,请求key/value数据,响应json结果,方便客户端对结果进行解析。

 

 

1.6   RESTful支持


什么是RESTful

 

rest即RepresentationalState Transfer,表现层状态转化

 

互联网上资源(是服务)细化理解为一个url,如果访问某个资源通过http url访问。

 

我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)

 

表现层对用户展示的形式:html、json、xml、pdf、图片。。

 

如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。

 

GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

 

目前常用就是get、post。

 

 

RESTful就是对http最全面最好的诠释,RESTful就是进行互联网开发的理念、思想。

 

RESTful开发:

1、url规范

原始url:http://www....../queryItems.action?type=101&id=111...

规范后:http://wwww.../item/101/1

比如:

对商品查询

url:http://wwww.../item/101/1表示对101分类下的1号商品查询

http请求方法设置为get

比如:

对商品删除

url:http://wwww.../item/101/1表示对101分类 下的1号商品删除

http请求方法设置为delete

 

2、给用户展示信息

在请求时指定服务端给客户端响应的内容类型是什么?

实现:在请求时设置http头中Accept

对商品查询,以json格式展示:

rest设置:

url为:http://wwww.../item/101/1

客户端请求此url并且设置Accept为"applicatoin/json"

 

服务端处理方法:

接收请求,解析Accept,根据指定类型返回不同的内容格式。

如果解析到Accept为"applicatoin/json",服务端就将内容转成json输出

 

如果解析到Accept为"applicatoin/xml",服务端就将内容转成xml输出

 

 

 

RESTful架构的特点:

综合上面的解释,我们总结一下什么是RESTful架构:

  (1)每一个URI代表一种资源;

实现:

规范后的url规范后:http://wwww.../item/101/1,特点是参数通过url传递。

  (2)客户端和服务器之间,传递这种资源的某种表现层;

实现:

服务端解析Accept,根据客户端的要求将内容进行输出。

 

  (3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。

实现:

服务解析客户端请求的http方法,根据不同的方法执行不同的service操作。

 

 

 

当前的现状:

 

实现第一点:url实现rest风格。

实现第二点:对外提供rest接口,输出json数据。

一般没有实现第三种的。



1.6.1        需求

RESTful方式实现商品信息查询,返回json数据

 

1.6.2        添加DispatcherServlet的rest配置

 

<span style="white-space:pre">	</span><servlet>
		<servlet-name>springmvc-servlet-rest</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring/springmvc.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc-servlet-rest</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

1.6.3        URL模板模式映射

@RequestMapping(value="/ viewItems/{id}"):{×××}占位符,请求的URL可以是“/viewItems/1”或“/viewItems/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。

 

@RequestMapping("/viewItems/{id}") 
	public @ResponseBody viewItems(@PathVariable("id") String id,Model model) throws Exception{
		//方法中使用@PathVariable获取useried的值,使用model传回页面
		//调用 service查询商品信息
		ItemsCustom itemsCustom = itemsService.findItemsById(id);
		return itemsCustom;
}

 

如果RequestMapping中表示为"/viewItems/{id}",id和形参名称一致,@PathVariable不用指定名称。

 

 

1.6.4        静态资源访问<mvc:resources>

如果在DispatcherServlet中设置url-pattern为 /则必须对静态资源进行访问处理。

spring mvc 的<mvc:resourcesmapping="" location="">实现对静态资源进行映射访问。

如下是对js文件访问配置:

<mvc:resources location="/js/"mapping="/js/**"/>

 

 

2       拦截器

2.1   定义

         SpringWeb MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

 

2.2   拦截器定义

实现HandlerInterceptor接口,如下:

Public class HandlerInterceptor1 implements HandlerInterceptor{

	/**
	 * controller执行前调用此方法
	 * 返回true表示继续执行,返回false中止执行
	 * 这里可以加入登录校验、权限拦截等
	 */
	@Override
	Public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		// TODO Auto-generated method stub
		Return false;
	}
	/**
	 * controller执行后但未返回视图前调用此方法
	 * 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
	 */
	@Override
	Public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		
	}
	/**
	 * controller执行后且视图返回后调用此方法
	 * 这里可得到执行controller时的异常信息
	 * 这里可记录操作日志,资源清理等
	 */
	@Override
	Public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		
	}

}



2.3   拦截器配置

2.3.1        针对某种mapping配置拦截器

<bean
	class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
	<property name="interceptors">
		<list>
			<ref bean="handlerInterceptor1"/>
			<ref bean="handlerInterceptor2"/>
		</list>
	</property>
</bean>
	<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
	<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>


 

 

2.3.2        针对所有mapping配置全局拦截器

<!--拦截器 -->
<mvc:interceptors>
	<!--多个拦截器,顺序执行 -->
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="cn.itcast.springmvc.filter.HandlerInterceptor1"></bean>
	</mvc:interceptor>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="cn.itcast.springmvc.filter.HandlerInterceptor2"></bean>
	</mvc:interceptor>
</mvc:interceptors>


 

2.4   正常流程测试

 

2.4.1        代码:

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2,每个拦截器的preHandler方法都返回true。

 

 

 

2.4.2        运行流程

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

 

HandlerInterceptor2..postHandle..

HandlerInterceptor1..postHandle..

 

HandlerInterceptor2..afterCompletion..

HandlerInterceptor1..afterCompletion..

 

 

2.5   中断流程测试

2.5.1        代码:

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2。

 

 

2.5.2        运行流程

HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true,运行流程如下:

 

HandlerInterceptor1..preHandle..

 

从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且controller也不执行了。

 

 

HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false,运行流程如下:

 

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

HandlerInterceptor1..afterCompletion..

 

从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。

 

总结:

preHandle按拦截器定义顺序调用

postHandler按拦截器定义逆序调用

afterCompletion按拦截器定义逆序调用

 

postHandler在拦截器链内所有拦截器返成功调用

afterCompletion只有preHandle返回true才调用

 

 

2.6   拦截器应用

 

2.6.1        用户身份认证

 

public class LoginInterceptor implements HandlerInterceptor{

	@Override
	Public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {

		//如果是登录页面则放行
		if(request.getRequestURI().indexOf("login.action")>=0){
			return true;
		}
		HttpSession session = request.getSession();
		//如果用户已登录也放行
		if(session.getAttribute("user")!=null){
			return true;
		}
		//用户没有登录挑战到登录页面
		request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
		
		return false;
	}}


 

2.6.2        用户登陆controller

	//登陆提交
	//userid:用户账号,pwd:密码
	@RequestMapping("/login")
	public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{
		
		//向session记录用户身份信息
		session.setAttribute("activeUser", userid);
		
		return "redirect:item/queryItem.action";
	}
	
	//退出
	@RequestMapping("/logout")
	public String logout(HttpSession session)throws Exception{
		
		//session过期
		session.invalidate();
		
		return "redirect:item/queryItem.action";
	}


 


 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/opopopwqwqwq/article/details/51926617
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-29 19:09:48
  • 阅读 ( 790 )
  • 分类:前端

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢