问题产生
在项目中在对某个用户进行多个角色(每个角色可以自定义权限勾选很多相关业务权限)进行授权时,突然报错:NPE空指针异常;但很奇怪选择的角色少点,给定的权限少点就不报异常,选择的角色很多,给定的权限很多时就会报异常;所以一开始定位问题产生的原因是由于ajax请求微服务数据量大时(大概几MB就会出现问题,自己模拟的数据量是5M),就会产生后台参数获取不到原因;
相关说明
项目中参数传递都是经过base64加密的,ajax请求需要通过nginx反向代理转发到网关gateway,网关中对参数进行解密,并重新设置request参数再转发路由到相应微服务;而且由于项目中之前提交都是表单提交Content-Type:application/x-www-form-urlencoded,对于@RequestBody注解在项目中重新写了适配包jar,即重新定义了参数解析器对其进行特殊处理,获取参数通过request.getParameterMap()进行获取;
问题跟踪分析
通过跟踪日志以及查看network得知,前端参数经过base64加密后已经传递到后台网关服务,但是请求的目标微服务userservice中关于修改用户接口参数并未接收到相应的前端传递过来的参数,所以导致了空指针异常;一开始怀疑是大数据量时网关中参数解密解析出了问题,但通过在本地跟踪代码后发现网关中过滤器已经获取到了相应参数,并且数据未丢失,但路由转发到网关经过适配包的自定义参数解析器时,发现通过request.getParameterMap()获取不到参数,所以到了微服务后台参数解析的时候,参数为获取到,相关参数没有进行校验就会报NPE;
问题解决
-
适配包中代码适配
所以最终问题产生的原因找到了,就是ajax通过post方法传递到后台,经过自定义参数解析器获取参数时未获取到;之后就试着通过流的方式进行参数获取,主要代码如下:
if (empyMap.size() ==0) {
String myparameters =null;
StringBuilder sb =new StringBuilder();
try {
BufferedReader reader = request.getReader();//通过流进行获取参数
char[] buff =new char[1024 *1024];
int len;
while ((len = reader.read(buff)) != -1) {
sb.append(buff,0, len);
}
}catch (IOException e) {
e.printStackTrace();
}
myparameters =this.splitString(sb.toString(), ArgumentUtil.PARAMETERS+"=");
if(!StringUtils.isEmpty(myparameters)){
myparameters = URLDecoder.decode(myparameters,"UTF-8");
return jsonToMap(myparameters);//json转换
}
- nginx超时等设置
client_max_body_size 2048m; //解决413请求数据量太大问题
location /api/ {
proxy_pass http://ip:port/api/; //相关请求代理转发
proxy_send_timeout 600;//600秒
proxy_read_timeout 600;//600秒
}
-
批量参数设置
主要发现批量插入未生效,所以url中设置此参数&rewriteBatchedStatements=true即可
url: jdbc:mysql://ip:port/dbname?useUnicode=true&characterEncoding=utf-8&useOldAliasMetadataBehavior=true&rewriteBatchedStatements=true
username: xxxx
password: xxxx
driver-class-name: com.mysql.jdbc.Driver
参考:关于ajax post请求,参数过大产生的问题解决 Java - 十月南城 - 博客园 (cnblogs.com)