【springboot】過濾器、監聽器、攔截器,Aspect切片


轉自:

  https://blog.csdn.net/cp026la/article/details/86501019

簡介:

  本章介紹攔截器、過濾器、切片對請求攔截的使用與區別,以及監聽器在 springboot1.5 中的簡單使用

過濾器、攔截器、切片攔截請求的對比:

相同點: 都可以對請求進行攔截。
不同點:
1、過濾器對請求的攔截只能獲取到原始的Request 和 Response 的信息。
2、攔截器對請求的攔截可以獲取原始的Request、Response和所有的controller及方法名,但無法獲取方法的參數信息。
3、Aspect切片只能獲取方法的參數,原始的Request、Response不能獲取。

所以,實際項目需根據需求選擇使用何種方式攔截請求。

一、過濾器:

1、實現Filter接口

/**
 * @Auther: xf
 * @Date: 2018/11/19 19:30
 * @Description: 自定義過濾器
 *
 * Filter 只能獲取request 和 response 並不知道請求是哪個 controller 處理的
 */
@Slf4j
public class CustomFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("過濾器初始化>>>>>>>");
    }

    /**
     * 請求被攔截的時候進行調用
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info(">>>>>>>>>>>>過濾器攔截請求處理邏輯>>>>>>>>>>>>>");

        // 業務邏輯
        long startTime = System.currentTimeMillis();

        // 過濾器鏈,給下一個過濾器
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("請求時間:" + (System.currentTimeMillis() - startTime));
    }

    @Override
    public void destroy() {
        log.info("過濾器銷毀>>>>>>>");
    }
}  

 

2、過濾器配置類:

傳統的web項目中,過濾器的配置是在web.xml中添加。SpringBoot需要使用FilterRegistrationBean來完成配置。

/**
 * @Auther: xf
 * @Date: 2018/11/19 19:58
 * @Description:  傳統的項目配置 Filter 在 web.xml 中添加
 * 在Spring boot中,我們需要 FilterRegistrationBean 來完成配置
 */
@Configuration
public class CustomFilterConfig {
    @Bean
    public FilterRegistrationBean customFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new CustomFilter());
        registration.addUrlPatterns("/*");
        registration.setName("customFilter");
        registration.setOrder(1);
        return registration;
    }
}  


3、啟動項目,隨便請求一個接口測試效果:

控制台有攔截器的日志。

4、配置過濾器的方式二:

直接通過@WebFilter注解配置(注釋掉上面的CustomFilterConfig配置類)

@Slf4j
// 多個過濾器,使用此注解指定執行順序,越小越先執行
@Order(1)
// 在 CustomFilterConfig 中配置  注釋掉 @WebFilter
@WebFilter(urlPatterns = "/*", filterName = "customFilter")
public class CustomFilter implements Filter {
    ...
}  

注意:
@WebFilter 是Servlet3.0 的規范,並不是SpringBoot提供的,需加上@ServletComponentScan注解掃描指定的包。我們這里加到啟動類上。

// filter和servlet、listener之類的需要單獨進行注冊才能使用,spring boot里面提供了該注解起到注冊作用
@ServletComponentScan
// mapper 接口類掃描包配置
@MapperScan("com.coolron.*.dao")
@SpringBootApplication(scanBasePackages = "com.coolron")
public class SpringbootApplication {
    ...
}  


二、攔截器:

1、自定義攔截器1:

@Slf4j
public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  throws Exception {
        log.info(">>>MyInterceptor1>>>>>>>在請求處理之前進行調用(Controller方法調用之前)");
        return true;// 只有返回true才會繼續向下執行,返回false取消當前請求
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info(">>>MyInterceptor1>>>>>>>請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后)");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        log.info(">>>MyInterceptor1>>>>>>>在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)");
    }
}  

2、自定義攔截器2:

/**
 * 自定義攔截器2
 */
@Slf4j
public class MyInterceptor2 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        log.info(">>>MyInterceptor2>>>>>>>在請求處理之前進行調用(Controller方法調用之前)");
        return true;// 只有返回true才會繼續向下執行,返回false取消當前請求
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info(">>>MyInterceptor2>>>>>>>請求處理之后進行調用,但是在視圖被渲染之前(Controller方法調用之后)");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        log.info(">>>MyInterceptor2>>>>>>>在整個請求結束之后被調用,也就是在DispatcherServlet 渲染了對應的視圖之后執行(主要是用於進行資源清理工作)");
    }
}

3、攔截器配置類:

/**
 * @Auther: xf
 * @Date: 2018/11/19 21:09
 * @Description:
 */
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
    /*
     * 攔截器配置
     * 在spring-mvc.xml配置文件內添加<mvc:interceptor>標簽配置攔截器。
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // 多個攔截器組成一個攔截器鏈
        // addPathPatterns 用於添加攔截規則
        // excludePathPatterns 用戶排除攔截
         registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").excludePathPatterns("/login");
         registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");
        // 父類的配置
        super.addInterceptors(registry);
    }
}  

三、Aspect切片攔截:

1、自定義切片:

/**
 * @Description:  
 * 可以拿到請求的具體controller 對應的方法的具體參數值  但是拿不到 原始的request 和 response
 *
 * 切入點(注解):
 * 1、 在哪些方法上起作用
 * 2、 什么時候起作用
 *
 * 增強(方法)
 * 1、起作用是執行的業務邏輯
 */
// 聲明切片類
@Slf4j
@Aspect
@Component
public class CustomAspect {

    // 在什么時候起作用
    // @Before() 相當於攔截器的 PreHandle() 方法
    // @After()  攔截的方法響應之后執行
    // @AfterThrowing 方法拋出某些異常的時候調用
    // @Around 環繞 覆蓋前面三種
    // 環繞的方式調用下面的方法
    @Around("execution(* com.coolron.*.controller..*.*(..))")
    // ProceedingJoinPoint 類 包含了當前攔截的方法的一些信息
    public Object method(ProceedingJoinPoint pjp) throws Throwable {
        log.info("=====Aspect處理=======");
        Object[] args = pjp.getArgs();
        for (Object arg : args) {
            log.info("參數為:" + arg);
        }
        long start = System.currentTimeMillis();
        // 相當於Filter 的 chain.doFilter()  調用被攔截的那個方法  返回值 object 與 controller中方法的返回值相同
        Object object = pjp.proceed();
        log.info("Aspect 耗時:" + (System.currentTimeMillis() - start));
        return object;
    }
}  

 

execution表達式參看SpringBoot>07 - 事物處理。

2、啟動訪問任意接口:

觀察控制台發現Filter、Interceptor、切片執行順序:

攔截順序 : Filter >>> Interceptor >>> Aspect >>> controller
若果有異常返回結果: controller >>> Aspect >>> ControllerAdvice(全局異常處理類上) >>> Interceptor >>> Filter

四、監聽器:

1、自定義監聽器,實現ServletRequestListener接口

/**
 * @Auther: xf
 * @Date: 2018/11/19 21:42
 * @Description:  監聽器
 */
@Slf4j
@WebListener
public class RequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        log.info("監聽器銷毀>>>>>");
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        log.info("監聽器初始化>>>>>");
    }
} 

 

2、測試:隨便請求一個接口會看到監聽器初始化和銷毀的日志。

注意:案例中實現的是request的監聽器。用於監聽request對象的創建、銷毀。
常見的監聽器:
1、HttpSessionListener:監聽session對象的創建、銷毀
2、ServletRequestListener:監聽request對象的創建、銷毀
3、ServletContextListener:監聽servletContext對象的創建、銷毀


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM