最近遇到测试环境和生成环境参数解析结果不一样的问题,最后发现是日志级别导致的,写个简单的demo记录下。
测试方法:
@PostMapping("test")
public String test(HttpServletRequest request) throws Exception{
InputStream inputStream = request.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null){
sb.append(line);
}
System.out.println(sb.toString());
return sb.toString();
}
传参方式为application/x-www-form-urlencoded,
在spring日志级别大于DEBUG时,可以正常解析出参数,测试环境日志级别为DEBUG时,无法获取到参数。
原因
在debug打开时,DispatcherServlet对请求参数进行了解析并打印:
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
........
}
private void logRequest(HttpServletRequest request) {
LogFormatUtils.traceDebug(logger, traceOn -> {
String params;
if (isEnableLoggingRequestDetails()) {
params = request.getParameterMap().entrySet().stream()
.map(entry -> entry.getKey() + ":" + Arrays.toString(entry.getValue()))
.collect(Collectors.joining(", "));
}
......
在debug打开时,会调用request.getParameterMap(),会对参数进行解析,在tomcat的Request的parseParameters方法中,对于application/x-www-form-urlencoded传参的POST,会读取Body的数据来解析:
protected int readPostBody(byte[] body, int len)
throws IOException {
int offset = 0;
do {
int inputLen = getStream().read(body, offset, len - offset);
if (inputLen <= 0) {
return offset;
}
offset += inputLen;
} while ((len - offset) > 0);
return len;
}
而BIO中InputStream是单向的,无法重复读取,所以在方法中再读是读不到的。
由此可见,即使是简单的日志级别的不同,也可能引起业务逻辑的不一样。测试环境最好和正式环境一模一样,才能尽可能提前发现问题。
网友评论