中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用Spring處理x-www-form-urlencoded方式

發布時間:2021-11-02 13:52:48 來源:億速云 閱讀:402 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關如何使用Spring處理x-www-form-urlencoded方式的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

Spring處理x-www-form-urlencoded方式

最近在重寫一個項目時遇到了許多奇葩問題,這個項目是一個簡單的web后臺項目,基本上全都是增刪改查數據庫的操作。這里面遇到幾個用spring接收前端post請求的接口。

基本情況是post請求有四種data參數格式,這些基礎知識在我另一片博文中提到過這里就不廢話了。主要是因為前端有兩個地方用到了這個接口,但是在用這個接口的時候兩個地方用法都不同,奇葩的c++居然還都解析成功了(其實因為c++沒有對請求參數格式和數據做檢查所以一直沒有問題)。

一個地方是發送的是application/json格式,發送了一個jsonArray數據(數據例子["abc", "bcd"])這個是沒有問題的正確使用方式。(下面簡稱前者)

另一個地方是發送的application/x-www-form-urlencode格式,發送的也是一個jsonArray數據。(下面簡稱后者)

前者解析方式比較簡單

 @RequestMapping(value = "/check_apps_version",
      method = RequestMethod.POST,
      produces = {"application/json;charset=UTF-8"},
      consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
  @ResponseBody
  public BaseResponse<List<AppListItem>> checkAppsVersion(ReqCheckAppsVersion requstParam,
      @RequestBody List<String> apps) {
    return new BaseResponse<>();
  }

后者這個發送方式在spring用@RequestBody解析時就很怪異,但是前段是手機APP已經發布出去了沒法修改,只能后端來修改滿足這個奇怪的需求

通過調試發現后者前端的接口傳過來的參數是"["abc","def"]="這樣子的,本身x-www-form-urlencode是多個kev-value對的數據格式,所以現在沒有value只有key了,只能通過字符串處理來解決了。

  @RequestMapping(value = "/check_apps_version",
      method = RequestMethod.POST,
      produces = {"application/json;charset=UTF-8"},
      consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
  @ResponseBody
  public BaseResponse<List<AppListItem>> checkAppsVersionParams(HttpServletRequest request,
                                                                ReqCheckAppsVersion requstParam,
                                                                @RequestBody String apps) {
 String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
    return BaseResponse.success();
  }

兩種方式,一種是通過@RequestBody把post data解析成string格式,另一種是通過HttpServletRequest解析出整個原始post data。然后做字符串處理。

但是在做做這個測試時候我們想了一下會不會有只有value沒有key的情況,也就是這樣"=["abc","def"]"。

測試結果是用tomcat沒法從HttpServletRequest到這個post data,但是用jetty可以從HttpServletRequest解析到post data。

這個可能是tomcat和jetty的區別吧,還沒有弄清楚什么原因。但是我們的問題總算是解決了,最大感觸就是前人挖坑后人埋啊。

希望以后能注意一下代碼健壯性的問題,避免給別人或者自己挖坑。

關于application/x-www-form-urlencoded編碼

同事遇到在servlet端通過request對象getInputStream讀取POST過來的數據,卻讀不到的問題,懷疑是tomcat的問題。查了一下Content-type是application/x-www-form-urlencoded,估計是被解析成了parameters,果然在他獲取流之前,有過request.getParameter的操作。

熟悉servlet的話,這個問題應該算常識了。它其實跟容器無關,所有的servlet容器都是這樣的行為。幾年前在實現一個網關代理的時候就遇到過這個問題,當時使用的是jetty,發現POST過來的數據讀不到,也是application/x-www-form-urlencoded編碼,斷點跟蹤發現是在獲取流之前有過request.getParameter,數據會被解析,并且后續數據流不可再被讀取。

在servlet規范3.1.1節里,對POST數據何時會被當做parameters有描述:

1. The request is an HTTP or HTTPS request.
2. The HTTP method is POST.
3. The content type is application/x-www-form-urlencoded.
4. The servlet has made an initial call of any of the getParameter family of methods on the request object.

If the conditions are met, post form data will no longer be available for reading directly from the request object's input stream.

規范里已經明確的聲明當請求滿足:

1) http/https

2) POST

3) Content-type 是application/x-www-form-urlencoded

4) 調用過getParameter方法,則數據會被當做請求的paramaters,而不能再通過 request 的 inputstream 直接讀取。

所以不論tomcat、jetty還是其他servlet容器都遵循這個方式。不過話說回來,為什么application/x-www-form-urlencoded編碼的數據會被當做parameter來解析呢?

使用http上傳數據可以用GET或POST,使用GET的話,只能通過uri的queryString形式,這會遇到長度的問題,各個瀏覽器或server可能對長度支持的不同,所以到要提交的數據如果太長并不適合使用GET提交。

采用POST的話,既可以在uri中帶有queryString也可以將數據放在body中。body內容可以有多種編碼形式,其中application/x-www-form-urlencoded編碼其實是基于uri的percent-encoding編碼的,所以采用application/x-www-form-urlencoded的POST數據和queryString只是形式不同,本質都是傳遞參數。

在tomcat的Request.parseParameters方法里,對于application/x-www-form-urlencoded是有做判斷的,對這種編碼會去解析body里的數據,填充到parameters里,所以后續想再通過流的方式讀取body是讀不到的(除非你沒有觸發過getParameter相關的方法)。

在HTML4之前,表單數據的編碼方式只有application/x-www-form-urlencoded這一種(現在默認也是這種方式),因為早期的時候,web上提交過來的數據也是非常簡單的,基本上以key-value形式為主,所以表單采用application/x-www-form-urlencoded這種編碼形式也沒什么問題。

感謝各位的閱讀!關于“如何使用Spring處理x-www-form-urlencoded方式”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

承德市| 津南区| 图们市| 鄄城县| 泗水县| 农安县| 孝义市| 大理市| 荆门市| 福海县| 汕头市| 民丰县| 绵竹市| 阿克| 南通市| 小金县| 佳木斯市| 广安市| 武功县| 烟台市| 奉节县| 石嘴山市| 伊金霍洛旗| 望谟县| 高陵县| 乐亭县| 叶城县| 甘南县| 安平县| 靖远县| 台南县| 白玉县| 永川市| 平顺县| 汉阴县| 上蔡县| 鄢陵县| 星子县| 察哈| 上杭县| 共和县|