Java 接受/返回XML/JSON请求和响应-Spring MVC
我需要编写一个rest服务,它接受XML/JSON作为输入(POST方法),接受XML/JSON作为输出(基于输入格式)。我尝试了下面的方法来实现这一点,但没有帮助。Endpoint方法接受XML/JSON,但在响应时,它总是根据@RequestMapping-Products中指定的顺序提供JSON或XML。任何帮助都将不胜感激 我的端点方法:Java 接受/返回XML/JSON请求和响应-Spring MVC,java,json,xml,spring,spring-mvc,Java,Json,Xml,Spring,Spring Mvc,我需要编写一个rest服务,它接受XML/JSON作为输入(POST方法),接受XML/JSON作为输出(基于输入格式)。我尝试了下面的方法来实现这一点,但没有帮助。Endpoint方法接受XML/JSON,但在响应时,它总是根据@RequestMapping-Products中指定的顺序提供JSON或XML。任何帮助都将不胜感激 我的端点方法: @RequestMapping(value = "/getxmljson", method = RequestMethod.POST,produces
@RequestMapping(value = "/getxmljson", method = RequestMethod.POST,produces={"application/json","application/xml"},
consumes={"application/json", "application/xml"})
public @ResponseBody Student processXMLJsonRequest(@RequestBody Student student)
throws Exception {
System.out.println("*************Inside Controller");
return student;
}
POJO类:Student.java
import java.io.Serializable;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@XmlRootElement(name = "student")
@XmlType(propOrder = {"id", "name", "graduationTime", "courses"})
@JsonPropertyOrder({"id", "name", "graduationTime", "courses"})
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private String graduationTime;
private ArrayList<Course> courses = new ArrayList<Course>();
@XmlElement
public int getId() { return id; }
@XmlElement
public String getName() { return name; }
@XmlElement
public String getGraduationTime() { return graduationTime; }
@XmlElement
public ArrayList<Course> getCourses() { return courses; }
public void setId(int value) { this.id = value; }
public void setName(String value) { this.name = value; }
public void setGraduationTime(String value) { this.graduationTime = value; }
public void setCourses(ArrayList<Course> value) { this.courses = value; }
@JsonIgnore
public String toString() {
return this.name + " - "
+ graduationTime == null? "Unknown" : graduationTime.toString();
}
public Student() {}
public Student(int id, String name, String graduationTime) {
this.id = id;
this.name = name;
this.graduationTime = graduationTime;
}
}
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Configure to plugin JSON as request and response in method handler -->
<beans:bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter" />
<beans:ref bean="xmlMessageConverter" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</beans:bean>
<beans:bean id="xmlMessageConverter"
class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter">
</beans:bean>
<beans:bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
</beans:bean>
<beans:bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
<context:component-scan base-package="com.test" />
</beans:beans>
XML输入:
<?xml version="1.0" encoding="UTF-8" ?>
<student>
<id>2014</id>
<name>test</name>
<graduationTime>09/05/2014</graduationTime>
<courses>
<courseName>Math</courseName>
<score>150</score>
</courses>
<courses>
<courseName>Che</courseName>
<score>150</score>
</courses>
</student>
2014
测试
09/05/2014
数学
150
胆碱酯酶
150
注册拦截每个请求的筛选器,将HttpServletRequest
扭曲到HttpServletRequestWrapper
的实现中,并返回接受
头的内容类型
值。例如,您可以注册一个名为sameinsameofilter
的过滤器,如下所示:
@Component
public class SameInSameOutFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
SameInSameOutRequest wrappedRequest = new SameInSameOutRequest((HttpServletRequest) request);
chain.doFilter(wrappedRequest, response);
}
}
它将当前请求包装在一个SameInSameOutRequest
中:
public class SameInSameOutRequest extends HttpServletRequestWrapper {
public SameInSameOutRequest(HttpServletRequest request) {
super(request);
}
@Override
public String getHeader(String name) {
if (name.equalsIgnoreCase("accept")) {
return getContentType();
}
return super.getHeader(name);
}
}
这个包装器告诉SpringMVC根据请求的内容类型
值选择一个HttpMessageConverter
。如果请求主体的内容类型
是application/xml
,那么响应将是xml
。否则,响应将是JSON
另一种解决方案是在每个请求中手动设置
Accept
头和内容类型
,并避免所有这些攻击。使用同一控制器处理不同数据格式的最佳实践是让框架完成所有确定编组和解编机制的工作
步骤1:使用最小控制器配置
这里不需要指定消耗
和产生
。作为一个例子,考虑到将来可能需要这种方法来处理其他格式,如谷歌协议缓冲区、EDI等。保持控制器不受<代码>消耗<代码> >代码>产生将允许您通过全局配置添加数据格式,而不必修改控制器代码。
步骤2:使用ContentNegotiatingViewResolver
而不是RequestMappingHandlerAdapter
让视图解析器决定如何读取传入数据以及如何将其写回
步骤3:使用接受
和内容类型
HTTP头
使用正确的HTTP头值点击控制器将强制contentnegotingviewresolver
使用适当的数据表示自动封送和解封送数据
如果要以JSON格式交换数据,请将两个标题都设置为application/JSON
。如果您想要XML,则将两者都设置为application/XML
如果您不想使用HTTP头(理想情况下您应该这样做),您可以简单地将.json
或.xml
添加到URL,然后ContentNegotiatingViewResolver
将完成其余工作
您可以查看我使用您的代码片段创建的,这些代码片段对JSON和XML都很好。添加到上面Manish的答案中,如果您不想使用基于XML的配置,请使用此基于java的配置-
@Bean
public ViewResolver contentNegotiatingViewResolver() {
ContentNegotiatingViewResolver resolver =
new ContentNegotiatingViewResolver();
List<View> views = new ArrayList<>();
views.add(new MappingJackson2XmlView());
views.add(new MappingJackson2JsonView());
resolver.setDefaultViews(views);
return resolver;
}
@Bean
公共视图解析程序contentnegotingviewresolver(){
ContentNegotingViewResolver解析程序=
新内容NegotiatingViewResolver();
列表视图=新建ArrayList();
添加(新映射jackson2xmlview());
添加(新映射jackson2jsonview());
resolver.setDefaultViews(视图);
返回解析器;
}
我和你面临着同样的问题。下面是我的解决方案和示例
以下是您需要包括的maven依赖项:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.4.3</version>
</dependency>
如果需要application/xml
,则必须显示以下标题
Content-Type:application/xml
Accept:application/xml
如果资源定义如下:
@GET
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Student getStudent(@PathParam("id") String id) {
return student(); // logic to retunrs student object
}
那么请求应该包含“accept”头('application/json'或application/xml'),然后返回json或xml格式的响应 样本请求:
curl -k -X GET -H "accept: application/json" "https://172.17.0.5:8243/service/1.0/222"
学生样本班
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "student")
public class Student {
private int id;
private String name;
private String collegeName;
private int age;
@XmlAttribute
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement
public String getCollegeName() {
return collegeName;
}
public void setCollegeName(String collegeName) {
this.collegeName = collegeName;
}
public int getAge() {
return age;
}
@XmlElement
public void setAge(int age) {
this.age = age;
}
}
看看这个样品。还需要org.springframework.web.servlet.view.xml.MappingJackson2XmlView来处理xml。
<mvc:annotation-driven
content-negotiation-manager="contentManager" />
<bean id="contentManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="ignoreAcceptHeader" value="false" />
<property name="defaultContentType" value="application/json" />
<property name="useJaf" value="false" />
</bean>
@RequestMapping(value = "/testXMLJSON",
method = RequestMethod.GET, produces = {
MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
public ArtworkContentMessageType testXMLJSON()
{
//this is GS1 xml standard mapping.
ArtworkContentMessageType resp = new ArtworkContentMessageType();
StandardBusinessDocumentHeader standarBusinessDocumentHeader = new StandardBusinessDocumentHeader();
resp.setStandardBusinessDocumentHeader(standarBusinessDocumentHeader );
ArtworkContentType artWorkContent = new ArtworkContentType();
resp.getArtworkContent().add(artWorkContent);
return resp ;
}
Content-Type:application/xml
Accept:application/xml
@GET
@Path("/{id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Student getStudent(@PathParam("id") String id) {
return student(); // logic to retunrs student object
}
curl -k -X GET -H "accept: application/json" "https://172.17.0.5:8243/service/1.0/222"
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "student")
public class Student {
private int id;
private String name;
private String collegeName;
private int age;
@XmlAttribute
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement
public String getCollegeName() {
return collegeName;
}
public void setCollegeName(String collegeName) {
this.collegeName = collegeName;
}
public int getAge() {
return age;
}
@XmlElement
public void setAge(int age) {
this.age = age;
}
}