原开发需求
原需求是需要开发一个全局过滤器,需要对请求体重的内容进行过滤,如果出现特定字符需要阻拦请求。
实现
代码第一版对body数据的读取如下:
String data= req.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
出现问题:第一版对于body数据的读取没有问题,但是后续的请求都获取不到请求体的内容了,后面是了解到请求体内容只能读取一次,需要重写HttpServletRequestWrapper保存request中的inputStream内容。
代码第二版读取内容参考如下文章:添加链接描述
为了方便解释上诉文章部分核心代码会放到该文章中
构造函数中主要是:
isr = new BufferedReader(new InputStreamReader(ins));
char[] charBuffer = new char[1024];
int readCount = 0;
while ((readCount = isr.read(charBuffer)) != -1) {
sb.append(charBuffer, 0, readCount);
}
getReader
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream(),"ISO-8859-1"));
}
getInputStream
ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
具体body请求变成如下:
ServletRequest requestWrapper = new BodyReaderRequestWrapper(req);
String data = requestWrapper.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
出现问题:请求参数出现部分中文乱码,如果中文内容为双数,则正常,如果是单数,单数的那个中文会出现乱码,实际推测是编码问题。后面经证实确实属于编码问题。
报文打印出现如下情况
三个字:测测测
分析
请求进入过滤器,查看并测试报文请求入参编码是ISO-8859-1,天然的我给构造函数里面的
new InputStreamReader(ins)
改成了
new InputStreamReader(ins,"ISO-8859-1")
实际测试打印出来的数据能通过以下代码正常输出三个测字
new String(str.getBytes("ISO-8859-1"), Charset.forName("UTF-8"))
但是实际是以下代码获取的还是乱码一堆
String data = requestWrapper.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
在构造函数正确的情况下,能通过测试代码正常输出中文,那就是取值存在问题,我把上句代码改成以下方便测试
String data = requestWrapper.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
data = new String(data.getBytes("ISO-8859-1"), Charset.forName("UTF-8"));
System.out.println(data);
经再次分析问题可能就是出在了getReader,然后getReader又是调用的getInputStream,所以我将getInputStream改成
ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes("ISO-8859-1"));
经过测试还是同样的报错,依旧乱码,这回只能去一个个debug看,结果发现InputStreamReader是默认带编码GBK,所以所有的数据其实全都没带编码的情况下都是GBK,getReader中也是,所以导致问题的发生,然后又要把getReader改成以下,问题解决
return new BufferedReader(new InputStreamReader(this.getInputStream(),"ISO-8859-1"));
以上问题会出现一种情况,就是如果不同的请求参数编码大概率会存在不兼容问题,所以需要修改的,不能直接用,该文只做分析。