解決先後端分離的項目傳null值變爲"null"字符串的問題

前言

解決先後端分離的項目傳入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:
image.png前後端分離

後臺被請求的方法以下: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"
image.pngui

null變成String,這就是空值判斷失效的緣由。

緣由

在解決問題以前,咱們須要先明白,前臺向後臺傳值,是使用JSON來完成的。

JSONJava 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字符串,不管什麼類型都要轉換成字符串數字

等到後臺接收到參數的時候,其實後臺也不知道傳過來的是什麼類型,只能按照規定好的參數類型,嘗試對字符串進行強制轉換。

image.png

因而,若是出現了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的參數都被過濾掉了:

image.png

後臺也確實變成null了:

image.png

至此,成功的過濾掉null參數。

總結

先後臺傳值,null變成"null",這根本不算個問題,而是因爲JSON的原理,只能變成字符串的形式。

解決方法就是在前臺攔截器加入對空參數的過濾,過濾後不傳這個參數,後臺接收到的就是實實在在的null了。

經過此次解決問題,對攔截器和JSON有了更多的瞭解。

相關文章
相關標籤/搜索