【发布时间】:2021-07-05 13:13:47
【问题描述】:
我正在开发一个应用程序,该应用程序使用OncePerRequestFilter 使用传入的 Web 请求执行一些自定义的类似日志的行为。此行为同时使用HttpServletRequest 和HttpServletResponse。此外,过滤器同时使用ContentCachingRequestWrapper 和ContentCachingResponseWrapper 来访问请求/响应正文。
我们决定只在调用特定 Spring 控制器的方法时才执行此行为,因为我们不想为其他控制器/执行器端点/等执行此操作。有没有办法判断传入的请求是否会(或曾经)映射到控制器?
public class ExampleFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
// Can I tell here whether this will be mapping to an endpoint in
// ExampleController or NestedExampleController?
ContentCachingRequestWrapper requestToUse = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseToUse = new ContentCachingResponseWrapper(response);
try {
filterChain.doFilter(requestToUse, responseToUse);
// Can I tell here whether this was mapped to an endpoint in
// ExampleController or OtherExampleController?
} finally {
responseToUse.copyBodyToResponse(); // Write the cached body back to the real response
}
}
}
@RestController
@RequestMapping("/example")
public class ExampleController {
@GetMapping("/{id}")
public Example retrieveExample() {
return getValue(); // Retrieve the value
}
// ...
}
@RestController
@RequestMapping("/example/{id}/nested")
public class NestedExampleController {
@GetMapping("/{nestedId}")
public NestedExample retrieveNestedExample() {
return getValue(); // Retrieve the value
}
// ...
}
我已经对 Spring MVC/Boot 内部进行了一些研究,但我不确定是否有一种方法可以轻松地做到这一点。作为替代方案,我可以进行一些手动 URL 模式匹配,这可能不一定与控制器中的方法完全匹配,但可能会让我足够接近以成为可接受的解决方案。
总结一下:网络过滤器中有没有办法判断传入的请求是映射到控制器(在执行过滤器链之前)还是映射到控制器(在执行过滤器链之后)?
【问题讨论】:
-
必须是特定的控制器类吗?说
@Controller类中的具体方法?从措辞来看,这听起来很容易解决,使用 AOP 和特定类的切面 + 切入点(或匹配方法,如果您需要更具体的话)。 -
我只需要特定的课程。
-
那么 AOP 应该可以很好地满足您的需求,尤其是因为您只想记录日志——这是最常见的用例之一。如果您愿意,我会在几分钟内写出答案。
-
您也可以通过
HandlerInterceptor、stackoverflow.com/questions/51352320/… 获取类,这不是您的确切请求,但可以使用它来告诉类/方法该请求已映射到 -
@DarrenForsythe 这看起来很有希望。我去看看。
标签: java spring spring-boot spring-mvc servlet-filters