解決先後端分離的項目傳入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有了更多的瞭解。