拦截器是指通过统一拦截从浏览器发往服务器的请求来完成功能的增强。
使用场景:解决请求的共性问题,如:乱码问题、权限验证问题等
过滤器实现乱码问题
Spring MVC默认提供了CharacterEncodingFilter过滤器类,来对客户端的请求进行编码设置。
在web.xml中配置该过滤器:
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器与拦截器原理类似,其是最先对请求进行拦截,拦截器是当请求通过过滤器之后,在请求到达Controller之前进行拦截。当执行完Controller的方法之后再依次递归返回执行。
实现SpringMVC拦截器的三个步骤
1. 创建一个实现HandlerInterceptor接口,并实现接口的方法的类。
2. 将创建的拦截器注册到SpringMVC的配置文件中实现注册。
3. 配置拦截器的拦截规则。
HandleInterceptor的三个方法
方法名 | 执行顺序 | 参数 | 返回值 |
---|---|---|---|
preHandler | 在请求被处理之前进行调用 | HttpServletRequest, HttpServletResponse, Object(被拦截的请求目标对象) | 是否需要将当前请求拦截下来(false:请求将被终止; true:请求会被继续运行) |
postHandler | 在请求被处理之后进行调用 | HttpServletRequest, HttpServletResponse, Object, ModelAndView(改变显示的视图setViewName) | 无 |
afterCompletion | 在请求结束之后才进行调用 | HttpServletRequest, HttpServletResponse, Object, Exception | 无(主要做资源的销毁,如关闭IO流) |
public class EncodingInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception)
throws Exception {
System.out.println("EncodingInterceptor afterCompletion");
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView modelAndView)
throws Exception {
System.out.println("EncodingInterceptor postHandle");
//请求处理之后被调用,使用视图更改发送的参数内容
modelAndView.addObject("msg", "这是EncodingInterceptor的msg");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
System.out.println("EncodingInterceptor preHandle");
//请求处理前被拦截,设置编码
request.setCharacterEncoding("utf-8");
return true;
}
}
配置文件中实现注册
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/login/result*" />
<bean class="com.lmr.springmvc.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- 拦截的action路径 -->
<mvc:mapping path="/login/*" />
<bean class="com.lmr.springmvc.interceptor.EncodingInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
如果配置多个拦截器,其执行顺序如下所示:
拦截器的其它实现方式
1.拦截器的类还可以通过实现WebRequestInterceptor接口来编写
2.向SpringMVC框架注册的写法不变
3.弊端:preHandler方法没有返回值,不能终止请求
Ps:建议使用功能更强大的实现方式,实现HandlerInterceptor接口。
public class TestInterceptor implements WebRequestInterceptor{
@Override
public void preHandle(WebRequest request) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void postHandle(WebRequest request, ModelMap model) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void afterCompletion(WebRequest request, Exception ex) throws Exception {
// TODO Auto-generated method stub
}
}
拦截器和过滤器
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
- 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑