過濾器、攔截器、AOP、ControllerAdvcie執行順序對比

licwuu發表於2024-08-10

0. 執行順序

過濾器 ➡ 攔截器 ➡ AOP ➡ ControllerAdvice ➡ Controller

執行順序

沒有異常的情況下,執行順序如下:
沒有異常

有異常的情況下,執行順序如下:
有異常

tip: 當產生異常後,無論是否有ControllerAdvice處理,HandlerInterceptor都不會執行postHandle方法, 直接執行afterCompletion方法。

1. 過濾器

過濾器是Servlet規範中的一部分,它依賴於Servlet容器,因此只能在web程式中使用。過濾器可以攔截到客戶端傳送的請求和伺服器響應的內容,對它們進行過濾處理,比如實現URL級別的許可權控制、過濾敏感詞彙、壓縮響應資訊等。

透過filterChain.doFilter(req, resp);可以看出Filter是基於責任鏈模式的。

package com.licw.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;

@Slf4j
@Component
public class WebFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
        log.info("filter: before");
        filterChain.doFilter(req, resp);
        log.info("filter: after");
    }
}

2. 攔截器

攔截器是依賴於Spring框架的,因此只能在Spring MVC中使用。攔截器是基於代理實現的。

// 攔截器
package com.licw.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("all")
@Slf4j
@Component
public class WebInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        log.info("interceptor: before");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest req, HttpServletResponse resp, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("interceptor: after");
    }

    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse resp, Object handler, Exception ex) throws Exception {
        log.info("interceptor: after completion");
    }
}
// 配置攔截器
package com.licw.config;

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 WebInterceptor())
    .addPathPatterns("/**");
 }
 
}

3. AOP

AOP是面向切面程式設計,它可以在不修改原始碼的情況下,透過動態代理的方式,在方法呼叫前後執行一些操作。AOP可以用於實現日誌記錄、事務管理、許可權控制等功能。

// AOP
package com.licw.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Slf4j
@Aspect
@Component
public class WebAop {
    @Around("execution(* com.licw.controller.BasicController.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("aop: before");
        try {
            return proceedingJoinPoint.proceed();
        } finally {
            log.info("aop: after");
        }
    }

}

4. ControllerAdvice

ControllerAdvice是Spring MVC提供的一種全域性異常處理機制,它可以定義在全域性範圍內處理Controller中的異常。ControllerAdvice是依賴於Spring MVC的,因此只能在Spring MVC中使用。

package com.licw.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {

    @ExceptionHandler(Exception.class)
    public String allExceptionHandler(Exception e) {
        log.info("RestControllerAdvice: {}", e.getMessage());
        return "系統異常,請稍後再試";
    }

}

相關文章