在项目中需要使用过滤器 在请求调用 Controller 方法前修改请求参数和在结果返回之前修改返回结果。
在 Controller 中定义如下接口:
@PostMapping("/hello")
public JSONObject hello(@RequestBody Map<String, Object> params) {
return JSONObject.parseObject(JSON.toJSONString(params));
}
定义的过滤器如下:
public class ServNoFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
// 获取请求体内容
String requestBody = getRequestBody(httpServletRequest);
// 业务处理
......
// 放行
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
private String getRequestBody(HttpServletRequest request) throws IOException {
BufferedReader reader = new BufferedReader(request.getReader());
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
}
此时启动项目,访问接口,则会在控制台打印如下异常信息:Request processing failed; nested exception is java.lang.IllegalStateException: getReader() has already been called for this request
。
表示在过滤器中已经通过 request.getReader()
方法将请求流读取。
如果在过滤器中将 getReader()
换成 getInputStream()
就会报请求体为空异常:org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing
。
这是因为在 Servlet 中,请求对象的输入流只能被读取一次。而在第一次读取请求体时,Servlet 容器会将请求体保存在内存中,并将其解析成相应的请求参数和请求头信息。如果在后续的处理中再次读取请求体,就可能会导致数据错误或异常。