拦截器 介绍 拦截器,顾名思义,是一个全局的拦截某些请求的东西,是AOP思想的具体实现,在Spring中Controller方法执行之前和之后都可以看到拦截器的身影。以下是一个web请求的执行流程
浏览器发送请求到Tomcat服务器
需要静态资源直接去项目目录访问,动态资源才进入后端代码
经过几个过滤器过滤
进入中央处理器寻找对应的Controller中的方法
配置的拦截器会动态拦截控制器(Controller)中方法的执行,在方法执行前后进行操作,如jwt校验鉴权
演示
自定义的拦截器需要实现HandlerInterceptor接口,接口中有三个方法preHandle、postHandle等等,都是默认方法,不必强制实现,所有接口的实现类都会通过继承得到这个方法。源码里默认返回true,意思是直接放行。
1 2 3 4 default boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true ; }
自定义拦截器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Component public class TestInterceptor implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle" ); System.out.println(request.getHeader("host" )); System.out.println(handler.getClass()); HandlerMethod handlerMethod = (HandlerMethod) handler; System.out.println(handlerMethod.getMethod().getName()); response.setStatus(999 ); return true ; } @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle" ); response.setStatus(888 ); } @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion" ); response.setStatus(777 ); } }
注册拦截器,配置要拦截的路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Configuration @Slf4j public class WebConfig implements WebMvcConfigurer { @Autowired private TestInterceptor interceptor; @Override public void addInterceptors (InterceptorRegistry registry) { log.info("开始注册拦截器" ); registry.addInterceptor(interceptor).addPathPatterns("/**" ).order(1 ); } }
可以通过.order(1)来控制拦截器的执行优先级,数字越小优先级越高
Controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @RestController @RequestMapping("/fuish") public class TestController { @Autowired private Dog dog; @RequestMapping("/test") public String test (HttpServletResponse response) { String sound = dog.bark("wof~wof~wof~wof~wof~wof~wof~" ); return sound; } }
Dog实体类:
1 2 3 4 5 6 7 8 9 10 @Component public class Dog implements Animal { @Timer @Override public String bark (String sound) { System.out.println("方法执行: " + sound); return sound; } }
好了,浏览器输入localhost:8081/fuish/test,就可以在控制台查收拦截器的执行过程了。(我自己配置的8081端口)
1 2 3 4 5 6 7 8 preHandle localhost:8081 class org.springframework.web.method.HandlerMethod test 方法执行: wof~wof~wof~wof~wof~wof~wof~ class com.spring.Dog postHandle afterCompletion
过滤器 过滤器,是在java web中将你传入的request、response提前过滤掉一些信息,或者提前设置一些参数。然后再传入Servlet或Struts2的 action进行业务逻辑处理。比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入Servlet或Struts2的action前统一设置字符集,或者去除掉一些非法字符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Component @WebFilter(urlPatterns = "/*") public class TestFilter implements Filter { @Override public void init (FilterConfig filterConfig) throws ServletException { Filter.super .init(filterConfig); } @Override public void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; System.out.println("过滤器拦截: " + request.getRequestURI()); filterChain.doFilter(servletRequest, servletResponse); System.out.println("要走了也得过滤一道。最终返回的状态码:" + response.getStatus()); } @Override public void destroy () { Filter.super .destroy(); } }
1 2 3 4 5 6 7 8 9 10 过滤器拦截: /fuish/test preHandle localhost:8081 class org.springframework.web.method.HandlerMethod test 方法执行: wof~wof~wof~wof~wof~wof~wof~ class com.spring.Dog postHandle afterCompletion 要走了也得过滤一道。最终返回的状态码:999
可以发现过滤器的执行顺序同样遵循先进后出,过滤器链也是一样的
同样可以通过@Order(1)注解来控制过滤器的执行优先级,数字越小优先级越高
拦截器与过滤器的区别 Filter属于Servlet技术, Interceptor属于SpringMVC技术
自定义过滤器需要实现 javax.servlet.Filter接口,而这个接口是在Servlet规范中定义的,或者说过滤器需要依赖于Servlet容器,因此它只能在Web程序中使用
自定义拦截器需要实现org.springframework.web.servlet.HandlerInterceptor接口,存在于SpringMVC中,由Spring容器来管理,不依赖于Servlet容器,是可以单独使用的,因此不仅可以用在Web程序中,也可以用在Application、Swing等程序中
Filter对所有访问进行增强,Interceptor只对特定请求增强
Filter基于函数回调, Interceptor基于AOP思想