先说原因:
检查request是否在controller接收之前被更改。
--------------------------------------
前提:
post请求,参数为json形式,java接收controller 是@RestController注解,采用@RequestBody 将参数转为bean,实际发现接收到的bean属性字段全部为null。
思路:
检查controller接收到的json是否正确,
网上搜这个问题,一般都是再说配置的问题,例如注解没配、请求方式未指定、jackson设置错误等等,本例提供一个新的角度,就是request是否被更改过。
以本次为例来讲:
采用以下代码,放在controller相关方法内的开始位置:
BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream(), "utf-8"));
StringBuffer sb = new StringBuffer("");
String temp;
while ((temp = br.readLine()) != null) {
sb.append(temp);
}
br.close();
params = sb.toString();
log.info(params);
对request进行流式输出,发现输出内容没有前端传的参数,只有我在网关添加的信息。
接下来检查网关过滤器,发现在向request添加信息,对request进行改造的过程中,出现了如下代码:
// ctx 是RequestContext paramObj 是需要放入request的信息对象
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
body = "{}";
JSONObject jsonObject = JSON.parseObject(body);
jsonObject.put(ConstantUtil.INFO,paramObj);//放入需要新增的信息
String newBody = jsonObject.toString();
final byte[] reqBodyBytes = newBody.getBytes();
//给 RequestContext 赋 新的改造过的request
ctx.setRequest(new HttpServletRequestWrapper(request){
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(reqBodyBytes);
}
@Override
public int getContentLength() {
return reqBodyBytes.length;
}
@Override
public long getContentLengthLong() {
return reqBodyBytes.length;
}
});
由此可见,body = "{}"; 是对request进行初始化了,然后再json化添加自定义信息,重构生成新的request。
所以只需要有条件的设置request的初始化 body = "{}"; 就可以。给 body = {} 添加为空的判断以及请求是否包含 “{”来判断是不是json,从而决定是否重置request【具体需要结合自己的业务需求来实现判断逻辑,这里只是指出 request 被重置导致接收参数全部为null】
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
if(StringUtil.isEmpty(body)){
body = "{}";
}
if(body.contains("{")) {
JSONObject jsonObject = JSON.parseObject(body);
jsonObject.put(ConstantUtil.INFO,paramObj);//放入需要新增的信息
String newBody = jsonObject.toString();
final byte[] reqBodyBytes = newBody.getBytes();
//给 RequestContext 赋 新的改造过的request
ctx.setRequest(new HttpServletRequestWrapper(request){
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(reqBodyBytes);
}
@Override
public int getContentLength() {
return reqBodyBytes.length;
}
@Override
public long getContentLengthLong() {
return reqBodyBytes.length;
}
});
}