Spring RESTful服务接收和返回JSON最佳实践
2014-04-20 16:50
405 查看
Spring RESTful服务接收和返回JSON最佳实践
博客分类:Spring
SpringRESTful返回JSON接收JSON最佳实践
个人学习参考所用,勿喷!
返回JSON
1) 用Maven构建web项目:
构建过程参考limingnihao的blog(写得相当的详细!!!):使用Eclipse构建Maven的SpringMVC项目
注解@ResponseBody可以将结果(一个包含字符串和JavaBean的Map),转换成JSON。由于Spring是采用对JSON进行了封装的jackson来生成JSON和返回给客户端,所以这里需要添加jackson的相关包。项目的pom.xml配置如下:
Xml代码
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.watson</groupId>
<artifactId>rest-spring</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>rest-spring Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- 省略其他配置,具体可以参考附件-->
......
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
</project>
2) 在web.xml配置Spring的请求处理的Servlet,具体设置:
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Spring-Rest</display-name>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/rest-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3) 在rest-servlet.xml中配置如下:
Xml代码
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.mkyong.common.controller" />
<mvc:annotation-driven />
</beans>
为了解决乱码问题,需要添加如下配置,并且这里可以显示的添加MappingJacksonHttpMessageConverter这个转换器。
Xml代码
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>
4) 编写自己的服务组件类,使用MVC的annotation风格,使用@ResponseBody处理返回值。具体代码如下:
Java代码
@RequestMapping("/jsonfeed")
public @ResponseBody Object getJSON(Model model) {
List<TournamentContent> tournamentList = new ArrayList<TournamentContent>();
tournamentList.add(TournamentContent.generateContent("FIFA", new Date(), "World Cup", "www.fifa.com/worldcup/"));
tournamentList.add(TournamentContent.generateContent("FIFA", new Date(), "U-20 World Cup", "www.fifa.com/u20worldcup/"));
tournamentList.add(TournamentContent.generateContent("FIFA", new Date(), "U-17 World Cup", "www.fifa.com/u17worldcup/"));
tournamentList.add(TournamentContent.generateContent("中超", new Date(), "中超", "www.fifa.com/confederationscup/"));
model.addAttribute("items", tournamentList);
model.addAttribute("status", 0);
return model;
}
5)将运行项目,在浏览器中输入http://[host]:[port]/[appname]/jsonfeed.json,例如楼主的实例中输入如下:http://localhost:7070/rest-spring/jsonfeed/,得到结果为:
Json代码
{"status":0,"items":[{"name":"World Cup","id":8,"link":"www.fifa.com/worldcup/","author":"FIFA","publicationDate":1334559460940},{"name":"U-20 World Cup","id":9,"link":"www.fifa.com/u20worldcup/","author":"FIFA","publicationDate":1334559460940},{"name":"U-17 World Cup","id":10,"link":"www.fifa.com/u17worldcup/","author":"FIFA","publicationDate":1334559460940},{"name":"Confederations Cup","id":11,"link":"www.fifa.com/confederationscup/","author":"FIFA","publicationDate":1334559460940}]}
这里我们也可以利用Spring3MVC中对试图和内容协商的方法来处理返回JSON的情况,下面步骤接上面第2步:
3) 在rest-servlet.xml中对相关进行具体的设置:
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 自动搜索@Controller标注的类,包括其下面的子包 -->
<context:component-scan base-package="com.watson.rest" />
<!-- 根据客户端的不同的请求决定不同的view进行响应, 如 /blog/1.json /blog/1.xml -->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<!-- 设置为true以忽略对Accept Header的支持 -->
<property name="ignoreAcceptHeader" value="true" />
<!-- 在没有扩展名时即: "/blog/1" 时的默认展现形式 -->
<property name="defaultContentType" value="text/html" />
<!-- 扩展名至mimeType的映射,即 /blog.json => application/json -->
<property name="mediaTypes">
<map>
<entry key="html" value="text/html" />
<entry key="pdf" value="application/pdf" />
<entry key="xsl" value="application/vnd.ms-excel" />
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</map>
</property>
<!-- 用于开启 /blog/123?format=json 的支持 -->
<property name="favorParameter" value="false" />
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/pages" />
<property name="suffix" value=".jsp"></property>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<!-- for application/json -->
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<!-- for application/xml -->
<!--
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller">
<bean class="org.springframework.oxm.xstream.XStreamMarshaller"/>
</property>
</bean>
-->
</list>
</property>
</bean>
</beans>
4)编写自己的服务组件类,使用MVC的annotation风格,这里可以不再使用@ResponseBody断言。具体代码如下:
Java代码
//FINAL
package com.watson.rest.json;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.watson.rest.feeds.TournamentContent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
public class FeedController {
@RequestMapping("/jsonfeed")
public String getJSON(Model model) {
List<TournamentContent> tournamentList = new ArrayList<TournamentContent>();
tournamentList.add(TournamentContent.generateContent("FIFA", new Date(), "World Cup", "www.fifa.com/worldcup/"));
tournamentList.add(TournamentContent.generateContent("FIFA", new Date(), "U-20 World Cup", "www.fifa.com/u20worldcup/"));
tournamentList.add(TournamentContent.generateContent("FIFA", new Date(), "U-17 World Cup", "www.fifa.com/u17worldcup/"));
tournamentList.add(TournamentContent.generateContent("FIFA", new Date(), "Confederations Cup", "www.fifa.com/confederationscup/"));
model.addAttribute("items", tournamentList);
model.addAttribute("status", 0);
return "jsontournamenttemplate";
}
}
这里的TournamentContent是自定义的POJO类:
Java代码
public class TournamentContent {
private static int idCounter = 0;
private String author;
private Date publicationDate;
private String name;
private String link;
private int id;
public static TournamentContent generateContent(String author, Date date, String name, String link) {
TournamentContent content = new TournamentContent();
content.author = author;
content.publicationDate = date;
content.name = name;
content.link = link;
content.id = idCounter++;
return content;
}
//省略getter、setter
}
5)将运行项目,在浏览器中输入http://[host]:[port]/[appname]/jsonfeed.json,例如楼主的实例中输入如下:http://localhost:7070/rest-spring/jsonfeed.json,得到结果为:
Json代码
{"status":0,"items":[{"name":"World Cup","id":8,"link":"www.fifa.com/worldcup/","author":"FIFA","publicationDate":1334559460940},{"name":"U-20 World Cup","id":9,"link":"www.fifa.com/u20worldcup/","author":"FIFA","publicationDate":1334559460940},{"name":"U-17 World Cup","id":10,"link":"www.fifa.com/u17worldcup/","author":"FIFA","publicationDate":1334559460940},{"name":"Confederations Cup","id":11,"link":"www.fifa.com/confederationscup/","author":"FIFA","publicationDate":1334559460940}]}
至此,Spring RESTful服务返回JSON的实践基本完成(因为这里对EXCEPTION的处理还够)。个人认为第一种方式更加适合一般的使用,特别是显示的添加MappingJacksonHttpMessageConverter这个转换器和对乱码的处理。
接收JSON
使用 @RequestBody 注解前台只需要向 Controller 提交一段符合格式的 JSON,Spring 会自动将其拼装成 bean。
1)在上面的项目中使用第一种方式处理返回JSON的基础上,增加如下方法:
Java代码
@RequestMapping(value="/add",method=RequestMethod.POST)
@ResponseBody
public Object addUser(@RequestBody User user)
{
System.out.println(user.getName() + " " + user.getAge());
return new HashMap<String, String>().put("success", "true");
}
这里的POJO如下:
Java代码
public class User {
private String name;
private String age;
//getter setter
}
2)而在前台,我们可以用 jQuery 来处理 JSON。从这里,我得到了一个 jQuery 的插件,可以将一个表单的数据返回成JSON对象:
Js代码
$.fn.serializeObject = function(){
var o = {};
var a = this.serializeArray();
$.each(a, function(){
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
}
else {
o[this.name] = this.value || '';
}
});
return o;
};
以下是使用 jQuery 接收、发送 JSON 的代码:
Js代码
$(document).ready(function(){
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: 'jsonfeed.do',
dataType: 'json',
success: function(data){
if (data && data.status == "0") {
$.each(data.data, function(i, item){
$('#info').append("姓名:" + item.name +",年龄:" +item.age);
});
}
},
error: function(){
alert("error")
}
});
$("#submit").click(function(){
var jsonuserinfo = $.toJSON($('#form').serializeObject());
jQuery.ajax({
type: 'POST',
contentType: 'application/json',
url: 'add.do',
data: jsonuserinfo,
dataType: 'json',
success: function(data){
alert("新增成功!");
},
error: function(){
alert("error")
}
});
});
});
但是似乎用Spring这套东西真是个麻烦的事情,相对Jersey对RESTful的实现来看,确实有很多不简洁的地方。
参考:
官方文档:http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch18.html
badqiu的BOLG:《spring REST中的内容协商(同一资源,多种展现:xml,json,html)》
liuweifeng的BOLG:http://blog.liuweifeng.net/archives/407
Gary Mark等的书籍:《Spring Recipes》2ed
rest-spring.zip (14.3 KB)
下载次数: 470
分享到:
Spring3 MVC的最佳实践和理解(1) |
Spring的JNDI数据源连接池配置示例及Spring ...
2012-04-16 17:13
浏览 11248
评论(4)
分类:开源软件
相关推荐
评论
4 楼
kingxss 2014-02-11
wlkfec 写道
有一个小问题,就是配置默认的视图MappingJacksonJsonView的时候,报错:Could not instantiate bean class [org.springframework.web.servlet.view.json.MappingJacksonJsonView]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/codehaus/jackson/Versioned
可是查看文档,这个类本来就是一个无参数的构造方法,这是什么情况
你好,这是个没有找到类的BUG,很常见。原因是没有加入需要的jar,或者jar的版本不对。
3 楼
wlkfec 2014-02-09
有一个小问题,就是配置默认的视图MappingJacksonJsonView的时候,报错:Could not instantiate bean class [org.springframework.web.servlet.view.json.MappingJacksonJsonView]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/codehaus/jackson/Versioned
可是查看文档,这个类本来就是一个无参数的构造方法,这是什么情况
2 楼
z_04915231 2013-12-10
1 楼
lc7183627 2013-10-11
我怎么缺一些类?
相关文章推荐
- Spring RESTful服务接收和返回JSON最佳实践
- Spring RESTful服务接收和返回JSON最佳实践
- Spring RESTful服务接收和返回JSON最佳实践
- Spring RESTful服务接收和返回JSON最佳实践
- Spring RESTful服务接收和返回JSON最佳实践
- Spring RESTful服务接收和返回JSON最佳实践
- Spring RESTful服务接收和返回JSON最佳实践
- Atitit.列表页面and条件查询的实现最佳实践(1)------设置查询条件and提交查询and返回json数据
- Atitit.列表页面and条件查询的实现最佳实践(1)------设置查询条件and提交查询and返回json数据
- Atitit.列表页and查询条件的最佳实践(1)------设定搜索条件and提交查询and返回json数据
- 构建基于JSON的Web服务最佳实践
- 云计算之openstack(N版)Nova计算服务最佳实践
- WCF与AJAX编程开发实践(4):支持JSON的Ajax WCF服务
- Windows Azure 安全最佳实践 - 第 6 部分:Azure 服务如何扩展应用程序安全性
- SOA最佳实践之构建数据服务层
- 用springMVC构建restful程序,接收以及返回json数据格式
- RESTful服务最佳实践——(九)
- 轻量级微服务架构及最佳实践
- Spring最佳实践-9.1 集成邮件服务
- 设计微服务的最佳实践