markdown-it
demo
Delete
Submit
clear
permalink
OncePerRequestFilter 是Spring框架提供的一個過濾器類別,用於實現一次請求僅執行一次過濾的功能。這個過濾器可以在需要保證過濾器只執行一次的情況下使用。 使用 OncePerRequestFilter 需要繼承這個類別,並實現其中的 doFilterInternal() 方法。在 doFilterInternal() 方法中可以定義需要執行的過濾邏輯。 以下是一個簡單的 OncePerRequestFilter 範例: ```java import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @Order(1) @Component public class MyFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 在這裡實現過濾邏輯 // 呼叫 filterChain.doFilter() 繼續執行過濾器鏈 filterChain.doFilter(request, response); } } ``` 如果希望在某些條件下不執行過濾器,可以在 MyFilter 中重寫 shouldNotFilter() 方法,該方法返回 true 則表示不執行過濾器: ```java @Override protected boolean shouldNotFilter(HttpServletRequest request) { // 在這裡判斷是否不執行過濾器的條件 return true; } ``` 通過使用 OncePerRequestFilter,可以確保過濾器在一次請求中只執行一次,並且還可以根據不同的條件來控制過濾器的執行。 ### [Spring 攔截處理器](https://www.tpisoftware.com/tpu/articleDetails/1929) Filter ```java @WebFilter(filterName = "RequestFilter", urlPatterns = "/book") public class RequestFilter implements Filter { private static final Logger LOGGER = LoggerFactory.getLogger(RequestFilter.class); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { LOGGER.info("Request do filter ..."); chain.doFilter(request, response); } } ``` Interceptor ```java @Component public class DemoInterceptor implements HandlerInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(DemoInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { LOGGER.info("Interceptor do preHandle ..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { LOGGER.info("Interceptor do postHandle ..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { LOGGER.info("Interceptor do afterCompletion ..."); } } ``` ### AOP ```java @Aspect @Order(1) @Component public class ControllerAspect { private static final Logger LOGGER = LoggerFactory.getLogger(ControllerAspect.class); @Around(value = "within(@org.springframework.web.bind.annotation.RestController *)") public Object controllerAround(ProceedingJoinPoint jp) throws Throwable { LOGGER.info("Aop do controller around before method ..."); Object result = jp.proceed(); LOGGER.info("Aop do controller around after method ..."); return result; } @Pointcut("execution(* com.example.api.*.*(..))") // 替換成你的API包名和方法 public void apiMethods() {} @Before("apiMethods()") public void beforeApiMethod(JoinPoint joinPoint) { } } ``` @Around 注解用於定義環繞增強方法,即在目標方法執行前後都執行的方法。使用 @Around 可以完全控制目標方法的執行,可以在目標方法執行之前進行一些前置處理,並在執行之後進行後置處理。在 @Around 注解的方法內部,你可以通過調用 ProceedingJoinPoint.proceed() 方法來執行目標方法。 @Pointcut 注解應用於一個方法上,該方法的內容可以是一個切點表達式,也可以是一個命名的切點,以便在其他切面中引用。使用 @Pointcut 可以將切點的定義集中在一個地方,以便在不同的切面中重複使用。 @Before 注解用於定義在目標方法執行之前應該執行的增強方法。當目標方法被調用之前,@Before 指定的方法將被執行。這種增強方法通常用於進行一些前置處理操作。 * execution(* com.example.service.*.*(..)): 匹配 com.example.service 包中的所有類的任意方法。 * execution(public * com.example.service.UserService.*(..)): 匹配 com.example.service.UserService 類中的所有公開方法。 * execution(* save*(..)): 匹配方法名以 "save" 開頭的所有方法。 * within(com.example.repository.*): 匹配 com.example.repository 包中的所有方法。 * args(java.lang.String): 匹配接受一個 String 參數的方法。 * @annotation(org.springframework.web.bind.annotation.GetMapping): 匹配標註有 @GetMapping 註解的方法。
html
source
debug
Fork me on GitHub