首先,我们回顾下,在基于Spring的RESTful的项目中如果你使用这种形式的URL:
http://localhost:8888/myapp/service/xxx/{id} 那么一般情况下,你会被导向到一个HTML页面。如果你想让它返回一个JSON格式或者XML格式的数据,那么你不得不在前台做一番格式转换的处理。 现在,你只需要在你的spring-servlet.xml文件里面配置一下就可以了。 先看配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www./schema/beans" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:p="http://www./schema/p" xmlns:mvc="http://www./schema/mvc" xmlns:context="http://www./schema/context" xsi:schemaLocation=" http://www./schema/beans http://www./schema/beans/spring-beans-3.0.xsd http://www./schema/context http://www./schema/context/spring-context-3.0.xsd http://www./schema/mvc http://www./schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="com.homeland.myapp.controller" /> <mvc:annotation-driven /> <mvc:resources location="/images/" mapping="/images/**" /> <mvc:resources location="/js/" mapping="/js/**" /> <mvc:resources location="/css/" mapping="/css/**" /> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="1" /> <property name="favorParameter" value="false" /> <property name="ignoreAcceptHeader" value="true" /> <property name="defaultContentType" value="text/html" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/page/" /> <property name="suffix" value=".jsp" /> </bean> </list> </property> <property name="defaultViews"> <list> <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> <bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>com.homeland.myapp.entity.Employee</value> </list> </property> </bean> </constructor-arg> </bean> </list> </property> </bean> </beans>
21行:viewResolver的顺序 22行:是一个格式化的开关,类似http://localhost:8888/myapp/service/{id}?format=json这种 23行:忽略请求头中的Accept 25行:默认的数据返回格式 26行~31行:配置媒体类型与扩展名的映射关系,也即将Content-Type=application/json的内容映射到http://localhost:8888/myapp/service/{id}.json这种格式 32行~42行:配置你的ViewResolver 42行~60行:配置数据格式的转换器 数据格式的转换器部分,需要说的是,在spring的包里面有2个不同的类:
这两个类对应到pom.xml文件是不同的包,先说第一个: 用第一个类你的JSON解析器是这样的:
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.13</version> </dependency> 用第二个类你的JSON解析器是这样的:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.2.2</version> </dependency>
此外,我配置的XML解析器是:
org.springframework.oxm.jaxb.Jaxb2Marshaller 如果你使用JAXB来绑定,那么你的entity类的annotation是这样的:
package com.homeland.myapp.entity; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @Entity @Table(name = "employee") @XmlRootElement(name = "employee") public class Employee implements Serializable { private static final long serialVersionUID = -8869011840496785130L; @Id @SequenceGenerator(name = "seq_employee_id", allocationSize = 1, initialValue = 1, sequenceName = "seq_employee_id") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_employee_id") private int id; @Column(name = "first_name", length = 60, nullable = false) private String firstname; @Column(name = "last_name", length = 60, nullable = false) private String lastname; @Column(name = "full_name", length = 120, nullable = false) private String fullname; @Column(name = "age", length = 3, nullable = false) private int age; @Column(name = "sex", length = 1, nullable = false) private int sex; @Column(name = "email", length = 255, nullable = false) private String email; @Column(name = "cell_phone", length = 15, nullable = false) private String cellphone; @Column(name = "department_id", nullable = false) private int departmentId; @Column(name = "role_id", nullable = false) private int roleId; public Employee() {} public int getId() { return id; } @XmlElement public void setId(int id) { this.id = id; } public String getFirstname() { return firstname; } @XmlElement public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } @XmlElement public void setLastname(String lastname) { this.lastname = lastname; } public String getFullname() { return fullname; } @XmlElement public void setFullname(String fullname) { this.fullname = fullname; } public int getAge() { return age; } @XmlElement public void setAge(int age) { this.age = age; } public int isSex() { return sex; } @XmlElement public void setSex(int sex) { this.sex = sex; } public int getSex() { return sex; } public String getEmail() { return email; } @XmlElement public void setEmail(String email) { this.email = email; } public String getCellphone() { return cellphone; } @XmlElement public void setCellphone(String cellphone) { this.cellphone = cellphone; } public int getDepartmentId() { return departmentId; } @XmlElement public void setDepartmentId(int departmentId) { this.departmentId = departmentId; } public int getRoleId() { return roleId; } @XmlElement public void setRoleId(int roleId) { this.roleId = roleId; } } 这里必须要说一下,如果你把@XmlElement放在property上面,会报错。这个很莫名其妙。根据错误信息,它判定有两个同名的属性,我猜测是因为在扫描文件的时候把方法也扫了。不知道为啥。所以,就把@XmlElement放在了setter()方法上。 但是,我们知道还有另外一个很好用的就是XStream解析器。 那么,如何使用XStream的话,配置文件要如何改呢?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www./schema/beans" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:p="http://www./schema/p" xmlns:mvc="http://www./schema/mvc" xmlns:context="http://www./schema/context" xsi:schemaLocation=" http://www./schema/beans http://www./schema/beans/spring-beans-3.0.xsd http://www./schema/context http://www./schema/context/spring-context-3.0.xsd http://www./schema/mvc http://www./schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="com.homeland.myapp.controller" /> <mvc:annotation-driven /> <mvc:resources location="/images/" mapping="/images/**" /> <mvc:resources location="/js/" mapping="/js/**" /> <mvc:resources location="/css/" mapping="/css/**" /> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="1" /> <property name="favorParameter" value="false" /> <property name="ignoreAcceptHeader" value="true" /> <property name="defaultContentType" value="text/html" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/page/" /> <property name="suffix" value=".jsp" /> </bean> </list> </property> <property name="defaultViews"> <list> <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> <bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <property name="marshaller"> <bean class="org.springframework.oxm.xstream.XStreamMarshaller"/> </property> </bean> </list> </property> </bean> </beans> 相对应的entity类的annotation也要改:
package com.homeland.myapp.entity; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; @Entity @Table(name = "employee") @XStreamAlias("employee") public class Employee implements Serializable { private static final long serialVersionUID = -8869011840496785130L; @Id @SequenceGenerator(name = "seq_employee_id", allocationSize = 1, initialValue = 1, sequenceName = "seq_employee_id") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_employee_id") @XStreamAsAttribute @XStreamAlias("id") private int id; @Column(name = "first_name", length = 60, nullable = false) @XStreamAsAttribute @XStreamAlias("first_name") private String firstname; @Column(name = "last_name", length = 60, nullable = false) @XStreamAsAttribute @XStreamAlias("last_name") private String lastname; @Column(name = "full_name", length = 120, nullable = false) @XStreamAsAttribute @XStreamAlias("full_name") private String fullname; @Column(name = "age", length = 3, nullable = false) @XStreamAsAttribute @XStreamAlias("age") private int age; @Column(name = "sex", length = 1, nullable = false) @XStreamAsAttribute @XStreamAlias("sex") private int sex; @Column(name = "email", length = 255, nullable = false) @XStreamAsAttribute @XStreamAlias("email") private String email; @Column(name = "cell_phone", length = 15, nullable = false) @XStreamAsAttribute @XStreamAlias("cell_phone") private String cellphone; @Column(name = "department_id", nullable = false) @XStreamAsAttribute @XStreamAlias("department_id") private int departmentId; @Column(name = "role_id", nullable = false) @XStreamAsAttribute @XStreamAlias("role_id") private int roleId; public Employee() {} public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getFullname() { return fullname; } public void setFullname(String fullname) { this.fullname = fullname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int isSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public int getSex() { return sex; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getCellphone() { return cellphone; } public void setCellphone(String cellphone) { this.cellphone = cellphone; } public int getDepartmentId() { return departmentId; } public void setDepartmentId(int departmentId) { this.departmentId = departmentId; } public int getRoleId() { return roleId; } public void setRoleId(int roleId) { this.roleId = roleId; } } 不过,用JAXB以及XStream其返回的数据样式也不完全一样。大家可以比较一下。 在使用Spring3自带的XStreamMarshaller的时候,你会发现如果你用了下划线("_")来链接属性名中的两个或多个单词的话,在最终的xml返回值中出现了双下划线("__")。 目前还不知道怎么解决。网上搜索了下,貌似要换marshaller了。当然,你也可以不用。以下代码告诉你,用好@XStreamAliases会让返回的XML好看一些:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www./schema/beans" xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:p="http://www./schema/p" xmlns:mvc="http://www./schema/mvc" xmlns:context="http://www./schema/context" xsi:schemaLocation=" http://www./schema/beans http://www./schema/beans/spring-beans-3.0.xsd http://www./schema/context http://www./schema/context/spring-context-3.0.xsd http://www./schema/mvc http://www./schema/mvc/spring-mvc-3.0.xsd"> <context:component-scan base-package="com.homeland.myapp.controller" /> <mvc:annotation-driven /> <mvc:resources location="/images/" mapping="/images/**" /> <mvc:resources location="/js/" mapping="/js/**" /> <mvc:resources location="/css/" mapping="/css/**" /> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="1" /> <property name="favorParameter" value="false" /> <property name="ignoreAcceptHeader" value="true" /> <property name="defaultContentType" value="text/html" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/page/" /> <property name="suffix" value=".jsp" /> </bean> </list> </property> <property name="defaultViews"> <list> <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> <bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <property name="marshaller"> <bean class="org.springframework.oxm.xstream.XStreamMarshaller"> <property name="autodetectAnnotations" value="true" /> <!-- <property name="aliases"> <map> <entry key="employee" value="com.homeland.myapp.entity.Employee" /> </map> </property> <property name="fieldAliases"> <map> <entry key="com.homeland.myapp.entity.Employee.firstname" value="first_name" /> </map> </property> --> </bean> </property> </bean> </list> </property> </bean> </beans> 在上面代码中注释部分相当于加了annotation的entity类: package com.homeland.myapp.entity; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import com.thoughtworks.xstream.annotations.XStreamAlias; @Entity @Table(name = "employee") @XStreamAlias("employee") public class Employee implements Serializable { private static final long serialVersionUID = -8869011840496785130L; @Id @SequenceGenerator(name = "seq_employee_id", allocationSize = 1, initialValue = 1, sequenceName = "seq_employee_id") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_employee_id") @XStreamAlias("id") private int id; @Column(name = "first_name", length = 60, nullable = false) @XStreamAlias("first-name") private String firstname; @Column(name = "last_name", length = 60, nullable = false) @XStreamAlias("last-name") private String lastname; @Column(name = "full_name", length = 120, nullable = false) @XStreamAlias("full-name") private String fullname; @Column(name = "age", length = 3, nullable = false) @XStreamAlias("age") private int age; @Column(name = "sex", length = 1, nullable = false) @XStreamAlias("sex") private int sex; @Column(name = "email", length = 255, nullable = false) @XStreamAlias("email") private String email; @Column(name = "cell_phone", length = 15, nullable = false) @XStreamAlias("cell-phone") private String cellphone; @Column(name = "department_id", nullable = false) @XStreamAlias("department-id") private int departmentId; @Column(name = "role_id", nullable = false) @XStreamAlias("role-id") private int roleId; public Employee() {} public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getFullname() { return fullname; } public void setFullname(String fullname) { this.fullname = fullname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int isSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public int getSex() { return sex; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getCellphone() { return cellphone; } public void setCellphone(String cellphone) { this.cellphone = cellphone; } public int getDepartmentId() { return departmentId; } public void setDepartmentId(int departmentId) { this.departmentId = departmentId; } public int getRoleId() { return roleId; } public void setRoleId(int roleId) { this.roleId = roleId; } }
双下划线神马的,换成短线(“-")吧! P.S: JSON格式的返回结果:
{"employee":{ "id":14, "firstname":"Jackson", "lastname":"Tom", "fullname":"tom.jackson", "age":33, "sex":1, "email":"tom.jackson@xxx.com", "cellphone":"86186xxxxxxx8", "departmentId":11, "roleId":11 } } XML格式的返回结果:
相应的controller代码:
package com.homeland.myapp.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.homeland.myapp.entity.Employee; import com.homeland.myapp.service.EmployeeService; import com.thoughtworks.xstream.XStream; @Controller public class EmployeeController { @Autowired private EmployeeService employeeService; @RequestMapping(method = RequestMethod.GET, value = "/employee/{id}") public Employee getEmployee(@PathVariable String id) { Employee e = employeeService.findById(Integer.parseInt(id)); return e; } @RequestMapping(method = RequestMethod.GET, value = "/employees") public List<Employee> getAllEmployee() { List<Employee> employees = employeeService.findAll(); return employees; } } |
|
来自: 瑶疏影 > 《SpringMvc》