(轉載http://hrps.me/2017/05/22/http-request-payload-vs-form-data/)前端
我正在開發的項目前端和後端是徹底獨立的,經過配置 webpack 的 proxy 將前端請求跨域代理到後臺服務。昨天發現,我前端執行 post
請求,後臺 springmvc 的 @RequestMapping
接收不到對應的請求參數。開始我覺得是我 proxy 配置有問題,致使 post 參數不能傳到後臺。然而,並非這樣…java
proxy 配置以下:webpack
前端代碼:ios
java 後臺代碼:git
我看了前端發起的請求,請求正文並非我熟悉的 Form Data
,而是 Request Payload
。如圖注意下面兩個請求的 Content-Type
的區別。github
Request Payload 請求web
Form Data 請求spring
瞭解這兩個的區別以前,咱們先回顧下 HTTP 請求報文格式:json
Request Payload 大概格式以下,請求頭部的 Content-Type: application/json
,而且請求正文是一個 json 格式的字符串axios
Form Data 大概格式以下,請求頭部的 Content-Type: application/x-www-form-urlencoded
,而且請求正文是相似 get 請求 url 的請求參數
對於 Request Payload 請求, 必須加 @RequestBody
才能將請求正文解析到對應的 bean 中,且只能經過 request.getReader()
來獲取請求正文內容
對於 Form Data 請求,無需任何註解,springmvc 會自動使用 MessageConverter 將請求參數解析到對應的 bean,且經過 request.getParameter(...)
能獲取請求參數
綜上,我在前端選擇使用 Form Data 的方式來發起請求,使用 qs 庫將 json 對象轉化爲字符串 (如 {name:'dahuang',age: 11}
轉化爲 name=dahuang&age=11
)。
以前我覺得 axios 會自動根據你的請求正文格式來選擇發起 Form Data 仍是 Request Payload 請求,可是執行 delete 操做時,如圖的 Content-Type 倒是 text/plain
因此,經過經過下面的方面來解決
執行 delete 操做時,我將 axios 添加了 headers,content-type: 'application/x-www-form-unlencoded'
,請求如圖,可是後臺 springmvc 的 @DeleteMapping
接收不到請求參數,必須使用 @RequestParam String id
,才能接收到請求參數。看了這個回答,有人回覆說這個是 tomcat 的問題而非 spring 的問題。
更新,今天遇到了一個問題,忽然個人 @PatchMapping
也不能獲取 form 表單傳遞的參數了。以前是能夠的,而後我 google 搜到了 HttpPutFormContentFilter,而後發現這個 filter 在 WebMvcAutoConfiguration
裏面配置的,而這個配置生效其中有一個條件是 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
,剛好,我前兩天整合前端代碼的時候配置 springMVC 繼承了 WebMvcConfigurationSupport.class
因此致使了該 fliter 不生效。