最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2021年11月02日 11:47:34   作者:zpzkitt  
這篇文章主要介紹了使用Spring處理x-www-form-urlencoded方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

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

最近在重寫一個(gè)項(xiàng)目時(shí)遇到了許多奇葩問題,這個(gè)項(xiàng)目是一個(gè)簡(jiǎn)單的web后臺(tái)項(xiàng)目,基本上全都是增刪改查數(shù)據(jù)庫的操作。這里面遇到幾個(gè)用spring接收前端post請(qǐng)求的接口。

基本情況是post請(qǐng)求有四種data參數(shù)格式,這些基礎(chǔ)知識(shí)在我另一片博文中提到過這里就不廢話了。主要是因?yàn)榍岸擞袃蓚€(gè)地方用到了這個(gè)接口,但是在用這個(gè)接口的時(shí)候兩個(gè)地方用法都不同,奇葩的c++居然還都解析成功了(其實(shí)因?yàn)閏++沒有對(duì)請(qǐng)求參數(shù)格式和數(shù)據(jù)做檢查所以一直沒有問題)。

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

另一個(gè)地方是發(fā)送的application/x-www-form-urlencode格式,發(fā)送的也是一個(gè)jsonArray數(shù)據(jù)。(下面簡(jiǎn)稱后者)

前者解析方式比較簡(jiǎn)單

 @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<>();
  }

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

通過調(diào)試發(fā)現(xiàn)后者前端的接口傳過來的參數(shù)是"["abc","def"]="這樣子的,本身x-www-form-urlencode是多個(gè)kev-value對(duì)的數(shù)據(jù)格式,所以現(xiàn)在沒有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解析出整個(gè)原始post data。然后做字符串處理。

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

測(cè)試結(jié)果是用tomcat沒法從HttpServletRequest到這個(gè)post data,但是用jetty可以從HttpServletRequest解析到post data。

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

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

關(guān)于application/x-www-form-urlencoded編碼

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

熟悉servlet的話,這個(gè)問題應(yīng)該算常識(shí)了。它其實(shí)跟容器無關(guān),所有的servlet容器都是這樣的行為。幾年前在實(shí)現(xiàn)一個(gè)網(wǎng)關(guān)代理的時(shí)候就遇到過這個(gè)問題,當(dāng)時(shí)使用的是jetty,發(fā)現(xiàn)POST過來的數(shù)據(jù)讀不到,也是application/x-www-form-urlencoded編碼,斷點(diǎn)跟蹤發(fā)現(xiàn)是在獲取流之前有過request.getParameter,數(shù)據(jù)會(huì)被解析,并且后續(xù)數(shù)據(jù)流不可再被讀取。

在servlet規(guī)范3.1.1節(jié)里,對(duì)POST數(shù)據(jù)何時(shí)會(huì)被當(dāng)做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.

規(guī)范里已經(jīng)明確的聲明當(dāng)請(qǐng)求滿足:

1) http/https

2) POST

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

4) 調(diào)用過getParameter方法,則數(shù)據(jù)會(huì)被當(dāng)做請(qǐng)求的paramaters,而不能再通過 request 的 inputstream 直接讀取。

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

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

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

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

在HTML4之前,表單數(shù)據(jù)的編碼方式只有application/x-www-form-urlencoded這一種(現(xiàn)在默認(rèn)也是這種方式),因?yàn)樵缙诘臅r(shí)候,web上提交過來的數(shù)據(jù)也是非常簡(jiǎn)單的,基本上以key-value形式為主,所以表單采用application/x-www-form-urlencoded這種編碼形式也沒什么問題。

在HTML4里又引入了multipart/form-data編碼,對(duì)于這兩種編碼如何選擇,請(qǐng)參考這里。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java調(diào)用淘寶api聯(lián)網(wǎng)查詢ip歸屬地

    java調(diào)用淘寶api聯(lián)網(wǎng)查詢ip歸屬地

    java聯(lián)網(wǎng)查詢IP歸屬地,原理是根據(jù)淘寶提供的service查詢IP的歸屬地并且解析http請(qǐng)求返回的json串
    2014-03-03
  • 剖析Fork?join并發(fā)框架工作竊取算法

    剖析Fork?join并發(fā)框架工作竊取算法

    這篇文章主要為大家剖析介紹了Fork?join并發(fā)框架工作竊取算法的示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • java逐行讀取文件(讀取文件每一行、按行讀取文件)附帶詳細(xì)代碼

    java逐行讀取文件(讀取文件每一行、按行讀取文件)附帶詳細(xì)代碼

    這篇文章主要給大家介紹了關(guān)于java逐行讀取文件(讀取文件每一行、按行讀取文件)的相關(guān)資料,讀取文件是我們?cè)谌粘9ぷ髦薪?jīng)常遇到的一個(gè)需求,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 圖解如何在Spring Boot中使用JSP頁面

    圖解如何在Spring Boot中使用JSP頁面

    這篇文章主要介紹了圖解如何在Spring Boot中使用JSP頁面,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java循環(huán)終止的實(shí)現(xiàn)方式總結(jié)

    Java循環(huán)終止的實(shí)現(xiàn)方式總結(jié)

    循環(huán)是一種重復(fù)執(zhí)行一段代碼的結(jié)構(gòu),Java提供了四種主要的循環(huán)結(jié)構(gòu),本文主要來和大家介紹一下Java循環(huán)終止的實(shí)現(xiàn)方式,有需要的小伙伴可以參考一下
    2023-10-10
  • Java堆&優(yōu)先級(jí)隊(duì)列示例講解(上)

    Java堆&優(yōu)先級(jí)隊(duì)列示例講解(上)

    這篇文章主要通過示例詳細(xì)為大家介紹Java中的堆以及優(yōu)先級(jí)隊(duì)列,文中的示例代碼講解詳細(xì),對(duì)我們了解java有一定幫助,需要的可以參考一下
    2022-03-03
  • 關(guān)于SpringBoot中事務(wù)失效的幾種情況

    關(guān)于SpringBoot中事務(wù)失效的幾種情況

    這篇文章主要介紹了關(guān)于SpringBoot中事務(wù)失效的幾種情況,Spring AOP默認(rèn)使用動(dòng)態(tài)代理,會(huì)給被代理的類生成一個(gè)代理類,事務(wù)相關(guān)的操作都通過代理來完成,使用內(nèi)部方法調(diào)用時(shí),使用的是實(shí)例調(diào)用,沒有通過代理類調(diào)用方法,因此事務(wù)不會(huì)檢測(cè)到失敗,需要的朋友可以參考下
    2023-08-08
  • java如何讀取文件目錄返回樹形結(jié)構(gòu)

    java如何讀取文件目錄返回樹形結(jié)構(gòu)

    這篇文章主要介紹了java如何讀取文件目錄返回樹形結(jié)構(gòu)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 理解Java設(shè)計(jì)模式編程中的迪米特原則

    理解Java設(shè)計(jì)模式編程中的迪米特原則

    這篇文章主要介紹了Java設(shè)計(jì)模式編程中的迪米特原則,迪米特原則旨在降低類與類之間的耦合,需要的朋友可以參考下
    2016-02-02
  • Java Map.getOrDefault方法詳解

    Java Map.getOrDefault方法詳解

    Map.getOrDefault(Object key, V defaultValue)是Java中Map接口的一個(gè)方法,用于獲取指定鍵對(duì)應(yīng)的值,如果鍵不存在,則返回一個(gè)默認(rèn)值,這篇文章主要介紹了Java Map.getOrDefault方法詳解,需要的朋友可以參考下
    2024-01-01

最新評(píng)論

包头市| 双鸭山市| 化州市| 南岸区| 三门峡市| 藁城市| 乐亭县| 临猗县| 徐汇区| 屏南县| 盐城市| 齐齐哈尔市| 屏山县| 廉江市| 龙海市| 建瓯市| 屏东市| 环江| 富平县| 屏山县| 高安市| 静安区| 凤庆县| 宣威市| 昌都县| 通化县| 罗江县| 龙游县| 巴马| 泌阳县| 贡觉县| 洮南市| 怀集县| 镇沅| 双牌县| 专栏| 花垣县| 元谋县| 天长市| 萨迦县| 溧水县|