自定义拦截器概述
1) Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器可以实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter 适配器类
① public boolean preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false。(判断是否还需要继续执行,true:放行;false:拦截)
② public void postHandle():这个方法在业务处理器处理完请求后(已经生成ModelAndView对象之后),但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求request进行处理。(如果在之前出现异常,则会停止运行,不会执行postHandle)
③ public void afterCompletion():方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。(相当于finally块中的语句,即一定会被执行)
拦截器和过滤器的区别:
Filter: 客户端发送请求的时候,先过滤,才会被Servlet处理
Interceptor: 已经交给DispatcherServlet处理了,在处理请求的过程中
设置拦截器的步骤:
1) 自定义拦截器类(可以定义多个拦截器)
package com.atguigu.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; @Component public class FirstInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("First:preHandle"); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("First:postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("First:afterCompletion"); } }
2) 在DispatcherServlet配置文件中配置拦截器
<mvc:interceptors> <!-- 默认拦截所有请求 -->
<!-- 方式一,手动配置bean标签 --> <bean class="com.atguigu.interceptor.FirstInterceptor"></bean> <bean class="com.atguigu.interceptor.SecondInterceptor"></bean> <!-- 方式二,要求拦截器类上必须加注解@Component --> <!-- <ref bean="firstInterceptor"/> --> <!-- 设置自定义拦截方式 --> <!--
<mvc:interceptor> <bean></bean> <mvc:mapping path=""/> <!--拦截总路径--> <mvc:exclude-mapping path=""/> <!--排除路径--> </mvc:interceptor>
--> </mvc:interceptors>
3)控制层
package com.atguigu.test; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class TestInterceptorController { /** * 当有多个拦截器时, * preHandle:按照拦截器数组的正向顺序执行 * postHandle:按照拦截器数组的反向顺序执行 * afterCompletion:按照拦截器数组的反向顺序执行 * * 当多个拦截器的preHandle有不同的值时,(考虑清楚什么时候preHandle执行后返回false) * 第一个返回false,第二个返回false:只有第一个preHandle会执行(第一个preHandle执行返回false,拦截程序) * 第一个返回true,第二个返回false:两个(全部)拦截器的preHandle都会执行 * 但是(全部)postHandle都不会执行,而afterCompletion只有第一个(返回false的拦截器之前的所有afterCompletion)会执行 * 第一个返回false,第二个返回true:只有第一个的preHandle会执行 */ @RequestMapping("/testInterceptor") public String testInterceptor() { return "success"; } }