Springboot中的过滤器、拦截器、切片

2019-03-03  本文已影响0人  _薯条

自定义过滤器(filter)

//@Component
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("my filter init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("my filter start");
        long start = new Date().getTime();
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("my filter 耗时:" + (new Date().getTime() - start));
        System.out.println("my filter finish");
    }

    @Override
    public void destroy() {
        System.out.println("my filter destroy");
    }
}

自定义的filter可以不加上@Componet注解,就比如我们开发中经常需要增加第三方的过滤器,但是引入的第三方包里的过滤器又不能修改源码,在以前ssm框架中开发时,可以将filter配置在web.xml文件中,而Springboot中并没有web.xml文件,所以需要单独写配置文件配置:

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean timeFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        MyFilter myFilter = new MyFilter();
        filterRegistrationBean.setFilter(myFilter);
        // 设置MyFile在指定url起作用
        List<String> urlList = new ArrayList<>();
        urlList.add("/*");
        filterRegistrationBean.setUrlPatterns(urlList);
        return filterRegistrationBean;
    }

}

使用配置文件配置我们自己写的filter时,可以配置filter在指定的url生效,如果直接使用@Compnent注解,则filter在所有的的url都生效。

自定义拦截器(interceptor)

@Component
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        request.setAttribute("startTime", new Date().getTime());
        System.out.println(((HandlerMethod) handler).getBean().getClass().getName());  // 获取处理请求的类名称
        System.out.println(((HandlerMethod) handler).getMethod().getName());  // 获取处理请求的方法名
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
        long startTime = (long) request.getAttribute("startTime");
        System.out.println("my interceptor 耗时:" + (new Date().getTime() - startTime));
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion");
        long startTime = (long) request.getAttribute("startTime");
        System.out.println("my interceptor 耗时:" + (new Date().getTime() - startTime));
        System.out.println("ex is " + e);
    }

}

自定义拦截器后,还需要单独写配置文件进行配置:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private MyInterceptor myInterceptor;

    // 重写WebMvcConfigurerAdapter类的addInterceptors方法,添加自己的拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor);
    }

}

切片(aspect)

引入maven依赖:

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
@Component
public class MyAspect {

    @Around("execution(* com.sinosoft.controller.UserController.*(..))")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("my aspect start");
        Object[] args = pjp.getArgs();  // 获取到方法参数的值
        for (Object arg : args) {
            System.out.println("arg is " + arg);
        }
        long startTime = new Date().getTime();
        Object object = pjp.proceed();
        System.out.println("my aspect 耗时:" + (new Date().getTime() - startTime));
        System.out.println("my aspect end");
        return object;
    }

}

定义过滤器、拦截器、切片后运行结果,测试其执行顺序:

my filter start
preHandle
com.sinosoft.controller.UserController$$EnhancerBySpringCGLIB$$89062ea2
getInfo
my aspect start
arg is “自己输入的参数”
进入controller服务   // controller调用方法中打印
my aspect 耗时:2
my aspect end
postHandle
my interceptor 耗时:41
afterCompletion
my interceptor 耗时:41
ex is null
my filter 耗时:55
my filter finish

从执行结果可以看出,执行顺序如图:

执行顺序图

总结:

1、过滤器能够拿到原始的http请求和响应的信息,但是拿不到真正处理请求的方法的信息;
2、拦截器既能拿到原始的http请求和响应的信息,也能拿到真正处理请求的方法的信息,但是拿不到方法被调用的时候,那个被调用方法的参数的值;
3、切片可以拿到方法被调用的时候,方法参数传进来的值,但是拿不到原始的http请求和响应的对象。

上一篇下一篇

猜你喜欢

热点阅读