Filter和Interceptor 使用场景和原理(二)
上接:Filter和Interceptor 使用场景和原理(一) - liyanbo - 博客园 (cnblogs.com)
上接 Filter和Interceptor 使用场景和原理(一), (一)主要对Filter 过滤器进行了总结和梳理,下面进行inteceptor的介绍,该Interceptor,中如果读request 请求数据需依赖 (一)过滤器,传递 RequestWrapper增强请求对象,使用该对象可以对请求数据Body读取多次,如果不使用只能读取一次。
Interceptor
一、原理定义说明
1、创建 MyIntecptor 需要实现 implements HandlerInterceptor
2、Inteceptor 接口方法说明
preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在请求处理之前被调用。如果已经是最后一个 Interceptor 的时候就会调用当前请求的 Controller 方法。
postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前请求处理完成之后,所以我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法需要在当前对应的 Interceptor 类的 preHandle 方法返回值为 true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行。此方法主要用来进行资源清理
3、Inteceptor 用途
1)、鉴权
2)、增加属性参数: request.setAttribute("startTime", startTime)
3)、记录 请求->响应时间 preHandle:记录开始时间 afterCompletion:记录结束时间 相减
4)、通用行为:读取 Cookie 得到用户信息,并解析后将用户对象放入请求
4、请看图
二、代码实例
1、MyInterceptor 定义拦截器 需实现HandlerInterceptor
/** * 拦截器 * filter——>servlet->interceptor->controller * 用于处理: * 1、鉴权 * 2、增加属性参数: request.setAttribute("startTime", startTime) * 3、记录 请求->响应时间 preHandle:记录开始时间 afterCompletion:记录结束时间 相减 * 4、通用行为:读取 Cookie 得到用户信息,并解析后将用户对象放入请求 * */ @Component public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long startTime = System.currentTimeMillis(); System.out.println("\n-------- LogInterception.preHandle --- "); System.out.println("Request URL: " + request.getRequestURL()); request.setAttribute("startTime", startTime);// 增加参数 if(request instanceof RequestWrapper){ // 获取请求参数 String bodyData=((RequestWrapper) request).getRequestBody(); System.out.println("bodyData = " + bodyData); } // 统一拦截(查询token) String token = request.getHeader("token"); if(StringUtils.isEmpty(token)){ //throw new CustomException(ResultEnum.MY_EXCEPTION.code,ResultEnum.MY_EXCEPTION.msg); // 验证登录,可以抛出自定义异常 // return false; } System.out.println("preHandle方法在控制器的处理请求方法调用之后,解析视图之前执行"); return true; // 返回 true: 正常执行 false:该请求停止向下运行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { long startTime = (Long) request.getAttribute("startTime"); long endTime = System.currentTimeMillis(); System.out.println("Request URL: " + request.getRequestURL()); System.out.println("End Time: " + endTime); System.out.println("Time Taken: " + (endTime - startTime)); } }
2)WebConfig 将拦截器注册添加到拦截器链
Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private MyInterceptor myInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor).addPathPatterns("/**"); // .excludePathPatterns("/user/get")/.addPathPatterns(). 可以排除和指定设置 } }
三、Filter和Inteceptor 的区别说明
1、使用范围不同
过滤器Filter实现了javax.servlet.Filter接口,也就是说过滤器的使用要依赖于Tomcat等容器,所以它只能在web程序中使用。
拦截器Interceptor实现了org.springframework.web.servlet接口,它是由Spring容器进行管理,并不依赖Tomcat等容器,既可以应用在web程序中,也可以应用在非web程序中。
2、触发时机不同
过滤器Filter是在请求进入Tomcat等容器后,servlet处理之前进行调用的。
拦截器Interceptor是在请求进入servlet后,执行Controller之前进行调用的。
3、深度不同:
Filter在只在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。所以在Spring构架的程序中,要优先使用拦截器。
至此Fitler和Inteceptor 原理和使用场景就总结和梳理就结束了,如有看不明白或疑问可以随时沟通交流,qq:626382542
代码实例:https://files.cnblogs.com/files/liyanbofly/filterIntecptorDemo.rar?t=1658933924