SpringMVC @RequestBody的使用解析
SpringMVC @RequestBody的使用
Spring mvc是一個非常輕量的mvc框架,注解可以大大減少配置,讓請求的攔截變得比較簡單。這次記錄下@RequestBody 注解接收參數(shù)尤其是數(shù)組參數(shù)的用法。
關(guān)于容器的配置不再多說,這里寫出spring-servlet.xml的sechme:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<!-- 掃描包注解 -->
<context:component-scan base-package="xxxx"></context:component-scan>
<!-- mvc注解功能啟動 -->
<mvc:annotation-driven />
</beans>
只要對應(yīng)包名下面的添加注解即可掃描到對應(yīng)的控制器,一般采用@Controller
RequestBody接收基本類型
@Controller
public class TestController {
// url請求攔截
@RequestMapping("test/test.do")
@ResponseBody // 返回參數(shù)為JSON
public void test(@RequestBody String name) {
System.out.println("getParams : " + name);
}
}
@RequestBody只要接收POST請求Body里的數(shù)據(jù)。

這樣發(fā)送請求,即可在java控制臺中打?。?/p>
getParams : {"name":"micro"}
@RequestBody接收基本數(shù)組
然后我們接收基本類型數(shù)組:
@RequestMapping("test/test.do")
@ResponseBody
public void test(@RequestBody List<String> nameList) {
System.out.println("getParams : " + nameList);
}

這樣即可獲取到參數(shù),不要body里寫成了{(lán)“nameList”:[“name1”,“name2”]}這樣會拋出異常。
@RequestBody是對應(yīng)的POST請求的body,body即是獲取的參數(shù),如果想通過參數(shù)去獲取,則要使用@RequestParams 注解:
@RequestMapping("test/test.do")
@ResponseBody
public void test(@RequestParam("name") String name) {
System.out.println("getParams : " + name);
}

注意是GET請求,參數(shù)直接放到URL后面,這樣就可以使用@RequestParams獲取到對應(yīng)參數(shù)名的參數(shù)值。如果是復(fù)雜的對象。
@RequestBody的使用。
定義model:
class Person {
private Long id;
private String name;
// setter getter
}
@RequestBody接收復(fù)雜對象
接收參數(shù)的方式
@RequestMapping("test/test.do")
@ResponseBody
public void test(@RequestBody Person person) {
System.out.println("getParams : " + person.getId() + " ," + person.getName());
}
即可獲取到參數(shù),body里的參數(shù)會自動匹配到person的屬性并賦值。
注意名字要與對象的屬性變量名一致。否則獲取不到參數(shù),例如這里就不能在body里寫成{“i”:1,“name”:“micro”},這樣獲取到person的id為null。
@RequestBody接收復(fù)雜對象數(shù)組
如果是復(fù)雜對象數(shù)組:
@RequestMapping("test/test.do")
@ResponseBody
public void test(@RequestBody List<Person> personList) {
for (Person p : personList) {
System.out.println(p.getId() + " ," + p.getName());
}
}
請求方式如下,注意body里的格式是[]數(shù)組。

控制臺打印:
1 ,micro
2 ,micro2
即完成了@RequestBody接收各種類型的參數(shù)。
@RequestBody使用的一些注意事項
眾所周知,springmvc中@RequestBody的注解是一個很實用的功能,它能幫我們解析客戶端(移動設(shè)備、瀏覽器等)發(fā)送過來的json數(shù)據(jù),并封裝到實體類中。
但我今天要說的不是它的原理,而是記錄一些工作中使用@RequestBody注解遇到的一些問題,也提醒廣大java開發(fā)者避免類似的問題。
最近有個需求,接收客戶的設(shè)備發(fā)送過來的json數(shù)據(jù),客戶的設(shè)備里面只能修改ip,然后通過http協(xié)議的post方式發(fā)送數(shù)據(jù)過來。我很自然地想到在登錄頁那里處理,在toLogin方法中增加@RequestBody Kehu kehu參數(shù),用戶解析并封裝json數(shù)據(jù)。
廢話不多說,上代碼,如下所示:
@RequestMapping(value = "/toLogin")
public ModelAndView toLogin(HttpServletRequest request, @RequestBody Kehu kehu) throws Exception {
// 接收客戶設(shè)備發(fā)送過來的json數(shù)據(jù)
if (kehu != null && !StringUtil.isEmpty(kehu.cmd)) {
uploadData(kehu);
}
ModelAndView mv = new ModelAndView();
PageData pageData = this.getPageData(request);
pageData.put("SYSNAME", Tools.readTxtFile(Const.SYSNAME)); // 讀取系統(tǒng)名稱
mv.setViewName("base/login");
mv.addObject("pd", pageData);
return mv;
}
一切看似很完美,在瀏覽器上測試一下,輸入localhost(我的項目已經(jīng)設(shè)置為了缺省項目,端口號也改為了80)
我傻眼了,報了400錯誤。如下圖所示:

The request sent by the client was syntactically incorrect.
翻譯過來就是:客戶端發(fā)送的請求在語法上是不正確的。
沒加@RequestBody Kehu kehu之前是正常的,問題肯定出在了這里。我一看RequestBody的源碼:
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.http.converter.HttpMessageConverter;
/**
* Annotation indicating a method parameter should be bound to the body of the web request.
* The body of the request is passed through an {@link HttpMessageConverter} to resolve the
* method argument depending on the content type of the request. Optionally, automatic
* validation can be applied by annotating the argument with {@code @Valid}.
*
* <p>Supported for annotated handler methods in Servlet environments.
*
* @author Arjen Poutsma
* @since 3.0
* @see RequestHeader
* @see ResponseBody
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
/**
* Whether body content is required.
* <p>Default is {@code true}, leading to an exception thrown in case
* there is no body content. Switch this to {@code false} if you prefer
* {@code null} to be passed when the body content is {@code null}.
* @since 3.2
*/
boolean required() default true;
}
required方法默認(rèn)返回值是true。
這樣問題就明朗了,我請求localhost的時候,沒有傳json過去,所以就會報400錯誤,因為客戶端發(fā)送的請求在語法上是不正確的。
解決方法:在@RequestBody后面加上(required=false)就可以了。表示kehu對象可以不傳入。
/**
* 訪問登錄頁
* @RequestBody(required=false) 表示kehu對象可以不傳入。
* 一定要加上required=false,否則登錄的時候會報400錯誤。錯誤代碼:
* The request sent by the client was syntactically incorrect.
* @return
* @throws Exception
*/
@RequestMapping(value = "/toLogin")
public ModelAndView toLogin(HttpServletRequest request, @RequestBody(required=false) Kehu kehu) throws Exception {
// 接收硬幣機發(fā)送過來的json數(shù)據(jù)
if (kehu != null && !StringUtil.isEmpty(kehu.cmd)) {
uploadData(kehu);
}
ModelAndView mv = new ModelAndView();
PageData pageData = this.getPageData(request);
pageData.put("SYSNAME", Tools.readTxtFile(Const.SYSNAME)); // 讀取系統(tǒng)名稱
mv.setViewName("base/login");
mv.addObject("pd", pageData);
return mv;
}
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
舉例講解Java編程中this關(guān)鍵字與super關(guān)鍵字的用法
這篇文章主要介紹了Java編程中this關(guān)鍵字與super關(guān)鍵字的用法示例,super是this的父輩,在繼承過程中兩個關(guān)鍵字經(jīng)常被用到,需要的朋友可以參考下2016-03-03
Java 實戰(zhàn)練手項目之校園超市管理系統(tǒng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+Mysql+Maven+Bootstrap實現(xiàn)一個校園超市管理系統(tǒng),大家可以在過程中查缺補漏,提升水平2021-11-11
JavaSE的三大接口:Comparator,Comparable和Cloneable詳解
這篇文章主要介紹了詳解JavaSE中Comparator,Comparable和Cloneable接口的區(qū)別的相關(guān)資料,希望通過本文大家能徹底掌握這部分內(nèi)容,需要的朋友可以參考下2021-10-10

