背景介绍
甲方客户的生产系统,有安全风险预警和安全事件快速溯源要求,需要做一套日志管理规范。
要求我们接入的系统,要对用户登录、注册、密码修改等重要场景,严格按照提供的格式,输出相应的日志。
后续通过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