1、将过滤器加入项目的方式: (1)采用@Component 注解,实现过滤器bean注入 (2)针对第三方过滤器,即无@Component 注解,需要在@Configuration配置文件进行注册:
package com.mall.config; import java.util.ArrayList; import java.util.List; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.mall.filter.TimeFilter; @Configuration public class WebConfig { //第三方过滤器注解 @Bean public FilterRegistrationBean timeFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); TimeFilter timeFilter = new TimeFilter(); ///注册 registrationBean.setFilter(timeFilter); //配置需要拦截的URL,与@Component不同的区别,可以指定生效的URL List<String> urls = new ArrayList<String>(); urls.add("/*"); registrationBean.setUrlPatterns(urls); return registrationBean; } }小结:采用filter过滤器,可以获取http、http请求和响应,但无法获取与spring框架相关的信息,如哪个control处理,哪个方法处理,有哪些参数,这些都是无法获取的
2、拦截器:spring框架本身提供,需要在拦截器类加入@Component ,并且在配置文件进行注册
@Configuration public class WebConfig extends WebMvcConfigurerAdapter{ @Autowired private TimeInterceptor timeInterceptor; //WebConfig 需要继承 WebMvcConfigurerAdapter配置类 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInterceptor); } }小结:采用interceptor拦截器,除了获取http、http请求和响应对象,还可以获取请求的类名、方法名,但拦截器无法获取请求参数的值,从DispatcherServlet类源码分析,如下:
//DispatcherServlet未传入具体参数值信息到拦截器中 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); }3、切片 (1)注解介绍: @before : 方法执行前 @after : 方法执行后,抛出异常则不执行 @AfterThrowing : 无论是否抛出异常,都会执行 @Around : 覆盖前面三种方式 (2)配置:在切片类加上 @Aspect @Component 注解
package com.mall.aspect; import java.util.Date; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect @Component public class TimeAspect { /* 第一个*含义是:代表所有类型的返回值 第二个*是代表com.mall.web.controller包下的所有类 第三个是类下的所有方法,括号中两个点表示任意个形参 */ @Around("execution(* com.mall.web.controller.*.*(..))") public Object handleController(ProceedingJoinPoint pjp) throws Throwable { System.out.println("time aspect start"); //可获取参数值 Object[] args = pjp.getArgs(); for (Object arg : args) { System.out.println("arg is " + arg); } long start = new Date().getTime(); Object obj = pjp.proceed(); System.out.println("aspect : " + (new Date().getTime() - start)); System.out.println("time aspect end"); return obj; } }小结:切片 aspect 可以获取传入的参数值,但无法获取原始的http,http请求和响应对象
4、拦截启用顺序:依次是过滤器、拦截器、切片,这是服务正常的时候,服务异常时,最先捕获的是切片、ControllerAdvice注解类、拦截器、过滤器