当前位置:   article > 正文

springboot使用过滤器、拦截器、切片_springboot 拦截器 切片

springboot 拦截器 切片

一、springboot中过滤器、拦截器和切片(Aspect)的描述及区别

1、描述:

(1)过滤器(Filter):是servlet容器实现的功能,使用时需要引入 Servlet 依赖。其可以对所有请求进行过滤,其在容器启动时进行一次初始化调用init方法,容器关闭时调用销毁方法。主要用于对 请求和响应做一些信息过滤,或者设置及销毁一些参数信息。如修改字符编码、在request加入参数、对请求进行拦截、通过request的session判断用户登录状态等。

(2)拦截器(Interceptor):是spring框架实现的功能,在实现上是基于Java的反射机制,一个拦截器实例在一个controller生命周期之内可以多次调用。只能对controller定义的方法进行拦截,但是对静态资源的请求则没办法进行拦截处理。

(3)切片(Aspect):即spring的AOP功能,面向切面编程,使用时需要引入 aop 依赖。定义切入点(在哪些方法起作用、什么时候起作用)以及在切入点执行的方法。

2、区别:

  1. 执行顺序:Filter 、Interceptor、Aspect的执行顺序为:Filter  -> Interceptor -> Aspect
  2. 获取的信息:Filter 在controller(方法)前调用,只能获取到请求和响应,不知道在那个控制器、方法处理,所以不能获取到调用的方法名,方法参数等信息(因为其为servlet定义,不知道spring定义的东西);Interceptor 能获取到方法名但无法获取到方法参数,可以看源码是因为controller方法的方法参数是在调用 Interceptor 后才设置进去的;Aspect 可以获取到方法名称、方法参数等信息。
  3. 使用:自定义Filter 需要实现 Filter 接口并加上@Component注解就会被容器注入bean进行使用;自定义Interceptor 需要实现HandlerInterceptor 接口并加上@Component注解,同时还要写一个实现 WebMvcConfigurer 接口的bean,在该bean中重写addInterceptors方法,方法中需要讲自定义的 Interceptor  加入InterceptorRegistry;自定义Aspect 需要在类上加 @Component、@Aspect两个注解,同时编写切面方法,在方法上添加对应注解表达在哪里执行,执行的节点等信息。
  4. 异常获取:如果项目中加了 @ControllerAdvice的统一异常处理器,则顺序变为 Filter  -> Interceptor -> ControllerAdvice ->Aspect -> controller。即controller抛出异常后只有Aspect 能够获取到异常信息,之后异常信息就被 ControllerAdvice 获取并进行统一的处理,而 Filter 、 Interceptor 无法直接获取到 controller抛出的异常信息

二、使用

1、过滤器

  1. //过滤器名称为loginFilter,拦截/desktop,/hello的请求
  2. //使用@Order是没办法控制多个过滤器顺序的,只能使用 FilterRegistrationBean
  3. @WebFilter(filterName="loginFilter",urlPatterns={"/desktop","/hello/*"})
  4. //@Component
  5. public class LoginFilter implements Filter
  6. {
  7. @Override
  8. public void init(FilterConfig filterConfig) throws ServletException {
  9. System.out.println("filter初始化");
  10. }
  11. @Override
  12. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  13. throws IOException, ServletException {
  14. System.out.println("=====进去filter");
  15. //设置request请求编码等
  16. request.setCharacterEncoding("UTF-8");
  17. response.setCharacterEncoding("UTF-8");
  18. chain.doFilter(request, response); //传给下一个过滤器
  19. }
  20. @Override
  21. public void destroy() {
  22. // TODO Auto-generated method stub
  23. }
  24. }

当有多个过滤器,且需要控制其执行顺序时,过滤器注释掉 @WebFilter,改为@Component

然后在启动类(获取其他@Configuration注解的bean)写如下代码

  1. @Autowired
  2. private LoginFilter loginFilter;
  3. @Bean
  4. public FilterRegistrationBean filterRegistrationBean(){
  5. FilterRegistrationBean registrationBean = new FilterRegistrationBean();
  6. registrationBean.setFilter(loginFilter);
  7. registrationBean.setName("loginFilter");
  8. registrationBean.addUrlPatterns("/face/*");
  9. registrationBean.setOrder(3); //order越小越先执行
  10. return registrationBean;
  11. }

2、拦截器

定义拦截器实现类,实现 HandlerInterceptor

  1. @Component
  2. public class LoginInterceptor implements HandlerInterceptor
  3. {
  4. @Override
  5. public boolean preHandle(HttpServletRequest request ,
  6. HttpServletResponse response, Object handler)throws Exception{
  7. System.out.println("========拦截");
  8. //获取类名
  9. ((HandlerMethod)handler).getBean().getClass().getName();
  10. //获取方法名
  11. ((HandlerMethod)handler).getMethod().getName();
  12. System.out.println(request.getContentType());
  13. return true; //返回false则controller的方法不会执行
  14. }
  15. @Override
  16. public void postHandle(HttpServletRequest request,
  17. HttpServletResponse response, Object handler, ModelAndView model)throws Exception{
  18. //处理请求完成后视图渲染之前的处理操作,controller异常则不执行
  19. }
  20. @Override
  21. public void afterCompletion(HttpServletRequest request,
  22. HttpServletResponse response, Object handler, Exception e)throws Exception{
  23. //视图渲染之后的处理操作,controller异常仍执行
  24. }
  25. }

需要在实现WebMvcConfigurer类中加入该拦截器,拦截器才能生效

  1. @Configuration
  2. public class Webconfigurer implements WebMvcConfigurer
  3. {
  4. @Autowired
  5. private LoginInterceptor loginInterceptor;
  6. //拦截除 /login /register 外的所有请求
  7. @Override
  8. public void addInterceptors(InterceptorRegistry registry) {
  9. registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login","/register");
  10. }
  11. }

3、Aspect

定义切片实现类,添加@Aspect注解

  1. @Aspect
  2. @Component
  3. public class MyAspect {
  4. @Around("execution(* com.example.security.controller.HelloController.*(..))")
  5. public Object handleAspect(ProceedingJoinPoint pjp) throws Throwable {
  6. Object[] args = pjp.getArgs();
  7. //打印方法中的所有参数
  8. Arrays.stream(args).forEach(System.out::println);
  9. //调用对应切入点的方法
  10. Object o = pjp.proceed();
  11. return null;
  12. }
  13. }

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号