继承HttpServletRequestWrapper的类:
public class MyRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public MyRequestWrapper(HttpServletRequest request) throws Exception {
super(request);
this.body = HttpUtil.readRequestBody(request);
}
public String getBody() {
return body;
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read(){
return bais.read();
}
};
}
@Override
public BufferedReader getReader(){
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
filter代码 :
@WebFilter(filterName = "middlewareFilter", urlPatterns = "/device_middleware/*")
public class MiddlewareFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(MiddlewareFilter.class);
private MiddlewareService middlewareService = null;
private TDeviceService deviceService = null;
private Map<String, Timer> middlewareTimerMap = new HashMap<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("------> 开始校验");
}
@SneakyThrows
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
logger.info("-----------------------> middleware request: " + ((HttpServletRequest) request).getRequestURL().toString());
MyRequestWrapper myRequestWrapper = new MyRequestWrapper((HttpServletRequest)request);
String body = myRequestWrapper.getBody();
logger.info("body :" + StringUtil.subLogString(body));
chain.doFilter(myRequestWrapper, response);
}
@Override
public void destroy() {
logger.info("<------校验结束");
}
}
遇事不决,量子力学
使用上面的filter过滤参数之后@Requestbody收到的数据出现中文乱码,在部分设备上部署的时候又没有出现乱码,使用的是一样的tomcat和jdk,我至今还未知道是说明原因所致,只能归结为量子力学的问题😁。
问题分析:
1、当初为什么要使用wrapper呢?因为如果直接request中的数据取出来化,在controller中就取不到数据了。
2、猜测wrapper中重新new了一个SeverletRequest对象,然后把这个对象给controller取数据,这样在filter中取request的数据就不会对controller造成影响。基于这个猜测,我在filter中把wrapper的数据也取出来,理论上controller会取不到数据。然而结果并非如此,controller仍然正常可以取到数据,只不过中文仍然是乱码,说明事实并非我之预想。由此可见,controller中的数据是另外提供的,应该不在wrapper的request中。
3、基于第二点的结果,查看HttpServletRequestWrapper的代码,有一个函数是:
getInputStream,在这个函数中,获取了body的数据,基本上可以判定,controller的数据是从通过这个函数获取,那么编码乱码问题应该也是出现在这里。
4、在获取body的数据时指定UTF-8编码:
final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes("UTF-8"));
重新运行程序,发送请求,controller获取中文正常!