解决 HttpServletRequest 流数据不可重复读

为了解决在处理HttpServletRequest时遇到的流数据只能读取一次的问题,本文介绍了背景及问题,提出了一种解决方案:通过封装ContentCachingRequestWrapper和ContentCachingResponseWrapper类,并在过滤器LogFilter中使用这些包装类,实现请求参数的多次读取。同时,SpringBoot启动类需添加@ServletComponentScan注解以识别过滤器。
摘要由CSDN通过智能技术生成

背景介绍

甲方客户的生产系统,有安全风险预警和安全事件快速溯源要求,需要做一套日志管理规范。

要求我们接入的系统,要对用户登录、注册、密码修改等重要场景,严格按照提供的格式,输出相应的日志。

后续通过filebeat对接,收集我们系统上的日志信息。

简单来说,就是应用系统,处理接口请求时,统一打印相应日志。

问题描述

成熟且常见的日志统一打印方案,就是使用AOP技术,自定义注解,在切面上使用环绕通知@Around,拦截请求,获取Controller类上方法的入参、出参即可。

奈何业务场景使用到的接口,以前的人在实现的时候,使用了如下方式:

@RequestMapping(value = "/auth", method = {
    RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS })
public void auth(HttpServletRequest req, HttpServletResponse resp) {
   
   authService.auth(req, resp);
}

把传参直接丢在 HttpServletRequest 中。

返回参数,又是采用 HttpServletResponse 输出。

public void printResult(HttpServletRequest req, HttpServletResponse resp,
      String action, int code, String msg, Object result) {
   
   PrintWriter p = null;
   Ret ret = new Ret();
   Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
         .serializeNulls()
         .create();
   try {
   
      p = resp.getWriter();
      ret.setRspCode(code);
      ret.setRspDesc(msg);
      ret.setData(result);

      p.write(gson.toJson(ret));
      return;
   } catch (Exception e) {
   
      logger.error(e.getMessage());
   } finally {
   
      p.flush();
      p.close();
   }
}

不像平时熟练的做法,把具体入参和出参,用对象封装,直接放在方法上即可。

因为上面的做法,导致我们在拦截器中,想提前拦截请求获取传参,使用 request.getParameter() 等方法时,能拿到参数。
但是在具体接口业务流程中,再使用request.getParameter() 等方法,传入参数就获取不到了。

因为流只能被读一次

因此就抛出一个问题:Request 和 Response 怎么重复读取?

解决方案

使用request.getPar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值