了解拦截器
掌握SpringMVC拦截器的原理和使用
掌握SpringMVC拦截器的使用场景
SpringMVC拦截器的对比和总结
SpringMVC拦截器——适用场景:解决共性问题
1、解决乱码问题——配置拦截过滤器;
2、权限验证问题
3、拦截器的实现:
1)编写拦截器类实现HandlerInterceptor接口(目的:想让所有的请求都经过这个类,从而实现对请求的处理)
2)将拦截器注册进SpringMVC框架中(如不注册,编写的方法就不会执行)
3)配置拦截器的拦截规则
4、拦截器的方法:
1)preHandle()——请求被处理之前被调用;
2)postHandle()——请求被处理之后调用;
3)afterComplete()——请求结束之后调用
5、拦截器与过滤器的不同:
1)拦截器Interceptor:依赖于框架容器,基于反射机制,只过滤请求;
2)过滤器Filter:依赖于Servlet,基于回调函数,过滤范围广
什么是拦截器?
拦截器是指通过统一拦截从浏览器发往服务器的请求来完成功能的增强
使用场景:解决请求的共性问题(如:乱码问题、权限验证问题等)
拦截器的基本工作原理:
SpringMVC可以通过配置过滤器来解决乱码问题,拦截器的工作原理和过滤器非常相似。
通过过滤器解决乱码:
<filter>
<filter-name>encoding</>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</>
<init-param>
<param-name>encoding</>
<param-value>utf8</>
</>
</>
<filter-mapping>
<filter-name>encoding</>
<url-pattern>*</>
</>
配置过滤器:所有的请求都经过这个filter,经过后默认的编码设置为utf-8编码,刚开始填写中文用户名会出现乱码,后来配置过滤器,所有的请求经过这个过滤器编码都改为utf-8,就解决了乱码问题。
SpringMVC配置拦截器编码:org.springframework.web.servlet.DispatcherServlet
在applicationContext.xml中注册拦截器
mapping表示拦截的路径,bean表示对应的拦截器
<!-- 注册拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/home"/>
<bean class="com.interceptor.Interceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器的类需要实现HandlerInterceptor接口
preHandle表示在页面加载直接执行,postHandle表示在页面加载之后执行,afterCompletion表示在页面加载完成之后执行
public class Interceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("afterCompletion...");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("postHandle...");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("preHandle...");
return true;
}
}
过滤器在web.xml中配置,作用范围大,而拦截器是在默认的框架配置xml中配置,作用范围小。过滤器和拦截器的实现原理很像,但是过滤器的配置是写在xml中的,作用域是服务器,然而拦截器的配置是写在springmvc的配置文件中的。
拦截器方法的介绍:
1.preHandle方法,在请求被处理之前进行调用
(返回值是布尔值,表示我们是否需要将当前的请求拦截下来,如果返回false,请求将被终止,如果返回true,请求将会继续运行) object参数表示拦截下来的类对象
2.postHandle方法,在请求被处理之后进行调用
ModelAndView参数表示Controller传过来的ModelAndView,可以对返回的页面进行修改,可以改变显示的视图,或者修改发往视图的方法,参数。
3.afterCompletion方法,在请求结束之后进行调用
用于做些资源的销毁,关闭流,比较少会用到
三个方法中都具有HttpServletRequest、HttpServletResponse与Object类型的参数.
Object类型参数表示的是被拦截的请求的目标对象.即请求去到Controller对应的那个方法.
postHandle()方法会在请求被处理之后进行调用,该方法中有ModelAndView类型的参数,可以通过ModelAndView参数来改变要显示的视图,或修改发往视图中保存的属性值.
(利用ModelAndView的addObject()、setViewName()方法修改)
afterCompletion()方法会在请求被响应之后进行调用,即视图已经被显示出来之后再调用的方法.可以在该方法中进行资源的销毁操作.
在spring默认的配置文件中 拦截器 <mvc:interceptors></~~>
中至指定拦截器实现类/bean没有具体配置<mvc:iterceptor></>
则默认全局
二、 Spring MVC拦截器的实现
2.1. 拦截器的实现
实现SpringMVC拦截器的三个步骤
1. 创建一个实现HandlerInterceptor接口,并实现接口的方法的类
2. 将创建的拦截器注册到SpringMVC的配置文件中实现注册
<mvc:interceptors>
<bean class="路径下的类">
</mvc:interceptors>
- 配置拦截器的拦截规则:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="拦截的action">
<bean class="路径下的类">
</mvc:interceptor>
</mvc:interceptors>
拦截器方法介绍
1. preHandle()方法是否将当前请求拦截下来。(返回true请求继续运行,返回false请求终止(包括action层也会终止),Object arg代表被拦截的目标对象。)
2. postHandle()方法(ModelAndView对象可以改变发往的视图或修改发往视图的信息。)
3. afterCompletion()方法表示视图显示之后在执行该方法。(一般用于资源的销毁)
多个拦截器应用
多个拦截器执行顺序:
Request–>interceptor1.preHandle()–>interceptor2.preHandle()–>Controller–>interceptor2.postHandle()–>interceptor1.postHandle()–>interceptor2.afterCompletion()–>interceptor1.afterCompletion()–>Response
多个拦截器的执行顺序问题:比喻为从甲地往返乙地,经过两道收费站,最后收费站发来信息.
客户端发出请求是,会按顺序经过每个拦截器的preHandler方法,控制器做出反应后,会依次再从后往前的经过postHandler,最后再一起从后往前的经过afterCompletion方法。
拦截器的其他实现方式(HandleInterceptor和WebRequestInterceptor两个接口)
实现WebRequestInterceptor接口:向SpringMVC框架注册的写法是不变的。
弊端:preHandle方法没有返回值,不能终止请求。
Ps:建议使用功能更强大的实现方式,实现HandlerInterceptor接口。两者的方法都是一样的,只是参数不同。
拦截器的使用场景
使用原则:处理所有请求的共同问题
• 解决乱码问题:调用参数HttpRequest对象的setCharacterEncoding方法,传入”utf-8”
在preHandle方法中写个request.setCharacterEncoding(“utf-8”);这样每次请求通过拦截器都会设置为utf-8
• 解决权限验证问题:
调用参数HttpRequest对象的getSession方法得到session对象,再通过session对象的getAttribute方法得到相应的校验参数并继续校验处理
若校验不通过,使用HttpRequest对象的getRequestDispather方法转发到登陆界面。
也是在实现接口继承的preHandle方法中写
if(request.getSession().getAttribute("user") == null){//校验用户是否登录 request.getRequestDispatcher(“/login.jsp”).forward(request,response);
}
拦截器和过滤器的区别:
1.拦截器是基于java的反射机制的,而过滤器是基于函数回调。
2.拦截器不依赖于servlet容器,过滤器依赖于servlet容器。
3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有deep请求起作用。
4.拦截器可以访问action上下文,值栈里的对象,而过滤器不能访问。
5.在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6.拦截器可以获取IOC容器中的各种bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
参考视频:http://www.imooc.com/video/9752