我有一个 SpringBoot 2.6.14 WebApp,我正在使用 Spring
OncePerRequestFilter
来记录有关 HTTP 请求和响应的一些信息。
代码类似于以下代码:
@Slf4j(topic = "logger")
public class LoggingFilter extends OncePerRequestFilter {
private final ObjectMapper mapper;
public LoggingFilter(ObjectMapper mapper) {
super();
this.mapper = mapper;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
......
}
我设法记录 uri、请求类型(GET、POST ecc..)、主机和其他一些有用的信息,但我无法检索
Controller
签名,或只是名称。谷歌搜索后我发现我可以用 HandlerInterceptor
来实现这一点,但我必须使用过滤器。
例如,如果我有一个像下面这样的
Controller
:
@RestController
@RequestMapping("/api/v1")
public class SomeController {
@GetMapping("/all")
public ResponseEntity<List<Some>> findAll() {
List<Some> result = service.findAll();
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
我称之为我可以检索路径
/api/v1/all
,但我什至想获得findAll()
方法名称。
没有
HandlerInterceptor
可以吗?
不过这是可能的! 这是我的完整解决方案..
过滤器类配置:
@Configuration
public class FilterConfig {
@Bean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
FilterRegistrationBean<LoggingFilter> logFilter(DispatcherServlet dispatcher) {
FilterRegistrationBean<LoggingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new LoggingFilter(dispatcher));
registrationBean.addUrlPatterns("/api/v1/test/*");
registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE);
return registrationBean;
}
}
过滤器:
@Slf4j(topic = "filter")
public class LoggingFilter extends OncePerRequestFilter {
private final DispatcherServlet dispatcher;
public LoggingFilter(DispatcherServlet dispatcher) {
super();
this.dispatcher = dispatcher;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
......
filterChain.doFilter(requestWrapper, responseWrapper);
ServletRequestPathUtils.parseAndCache(request);
List<HandlerMapping> mapping = dispatcher.getHandlerMappings();
List<HandlerExecutionChain> chain = new ArrayList<>();
mapping.forEach(item -> {
try {
HandlerExecutionChain c = item.getHandler(requestWrapper);
chain.add(c);
} catch (Exception e) {
log.error(e);
}
});
List<HandlerExecutionChain> resource = chain.stream().filter(i -> i != null).collect(Collectors.toList());
HandlerExecutionChain hEc = resource.stream().findFirst().orElse(null);
HandlerMethod handlerMethod = (HandlerMethod) hEc.getHandler();
Method method = handlerMethod.getMethod(); // All INFO about the method called by request
log.info(method.getName()); // method name
......
responseWrapper.copyBodyToResponse();
}
也许不完全兼容,但如果您无法注册拦截器,这是实现结果的一种方法。
希望有帮助。