spring boot 过滤器、拦截器的区别与使用_hwm的专栏-博客
其他网址
spring boot 过滤器、拦截器的区别与使用_hwm的专栏-博客Spring Interceptor vs Filter 拦截器和过滤器区别 | ASPIRE
过滤器:《JSP&Servlet学习笔记》=> 5.3过滤器 拦截器:《深入浅出Spring Boot2.x》
简介
过滤器:Filter。拦截器:Interceptor 。
在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情,interceptor 都能够轻松的实现。
AOP:可以自定义切入的点,有方法的参数,但拿不到http请求,可以通过RequestContextHolder等方式获得。 AOP用法见:SpringAOP系列--AOP+注解 实例_feiying0canglang的博客-博客
调用顺序
过滤前=> 拦截前=> AOP=> Controller=> AOP=> 拦截后=> 过滤后
不同点
项过滤器拦截器使用场景对请求/响应进行修改、判断等。一般用于过滤参数、登录权限验证、资源访问权限控制、敏感词汇过滤、字符编码转换。在service或者一个方法前/后调用一个方法,或者在方法后调用一个方法。能力可以拿到原始的http请求与响应,拿不到请求的控制器和请求控制器中的方法的信息。
可以修改请求、响应、参数:比如:修改字符编码、删除低俗文字、删除危险字符、修改参数
可以拿到你请求的控制器和方法,却拿不到请求与响应。顺序可指定顺序。可指定顺序。实现方式回调函数AOP使用范围只能用于Web可用于Web、Application、Swing作用范围所有请求。只能是controller请求。静态资源无法控制。使用位置controller前后、dispaterServlet前后controller前后规范定义Servlet 规范定义,Servlet 容器支持。
Filter 接口定义在 javax.servlet 包
Spring容器内,Spring框架支持。
HandlerInterceptor 接口 定义在org.springframework.web.servlet 包
灵活性/粒度灵活性差(粒度大)。
不能够使用 Spring 容器资源
灵活性好(粒度小)。
能使用Spring里的任何资源、对象,例如 Service对象、数据源、事务管理等,通过IoC注入到拦截器即可。
打断链路打断方法:处理请求和响应对象来引发中断,需要额外的动作,比如将用户重定向到错误页面。打断方法:preHandle方法内返回 false执行次数一个controller周期只调用一次:一个过滤器实例只能在容器初始化时调用一次。
一个controller周期可调用多次其他网址
servlet过滤器
说明
Filter可以有多个。一个filter执行完之后会执行另外一个。
JavaDoc对过滤器使用场景的描述
Examples that have been identified for this design are<br> (1) Authentication Filters, //用户访问权限过滤 (2) Logging and Auditing Filters, //日志过滤,可以记录特殊用户的特殊请求的记录等 (3) Image conversion Filters (4) Data compression Filters <br> (5) Encryption Filters <br> (6) Tokenizing Filters <br> //过滤Token (7) Filters that trigger resource access events <br> (8) XSL/T filters <br> (9) Mime-type chain Filter <br>
两种方式注册filter(两种方式的本质都是一样的,都是去FilterRegistrationBean注册自定义Filter ): 1、使用spring boot提供的FilterRegistrationBean注册Filter 2、使用原生servlet注解定义Filter。缺点:无法指定过滤器顺序
注册方式1:FilterRegistrationBean
定义Filter
package com.example.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class MyFilter implements Filter { @Override public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { System.out.println("MyFilter.init"); System.out.println(" 过滤器名:" + filterConfig.getFilterName()); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 处理request 或response System.out.println("MyFilter.doFilter"); if (servletRequest instanceof HttpServletRequest) { System.out.println(" URL:" + ((HttpServletRequest)servletRequest).getRequestURL()); } // 调用filter链中的下一个filter filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("MyFilter.destroy"); } }注册自定义Filter
package com.example.filter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter()); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } }方式2:@WebFilter
package com.example.filter; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @Component // 定义filterName 和过滤的url @WebFilter(filterName = "myFilter" ,urlPatterns = "/*") public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("MyFilter.init"); System.out.println(" 过滤器名:" + filterConfig.getFilterName()); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 处理request 或response System.out.println("MyFilter.doFilter"); if (servletRequest instanceof HttpServletRequest) { System.out.println(" URL:" + ((HttpServletRequest)servletRequest).getRequestURL()); } // 调用filter链中的下一个filter filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("MyFilter.destroy"); } }测试结果
启动SpringBoot
2020-09-04 23:25:27.216 INFO 16948 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2020-09-04 23:25:27.216 INFO 16948 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 781 ms MyFilter.init 过滤器名:myFilter 2020-09-04 23:25:27.361 INFO 16948 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-09-04 23:25:27.493 INFO 16948 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2020-09-04 23:25:27.501 INFO 16948 --- [ main] com.example.DemoApplication : Started DemoApplication in 1.44 seconds (JVM running for 2.276) 2020-09-04 23:25:40.252 INFO 16948 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2020-09-04 23:25:40.253 INFO 16948 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2020-09-04 23:25:40.257 INFO 16948 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 4 mspostman访问:http://localhost:8080/hello/test1?name=Tony
后端结果:
MyFilter.doFilter URL:http://localhost:8080/hello/test1 HelloController.test1postman结果
{ "id": null, "name": "Tony", "age": null }关闭SpringBoot
Disconnected from the target VM, address: '127.0.0.1:57939', transport: 'socket' MyFilter.destroy 2020-09-04 23:26:00.810 INFO 16948 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'过滤器1
package com.example.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class MyFilter1 implements Filter { @Override public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { System.out.println("MyFilter1.init"); System.out.println(" 过滤器名:" + filterConfig.getFilterName()); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 处理request 或response System.out.println("MyFilter1.doFilter"); if (servletRequest instanceof HttpServletRequest) { System.out.println(" URL:" + ((HttpServletRequest)servletRequest).getRequestURL()); } // 调用filter链中的下一个filter filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("MyFilter1.destroy"); } }过滤器2
package com.example.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class MyFilter2 implements Filter { @Override public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { System.out.println("MyFilter2.init"); System.out.println(" 过滤器名:" + filterConfig.getFilterName()); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 处理request 或response System.out.println("MyFilter2.doFilter"); if (servletRequest instanceof HttpServletRequest) { System.out.println(" URL:" + ((HttpServletRequest)servletRequest).getRequestURL()); } // 调用filter链中的下一个filter filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("MyFilter2.destroy"); } }配置类
package com.example.filter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registrationBean1() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter1()); filterRegistrationBean.addUrlPatterns("/*"); // filterRegistrationBean.setName("xxx"); //可设置过滤器名字 //过滤器执行顺序。(决定doFilter顺序,不决定init和destroy顺序) filterRegistrationBean.setOrder(1); return filterRegistrationBean; } @Bean public FilterRegistrationBean registrationBean2() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter2()); filterRegistrationBean.addUrlPatterns("/*"); // filterRegistrationBean.setName("xxx"); //可设置过滤器名字 //过滤器执行顺序(决定doFilter顺序,不决定init和destroy顺序) filterRegistrationBean.setOrder(2); return filterRegistrationBean; } }执行结果
启动SpringBoot
MyFilter2.init 过滤器名:myFilter2 MyFilter1.init 过滤器名:myFilter1postman访问:http://localhost:8080/hello/test1?name=Tony
后端结果
MyFilter1.doFilter URL:http://localhost:8080/hello/test1 MyFilter2.doFilter URL:http://localhost:8080/hello/test1 HelloController.test1postman结果
{ "id": null, "name": "Tony", "age": null }关闭SpringBoot
Disconnected from the target VM, address: '127.0.0.1:57939', transport: 'socket' MyFilter2.destroy MyFilter1.destroy 2020-09-04 23:26:00.810 INFO 16948 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'测试结果(配置类setOrder的值调换顺序)
配置类:
package com.example.filter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registrationBean1() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter1()); filterRegistrationBean.addUrlPatterns("/*"); // filterRegistrationBean.setName("xxx"); //可设置过滤器名字 //过滤器执行顺序。(决定doFilter顺序,不决定init和destroy顺序) filterRegistrationBean.setOrder(2); return filterRegistrationBean; } @Bean public FilterRegistrationBean registrationBean2() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter2()); filterRegistrationBean.addUrlPatterns("/*"); // filterRegistrationBean.setName("xxx"); //可设置过滤器名字 //过滤器执行顺序(决定doFilter顺序,不决定init和destroy顺序) filterRegistrationBean.setOrder(1); return filterRegistrationBean; } }测试:
启动SpringBoot
MyFilter2.init 过滤器名:myFilter2 MyFilter1.init 过滤器名:myFilter1postman访问:http://localhost:8080/hello/test1?name=Tony
后端结果
MyFilter2.doFilter URL:http://localhost:8080/hello/test1 MyFilter1.doFilter URL:http://localhost:8080/hello/test1 HelloController.test1postman结果
{ "id": null, "name": "Tony", "age": null }关闭SpringBoot
Disconnected from the target VM, address: '127.0.0.1:57939', transport: 'socket' MyFilter2.destroy MyFilter1.destroy 2020-09-04 23:26:00.810 INFO 16948 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'其他网址
Spring Boot 优雅的配置拦截器方式 - GIT猿【边鹏】博客 - OSCHINASpring Boot拦截器(Interceptor)详解 - 掘金
使用场景
日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等权限检查:如登录检测,进入处理器检测检测是否登录性能监控:通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。(反向代理,如apache也可以自动记录);通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。Interceptor 的相关方法
Spring 中主要通过 HandlerInterceptor 接口来实现请求的拦截,实现 HandlerInterceptor 接口需要实现下面三个方法:
preHandle() – 在handler执行之前,返回 boolean 值,true 表示继续执行,false 为停止执行并返回。postHandle() – 在handler执行之后, 可以在返回之前对返回的结果进行修改afterCompletion() – 在请求完全结束后调用,可以用来统计请求耗时等等注意事项
实现WebMvcConfigurer接口是官方推荐的,下边两种不推荐。
实现WebMvcConfigurerAdapter:Spring5.0之后是废弃的。 继承WebMvcConfigurationSupport:会导致yml的配置失效。原因:WebMvcAutoConfiguration有个条件注解: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
拦截器类
package com.example.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor.preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor.postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor.afterCompletion"); } }配置类
package com.example.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()); // registry.addInterceptor(new MyInterceptor()).addPathPatterns("/hello/test2"); } }测试结果
postman访问:http://localhost:8080/hello/test1?name=Tony
后端结果:
MyInterceptor.preHandle HelloController.test1 MyInterceptor.postHandle MyInterceptor.afterCompletionpostman结果
{ "id": null, "name": "Tony", "age": null }拦截器类
package com.example.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor.preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor.postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor.afterCompletion"); } }配置类
package com.example.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // registry.addInterceptor(new MyInterceptor()); registry.addInterceptor(new MyInterceptor()).addPathPatterns("/hello/test2"); } }测试结果
postman访问:http://localhost:8080/hello/test1?name=Tony
后端结果:
HelloController.test1postman结果
{ "id": null, "name": "Tony", "age": null }使用场景示例:在需要登录验证的Controller的方法上使用注解。当然,也可以直接通过HttpServletRequest获得URI来判断。
注解类
package com.example.interceptor; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 在需要登录验证的Controller的方法上使用此注解 */ @Target({ElementType.METHOD}) // 可用在方法名上 @Retention(RetentionPolicy.RUNTIME)// 运行时有效 public @interface LoginRequired { }拦截器类
package com.example.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; public class MyInterceptor3 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor3.preHandle"); // 如果不是映射到方法直接通过 if (!(handler instanceof HandlerMethod)) { return true; } // 方法注解级拦截器 HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); // 判断接口是否需要登录。也可用method.isAnnotationPresent(LoginRequired.class) LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class); // 有 @LoginRequired 注解,需要认证 if (methodAnnotation != null) { // 取缓存,SESSION,权限判断等 System.out.println(" 权限判断等"); return true; } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor3.postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor3.afterCompletion"); } }拦截器配置
package com.example.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { //这个顺序会决定拦截器执行顺序 registry.addInterceptor(new MyInterceptor3()); // registry.addInterceptor(new MyInterceptor2()); // registry.addInterceptor(new MyInterceptor1()); // registry.addInterceptor(new MyInterceptor()).addPathPatterns("/hello/test2"); } }controller
package com.example.controller; import com.example.entity.User; import com.example.interceptor.LoginRequired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") public class HelloController { @LoginRequired @RequestMapping("/test1") public User test1(User user) { System.out.println("HelloController.test1"); return user; } }测试结果
postman访问:http://localhost:8080/hello/test1?name=Tony
后端结果
MyInterceptor3.preHandle 权限判断等 HelloController.test1 MyInterceptor3.postHandle MyInterceptor3.afterCompletionpostman结果
{ "id": null, "name": "Tony", "age": null }拦截器1
package com.example.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1.preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1.postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor1.afterCompletion"); } }拦截器2
package com.example.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor2 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor2.preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor2.postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor2.afterCompletion"); } }配置类
package com.example.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { //如果不写.order,则按照先后顺序 registry.addInterceptor(new MyInterceptor1()).order(0); registry.addInterceptor(new MyInterceptor2()).order(1); } }测试结果
postman访问:http://localhost:8080/hello/test1?name=Tony
后端结果
MyInterceptor1.preHandle MyInterceptor2.preHandle HelloController.test1 MyInterceptor2.postHandle MyInterceptor1.postHandle MyInterceptor2.afterCompletion MyInterceptor1.afterCompletionpostman结果
{ "id": null, "name": "Tony", "age": null }配置类(颠倒顺序)
package com.example.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { //如果不写.order,则按照先后顺序 registry.addInterceptor(new MyInterceptor2()).order(0); registry.addInterceptor(new MyInterceptor1()).order(1); } }测试结果(颠倒顺序后)
postman访问:http://localhost:8080/hello/test1?name=Tony
后端结果
MyInterceptor2.preHandle MyInterceptor1.preHandle HelloController.test1 MyInterceptor1.postHandle MyInterceptor2.postHandle MyInterceptor1.afterCompletion MyInterceptor2.afterCompletionpostman结果
{ "id": null, "name": "Tony", "age": null }实体类
package com.example.entity; import lombok.Data; @Data public class User { private Integer id; private String name; private Integer age; }控制器
package com.example.controller; import com.example.entity.User; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") public class HelloController { @RequestMapping("/test1") public User test1(User user) { System.out.println("HelloController.test1"); return user; } }过滤器
package com.example.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class MyFilter implements Filter { @Override public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { System.out.println("MyFilter.init"); System.out.println(" 过滤器名:" + filterConfig.getFilterName()); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 处理request 或response System.out.println("MyFilter.doFilter"); if (servletRequest instanceof HttpServletRequest) { System.out.println(" URL:" + ((HttpServletRequest)servletRequest).getRequestURL()); } // 调用filter链中的下一个filter filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("MyFilter.destroy"); } } package com.example.filter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registrationBean1() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter()); filterRegistrationBean.addUrlPatterns("/*"); // filterRegistrationBean.setName("xxx"); //可设置过滤器名字 return filterRegistrationBean; } }拦截器
package com.example.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor.preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor.postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor.afterCompletion"); } } package com.example.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()); } }@ControllerAdvice
package com.example.advice; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ModelAttribute; @ControllerAdvice public class GlobalControllerAdvice { @ModelAttribute public void authenticationUser() { System.out.println("GlobalControllerAdvice.authenticationUser"); } }对@RequestMapping的AOP
package com.example.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class RequestMappingAspect { @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)") public void pointcut() { } @Around("pointcut()") public Object around1(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("[RequestMappingAspect.around1]: around before"); Object object = joinPoint.proceed(); System.out.println("[RequestMappingAspect.around1]: around after"); return object; } }测试
启动SpringBoot
MyFilter.init 过滤器名:myFilterpostman访问:http://localhost:8080/hello/test1?name=Tony
后端结果
MyFilter.doFilter URL:http://localhost:8080/hello/test1 MyInterceptor.preHandle GlobalControllerAdvice.authenticationUser [RequestMappingAspect.around1]: around before HelloController.test1 [RequestMappingAspect.around1]: around after MyInterceptor.postHandle MyInterceptor.afterCompletion
postman结果
{ "id": null, "name": "Tony", "age": null }关闭SpringBoot
Disconnected from the target VM, address: '127.0.0.1:61631', transport: 'socket' MyFilter.destroy 2020-09-05 17:49:01.499 INFO 17144 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'