Spring 注解学习手札(七) 补遗——@ResponseBody,@RequestBody,@PathVariable

SpringMVC层跟JSon结合,几乎不需要做什么配置,代码实现也相当简洁。再也不用为了组装协议而劳烦辛苦了!

一、Spring注解@ResponseBody,@RequestBody和HttpMessageConverter

Spring 3.X系列增加了新注解 @ResponseBody @RequestBody

  • @RequestBody将HTTP请求正文转换为适合的HttpMessageConverter对象。
  • @ResponseBody将内容或对象作为 HTTP 响应正文返回,并调用适合HttpMessageConverter的Adapter转换对象,写入输出流。

HttpMessageConverter 接口,需要开启 <mvc:annotation-driven />
AnnotationMethodHandlerAdapter 将会初始化7个转换器,可以通过调用 AnnotationMethodHandlerAdapter getMessageConverts() 方法来获取转换器的一个集合 List<HttpMessageConverter>
引用
ByteArrayHttpMessageConverter
StringHttpMessageConverter
ResourceHttpMessageConverter
SourceHttpMessageConverter
XmlAwareFormHttpMessageConverter
Jaxb2RootElementHttpMessageConverter
MappingJacksonHttpMessageConverter


可以理解为,只要有对应协议的解析器,你就可以通过几行配置,几个注解完成协议——对象的转换工作!

PS:Spring默认的json协议解析由Jackson完成。

二、servlet.xml配置

Spring的配置文件,简洁到了极致,对于当前这个需求只需要三行核心配置:
Xml代码 收藏代码
  1. <context:component-scanbase-package="org.zlex.json.controller"/>
  2. <context:annotation-config/>
  3. <mvc:annotation-driven/>


三、pom.xml配置

闲言少叙,先说依赖配置,这里以Json+Spring为参考:
pom.xml
Xml代码 收藏代码
  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-webmvc</artifactId>
  4. <version>3.1.2.RELEASE</version>
  5. <type>jar</type>
  6. <scope>compile</scope>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.codehaus.jackson</groupId>
  10. <artifactId>jackson-mapper-asl</artifactId>
  11. <version>1.9.8</version>
  12. <type>jar</type>
  13. <scope>compile</scope>
  14. </dependency>
  15. <dependency>
  16. <groupId>log4j</groupId>
  17. <artifactId>log4j</artifactId>
  18. <version>1.2.17</version>
  19. <scope>compile</scope>
  20. </dependency>

主要需要 spring-webmvc jackson-mapper-asl 两个包,其余依赖包Maven会帮你完成。至于 log4j ,我还是需要看日志嘛。
包依赖图:

至于版本,看项目需要吧!

四、代码实现

域对象:
Java代码 收藏代码
  1. publicclassPersonimplementsSerializable{
  2. privateintid;
  3. privateStringname;
  4. privatebooleanstatus;
  5. publicPerson(){
  6. //donothing
  7. }
  8. }


这里需要一个空构造,由Spring转换对象时,进行初始化。

@ResponseBody,@RequestBody,@PathVariable
控制器:
Java代码 收藏代码
  1. @Controller
  2. publicclassPersonController{
  3. /**
  4. *查询个人信息
  5. *
  6. *@paramid
  7. *@return
  8. */
  9. @RequestMapping(value="/person/profile/{id}/{name}/{status}",method=RequestMethod.GET)
  10. public@ResponseBody
  11. Personporfile(@PathVariableintid,@PathVariableStringname,
  12. @PathVariablebooleanstatus){
  13. returnnewPerson(id,name,status);
  14. }
  15. /**
  16. *登录
  17. *
  18. *@paramperson
  19. *@return
  20. */
  21. @RequestMapping(value="/person/login",method=RequestMethod.POST)
  22. public@ResponseBody
  23. Personlogin(@RequestBodyPersonperson){
  24. returnperson;
  25. }
  26. }


备注: @RequestMapping(value = "/person/profile/{id}/{name}/{status}", method = RequestMethod.GET) 中的 {id}/{name}/{status} @PathVariable int id, @PathVariable String name,@PathVariable boolean status 一一对应,按名匹配。 这是restful式风格。
如果映射名称有所不一,可以参考如下方式:

Java代码 收藏代码
  1. @RequestMapping(value="/person/profile/{id}",method=RequestMethod.GET)
  2. public@ResponseBody
  3. Personporfile(@PathVariable("id")intuid){
  4. returnnewPerson(uid,name,status);
  5. }


  • GET模式下,这里使用了@PathVariable绑定输入参数,非常适合Restful风格。因为隐藏了参数与路径的关系,可以提升网站的安全性,静态化页面,降低恶意攻击风险。
  • POST模式下,使用@RequestBody绑定请求对象,Spring会帮你进行协议转换,将Json、Xml协议转换成你需要的对象。
  • @ResponseBody可以标注任何对象,由Srping完成对象——协议的转换。


做个页面测试下:
JS
Js代码 收藏代码
  1. $(document).ready(function(){
  2. $("#profile").click(function(){
  3. profile();
  4. });
  5. $("#login").click(function(){
  6. login();
  7. });
  8. });
  9. functionprofile(){
  10. varurl='http://localhost:8080/spring-json/json/person/profile/';
  11. varquery=$('#id').val()+'/'+$('#name').val()+'/'
  12. +$('#status').val();
  13. url+=query;
  14. alert(url);
  15. $.get(url,function(data){
  16. alert("id:"+data.id+"\nname:"+data.name+"\nstatus:"
  17. +data.status);
  18. });
  19. }
  20. functionlogin(){
  21. varmydata='{"name":"'+$('#name').val()+'","id":"'
  22. +$('#id').val()+'","status":"'+$('#status').val()+'"}';
  23. alert(mydata);
  24. $.ajax({
  25. type:'POST',
  26. contentType:'application/json',
  27. url:'http://localhost:8080/spring-json/json/person/login',
  28. processData:false,
  29. dataType:'json',
  30. data:mydata,
  31. success:function(data){
  32. alert("id:"+data.id+"\nname:"+data.name+"\nstatus:"
  33. +data.status);
  34. },
  35. error:function(){
  36. alert('Err...');
  37. }
  38. });

Table
Html代码 收藏代码
  1. <table>
  2. <tr>
  3. <td>id</td>
  4. <td><inputid="id"value="100"/></td>
  5. </tr>
  6. <tr>
  7. <td>name</td>
  8. <td><inputid="name"value="snowolf"/></td>
  9. </tr>
  10. <tr>
  11. <td>status</td>
  12. <td><inputid="status"value="true"/></td>
  13. </tr>
  14. <tr>
  15. <td><inputtype="button"id="profile"value="Profile——GET"/></td>
  16. <td><inputtype="button"id="login"value="Login——POST"/></td>
  17. </tr>
  18. </table>


四、简单测试

Get方式测试:




Post方式测试:




五、常见错误
POST操作时,我用$.post()方式,屡次失败,一直报各种异常:


引用
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported

直接用$.post()直接请求会有点小问题,尽管我标识为 json 协议,但实际上提交的 ContentType 还是 application/x-www-form-urlencoded 。需要使用$.ajaxSetup()标示下 ContentType
Js代码 收藏代码
  1. functionlogin(){
  2. varmydata='{"name":"'+$('#name').val()+'","id":"'
  3. +$('#id').val()+'","status":"'+$('#status').val()+'"}';
  4. alert(mydata);
  5. $.ajaxSetup({
  6. contentType:'application/json'
  7. });
  8. $.post('http://localhost:8080/spring-json/json/person/login',mydata,
  9. function(data){
  10. alert("id:"+data.id+"\nname:"+data.name
  11. +"\nstatus:"+data.status);
  12. },'json');
  13. };

效果是一样!