![](/img/trans.png)
[英]how to use @Requestparam @RequestBody together in spring restful
[英]Spring MVC - Why not able to use @RequestBody and @RequestParam together
使用帶有 Post 請求和 Content-Type application/x-www-form-urlencoded 的 HTTP 開發客戶端
網址:本地主機:8080/SpringMVC/welcome
正文:名稱=abc
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, Model model) {
model.addAttribute("message", body);
return "hello";
}
// Gives body as 'name=abc' as expected
網址:本地主機:8080/SpringMVC/welcome
在正文中 - name=abc
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, Model model) {
model.addAttribute("name", name);
return "hello";
}
// Gives name as 'abc' as expected
網址:本地主機:8080/SpringMVC/welcome
正文:名稱=abc
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(
@RequestBody String body,
@RequestParam String name, Model model)
{
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// HTTP Error Code 400 - The request sent by the client was syntactically incorrect.
網址:本地主機:8080/SpringMVC/welcome
正文:名稱=abc
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(
@RequestParam String name,
@RequestBody String body, Model model)
{
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// No Error. Name is 'abc'. body is empty
URL: localhost:8080/SpringMVC/welcome?name=xyz
正文:名稱=abc
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(
@RequestBody String body,
@RequestParam String name, Model model)
{
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// name is 'xyz' and body is 'name=abc'
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(
@RequestParam String name,
@RequestBody String body, Model model)
{
model.addAttribute("name", name);
model.addAttribute("message", body);
return "hello";
}
// name = 'xyz,abc' body is empty
有人可以解釋這種行為嗎?
@RequestBody
javadoc 狀態
指示方法參數的注釋應綁定到 Web 請求的正文。
它使用HttpMessageConverter
注冊實例將請求正文反序列化為帶注釋的參數類型的對象。
而@RequestParam
javadoc 狀態
指示方法參數應綁定到 Web 請求參數的注釋。
Spring 將請求的主體綁定到用@RequestBody
注釋的參數。
Spring 將請求主體中的請求參數(url 編碼的參數)綁定到您的方法參數。 Spring 將使用參數的名稱,即。 name
,映射參數。
參數按順序解析。 首先處理@RequestBody
。 Spring 將消耗所有HttpServletRequest
InputStream
。 當它然后嘗試解析@RequestParam
,默認情況下是required
,查詢字符串中沒有請求參數或請求正文的剩余部分,即。 沒什么。 因此它以 400 失敗,因為處理程序方法無法正確處理請求。
@RequestParam
的處理程序首先起作用,讀取HttpServletRequest
InputStream
以映射請求參數,即。 整個查詢字符串/url 編碼的參數。 它這樣做並獲取映射到參數name
的值abc
。 當@RequestBody
的處理程序運行時,請求正文中沒有任何內容,因此使用的參數是空字符串。
@RequestBody
的處理程序讀取正文並將其綁定到參數。 @RequestParam
的處理程序然后可以從 URL 查詢字符串中獲取請求參數。
@RequestParam
的處理程序從正文和 URL 查詢字符串中讀取。 它通常會將它們放在Map
,但由於參數是String
類型,Spring 會將Map
序列化為逗號分隔值。 然后,@ @RequestBody
的處理程序再次從正文中讀取任何內容。
回答這個問題為時已晚,但它可以幫助新讀者,似乎是版本問題。 我用 spring 4.1.4 運行了所有這些測試,發現@RequestBody
和@RequestParam
的順序無關緊要。
body= "name=abc"
和name = "abc"
body ="name=abc"
, name = "xyz,abc"
這是因為不是很直接的 Servlet 規范。 如果您正在使用本機HttpServletRequest
實現,則無法同時獲得 URL 編碼正文和參數。 Spring 做了一些變通方法,這使它變得更加奇怪和不透明。
在這種情況下,Spring(版本 3.2.4)使用來自getParameterMap()
方法的數據為您重新呈現主體。 它混合了 GET 和 POST 參數並打破了參數順序。 負責混亂的類是ServletServerHttpRequest
。 不幸的是它不能被替換,但StringHttpMessageConverter
類可以。
不幸的是,干凈的解決方案並不簡單:
StringHttpMessageConverter
。 復制/覆蓋原始類調整方法readInternal()
。HttpServletRequest
覆蓋getInputStream()
、 getReader()
和getParameter*()
方法。在 StringHttpMessageConverter#readInternal 方法中,必須使用以下代碼:
if (inputMessage instanceof ServletServerHttpRequest) {
ServletServerHttpRequest oo = (ServletServerHttpRequest)inputMessage;
input = oo.getServletRequest().getInputStream();
} else {
input = inputMessage.getBody();
}
然后轉換器必須在上下文中注冊。
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true/false">
<bean class="my-new-converter-class"/>
</mvc:message-converters>
</mvc:annotation-driven>
此處描述了第二步: Http Servlet 請求在讀取一次后丟失 POST 正文中的參數
您也可以將 @RequestParam 默認必需狀態更改為 false,以便不生成 HTTP 響應狀態代碼 400。 這將允許您按照您喜歡的任何順序放置注釋。
@RequestParam(required = false)String name
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.