解决先后端分离的项目传入null值,到了后台就变成"null"字符串的问题。spring
先说结论:这其实根本不是一个问题,而是事实。JSON传值的时候,null就会变成"null"字符串。后端
解决方式就是在前台加拦截器,把值为null的参数过滤掉。浏览器
一个Angular + SpringMVC的项目,当前台向后台传值的时候,若是传值为null,到后台会变为"null"。springboot
前台发起请求的方法以下:markdown
constructor(private httpClient: HttpClient) { } page(params: {clientId?: number, page: number, size: number, message?: string, level?: string}): Observable<Page<Log>> { const Params = { clientId: params.clientId ? params.clientId.toLocaleString() : null, page: params.page.toLocaleString(), size: params.size.toLocaleString(), message: params.message ? params.message : null, level: params.level ? params.level : null }; const url = '/log/page'; console.log(Params); return this.httpClient.get<Page<Log>>(url, {params: Params}); }
在前台会判断全部参数的值,若是为null或者undefined,参数就传null。app
在浏览器控制台输出了请求的参数,就是实实在在的null:前后端分离
后台被请求的方法以下:ide
@GetMapping("page") @JsonView(page.class) public Page<Log> page(@RequestParam(required = false) Long clientId, @RequestParam(required = false) String message, @RequestParam(required = false) String level, Pageable pageable) { logger.info(message+""+level); return new PageImpl(logService.page(clientId, level, message, pageable)); }
可是在后台判断空值的时候,意外的发现,全部的空值判断都不生效,即便传入的是null,后台也不会按照null来处理,因而报错。工具
在后台打断点一看,才发现全部的null传到后台以后,都变成了"null":ui
null变成String,这就是空值判断失效的缘由。
在解决问题以前,咱们须要先明白,前台向后台传值,是使用JSON来完成的。
JSON: Java Script Object Notation,JavaScript对象表示法。
虽然名字中有JS,但JSON并非JavaScript专属,而是一种独立于语言的文本格式(相似markdown、XML之类的),所以,许多语言均可以解析JSON,它也就变成了不一样语言之间传值的工具。
实际传值的时候,前台会把参数变成JSON字符串。
随便来一段JSON字符串,以下:
[ { "id": 1, "level": "DEBUG", "levelCode": 1, "logger": "123", "context": "1", "thread": "", "message": "123", "timestamp": "2020-03-15T21:53:32.000+0000", }, { "id": 2, "level": "INFO", "levelCode": 2, "logger": "123", "context": "2", "thread": "", "message": "123", "timestamp": "2020-03-10T21:53:32.000+0000" } ]
能够看出,JSON使用了键值对的形式,而值得关注的一点是,全部的信息,都是字符串或数字。
换句话说,JSON中只有字符串和数字。
因为数据传输时,是不能直接传对象的,因此在真正传值的时候,要转换成JSON字符串,不管什么类型都要转换成字符串或数字。
等到后台接收到参数的时候,其实后台也不知道传过来的是什么类型,只能按照规定好的参数类型,尝试对字符串进行强制转换。
因而,若是出现了null,前台就只能转化成"null",这就致使了后台只能接收到"null",甚至没法区分null和"null"。
更严重的问题在于:若是后台接收的参数是数字类型(Long、Int、Double),而前台传入是null的话,因为字符串强制转换为数字失败,会直接致使后台500.
整体思路,就是在前台加HTTP请求的拦截器,只要发现参数中有null,就把这个参数去掉。
因为发起请求时根本没有这个参数,后台接收到的就是实实在在的null了。
对于初学者来讲,Angular设置拦截器可能比较困难,能够参考:拦截器——SpringBoot+Angular入门实例教程
只须要在已经写好的负责拦截HTTP请求的拦截器中添加,并稍微改动:
/** * 过滤到null及undefined */ let cleanedParams = new HttpParams(); // request 须要替换成本身的 request.params.keys().forEach(x => { if (isDefined(request.params.get(x))) { cleanedParams = cleanedParams.append(x, req.params.get(x)); } }); request = request.clone({headers, params: cleanedParams});
当前台拦截器生效以后,再看控制台,就能发现,只剩下page和size两个参数了,其余的值为null的参数都被过滤掉了:
后台也确实变成null了:
至此,成功的过滤掉null参数。
先后台传值,null变成"null",这根本不算个问题,而是因为JSON的原理,只能变成字符串的形式。
解决方法就是在前台拦截器加入对空参数的过滤,过滤后不传这个参数,后台接收到的就是实实在在的null了。
经过此次解决问题,对拦截器和JSON有了更多的了解。