• Spring MVC记录传入请求


    1. 简介

    在本教程中,我们将研究如何使用Spring MVC记录传入的请求。

    2. 示例应用程序

    让我们首先看一下我们的示例应用程序。

    1. @RestController
    2. public class ContactController {
    3. @PostMapping("/contact/{name}")
    4. public String contact(@PathVariable("name") String name, @RequestBody String details) {
    5. return "Contact details received for: " + name;
    6. }
    7. }

    我们有一个简单的 REST 控制器,其中包含单个端点 -/contact/{name}。在接下来的示例中,我们将针对此终结点发出请求。

    3. 自定义实现

    现在,我们将探索一些自定义实现来记录传入的 HTTP 请求。

    3.1. 使用处理程序拦截器

    HandlerInterceptor类为我们提供了在请求处理之前和之后运行的钩子。因此,我们将使用这些方法来记录请求数据:

    1. @Slf4j
    2. @Component
    3. public class CustomRequestLoggingInterceptor extends HandlerInterceptorAdapter {
    4. @Override
    5. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    6. StringBuffer requestURL = request.getRequestURL();
    7. log.info("preHandle => Request URL: {}", requestURL);
    8. return true;
    9. }
    10. @Override
    11. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    12. int status = response.getStatus();
    13. log.info("afterCompletion => Response Status: {}", status);
    14. }
    15. }

    我们的CustomRequestLoggingInterceptor类扩展了 HandlerInterceptorAdapter,它是一个实现HandlerInterceptor的抽象类。请注意,preHandle将在请求处理之前运行,afterCompletion将在请求处理完成后运行。

    现在我们有了HandlerInterceptor,我们必须使用WebMvcConfigurerbean 注册它:

    1. @Component
    2. public class WebMvcConfiguration implements WebMvcConfigurer {
    3. @Override
    4. public void addInterceptors(InterceptorRegistry registry) {
    5. registry.addInterceptor(new CustomRequestLoggingInterceptor());
    6. }
    7. }

    当应用程序收到请求时,我们的CustomRequestLoggingInterceptor类也会被调用:

    1. INFO 27115 --- [nio-8081-exec-1] .j.s.m.r.CustomRequestLoggingInterceptor : preHandle => Request URL: http://localhost:8081/contact/John
    2. INFO 27115 --- [nio-8081-exec-1] .j.s.m.r.CustomRequestLoggingInterceptor : afterCompletion => Response Status: 200

    3.2. 使用过滤器

    过滤器在 servlet 之前和之后运行,因此它适用于记录请求。在我们的例子中,servlet 是 Spring MVC 的DispatcherServlet,它处理所有传入的请求。

    1. @Slf4j
    2. @Component
    3. public class CustomRequestLoggingFilter extends GenericFilterBean {
    4. @Override
    5. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
    6. throws IOException, ServletException {
    7. final HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
    8. final HttpServletResponse currentResponse = (HttpServletResponse) servletResponse;
    9. StringBuffer requestURL = currentRequest.getRequestURL();
    10. log.info("Request URL: {}", requestURL);
    11. try {
    12. chain.doFilter(currentRequest, servletResponse);
    13. } finally {
    14. int status = currentResponse.getStatus();
    15. log.info("Response status: {}", status);
    16. }
    17. }
    18. }

    在这里,实际的请求处理发生在chain.doFilter调用中。换句话说,DispatcherServlet获取请求并选择适当的控制器方法。因此,我们在过滤器中编写此调用之前和之后的日志语句。

    此外,我们可以使用FilterRegistrationBean 配置过滤器的注册属性,尽管我们在这里选择了默认值。

    当应用程序为请求提供服务时,将写入以下日志:

    1. INFO 5835 --- [nio-8081-exec-1] c.j.s.m.r.CustomRequestLoggingFilter : Request URL: http://localhost:8081/contact/John
    2. INFO 5835 --- [nio-8081-exec-1] c.j.s.m.r.CustomRequestLoggingFilter : Response status: 200

    4. 弹簧 MVC 支持

    Spring MVC内置了对日志记录请求的支持,我们接下来将对此进行研究。

    4.1. 使用共享资源请求日志记录过滤器

    Spring MVC提供了CommonsRequestLoggingFilter,它可以记录请求URL,正文和其他相关信息

    要在应用程序中使用它,我们必须首先为它定义一个 bean:

    1. @Bean
    2. public CommonsRequestLoggingFilter requestLoggingFilter() {
    3. CommonsRequestLoggingFilter requestLoggingFilter = new CommonsRequestLoggingFilter();
    4. requestLoggingFilter.setIncludeClientInfo(true);
    5. requestLoggingFilter.setIncludeHeaders(true);
    6. requestLoggingFilter.setIncludeQueryString(true);
    7. requestLoggingFilter.setIncludePayload(true);
    8. return requestLoggingFilter;
    9. }

    在这里,我们正在创建一个CommonsRequestLoggingFilter的实例,并为丰富的日志语句启用所有包含选项。

    然后,我们将筛选器的日志级别更改为DEBUG。我们可以使用application.properties 来做到这一点:

    logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG

    当新请求到达时,筛选器会提供日志:

    1. DEBUG 27115 --- [nio-8081-exec-1] o.s.w.f.CommonsRequestLoggingFilter : Before request [uri=/contact/John;client=127.0.0.1;headers=[accept:"text/plain, application/json, application/*+json, */*", content-type:"text/plain;charset=UTF-8", user-agent:"Java/1.8.0_191", host:"localhost:8081", connection:"keep-alive", content-length:"15"]]
    2. DEBUG 27115 --- [nio-8081-exec-1] o.s.w.f.CommonsRequestLoggingFilter : After request [uri=/contact/John;client=127.0.0.1;headers=[accept:"text/plain, application/json, application/*+json, */*", content-type:"text/plain;charset=UTF-8", user-agent:"Java/1.8.0_191", host:"localhost:8081", connection:"keep-alive", content-length:"15"];payload=London, England]

    4.2. 扩展抽象请求日志记录过滤器

    除了使用CommonsRequestLoggingFilter,我们还可以创建自己的过滤器来扩展AbstractRequestLoggingFilter。事实上,CommonsRequestLoggingFilter也是AbstractRequestLoggingFilter 的实现。

    1. @Component
    2. public class AnotherCustomLoggingFilter extends AbstractRequestLoggingFilter {
    3. @Value("${request.logging.shouldLog}")
    4. private boolean shouldLog;
    5. public AnotherCustomLoggingFilter(){
    6. setIncludeClientInfo(true);
    7. setIncludeHeaders(true);
    8. setIncludePayload(true);
    9. setIncludeQueryString(true);
    10. setBeforeMessagePrefix("Request started => ");
    11. setAfterMessagePrefix("Request ended => ");
    12. }
    13. @Override
    14. protected boolean shouldLog(HttpServletRequest request) {
    15. return shouldLog;
    16. }
    17. @Override
    18. protected void beforeRequest(HttpServletRequest request, String message) {
    19. logger.info(message);
    20. }
    21. @Override
    22. protected void afterRequest(HttpServletRequest request, String message) {
    23. logger.info(message);
    24. }
    25. }

    在这里,我们有OtherCustomLoggingFilter它实现了 3 个方法:shouldLogbeforeRequestafterRequest

    我们使用应用程序属性 -request.logging.shouldLog 启用日志记录行为。在beforeRequestafterRequest方法中,我们只是记录消息,尽管我们也可以执行更复杂的操作。最后,我们在构造函数中启用包含选项。

    日志输出与CommonsRequestLoggingFilter 非常相似:

    1. INFO 5835 --- [nio-8081-exec-1] c.j.s.m.r.AnotherCustomLoggingFilter : Request started => uri=/contact/John;client=127.0.0.1;headers=[accept:"text/plain, application/json, application/*+json, */*", content-type:"text/plain;charset=UTF-8", user-agent:"Java/1.8.0_191", host:"localhost:8081", connection:"keep-alive", content-length:"15"]
    2. INFO 5835 --- [nio-8081-exec-1] c.j.s.m.r.AnotherCustomLoggingFilter : Request ended => uri=/contact/John;client=127.0.0.1;headers=[accept:"text/plain, application/json, application/*+json, */*", content-type:"text/plain;charset=UTF-8", user-agent:"Java/1.8.0_191", host:"localhost:8081", connection:"keep-alive", content-length:"15"];payload=London, England

    5. 总结

    在本教程中,我们研究了使用 Spring MVC 记录传入请求的不同方法。

    Github 上查看本教程中所有示例的源代码。

  • 相关阅读:
    Java面试题目大汇总(附参考答案)
    EL 与 JSTL(1)( EL 表达式基础知识)
    【五月集训】—— 汇聚星球,算法锤炼,集中一点,登峰造极
    云原生开发:从容器到微服务的全栈指南
    尚好房 11_Session共享
    Android StringFog 字符串自动加密
    建造者模式/生成器模式
    Chapter7:非线性控制系统分析
    跨域的MPLS VXN Option C
    编译安装MySQL服务(LAMP2)
  • 原文地址:https://blog.csdn.net/allway2/article/details/127976947