接受/返回XML / JSON请求和响应 – Spring MVC
我需要编写一个rest服务,它接受XML / JSON作为输入(POST方法)和XML / JSON作为输出(基于输入格式)。 我尝试过以下方法来实现这一点,但没有帮助.Endpoint方法同时接受XML / JSON但在响应时它总是根据@RequestMapping -produces中指定的顺序提供JSON或XML.Any help将非常感谢。
我的端点方法:
@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 courses = new ArrayList(); @XmlElement public int getId() { return id; } @XmlElement public String getName() { return name; } @XmlElement public String getGraduationTime() { return graduationTime; } @XmlElement public ArrayList 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 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; } }
POJO课程:Course.java
import java.io.Serializable; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @XmlRootElement(name = "course") @XmlType(propOrder = {"courseName", "score"}) @JsonPropertyOrder({"courseName", "score"}) public class Course implements Serializable { private static final long serialVersionUID = 1L; private String courseName; private Integer score; public @XmlElement String getCourseName() { return courseName; } public @XmlElement Integer getScore() { return score; } public void setCourseName(String value) { courseName = value; } public void setScore(Integer value) { score = value; } public Course() {} public Course(String courseName, Integer score) { this.courseName = courseName; this.score = score; } }
spring-config.xml中
Json输入:
{ "id":2014, "name":"test", "graduationtime":"09/05/2014", "courses":[ { "courseName":"Math", "score":150 }, { "courseName":"Che", "score":150 } ] }
XML输入:
2014 test 09/05/2014 Math 150 Che 150
使用相同控制器处理不同数据格式的最佳实践是让框架完成计算编组和解组机制的所有工作。
第1步 :使用最小控制器配置
@RequestMapping(value = "/getxmljson", method = RequestMethod.POST) @ResponseBody public Student processXMLJsonRequest(@RequestBody Student student) { return student; }
这里没有必要指定consumes
和produces
。 例如,考虑到您可能希望将来使用相同的方法来处理其他格式,例如Google协议缓冲区,EDI等。保持控制器consumes
和produces
将允许您通过全局配置添加数据格式而不必修改控制器代码。
第2步 :使用
ContentNegotiatingViewResolver
而不是RequestMappingHandlerAdapter
让视图解析器决定如何读取传入数据以及如何将其写回。
第3步 :使用
Accepts
和Content-Type
HTTP标头
使用正确的HTTP标头值命中控制器将强制ContentNegotiatingViewResolver
使用适当的数据表示自动编组ContentNegotiatingViewResolver
数据。
如果要以JSON格式交换数据,请将两个标头都设置为application/json
。 如果您想要XML,请将它们都设置为application/xml
。
如果您不想使用HTTP标头(理想情况下应该这样),您只需将ContentNegotiatingViewResolver
或.xml
添加到URL中, ContentNegotiatingViewResolver
将完成剩下的工作。
您可以查看我使用您的代码片段创建的示例应用程序 ,该代码片段适用于JSON和XML。
除了Manish上面的答案,如果你不想使用基于xml的配置,请使用这个基于java的配置代替 –
@Bean public ViewResolver contentNegotiatingViewResolver() { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver(); List views = new ArrayList<>(); views.add(new MappingJackson2XmlView()); views.add(new MappingJackson2JsonView()); resolver.setDefaultViews(views); return resolver; }
注册拦截每个请求的filter,将HttpServletRequest
扭曲为HttpServletRequest
的实现,并返回Accept
头的Content-Type
值。 例如,您可以注册名为SameInSameOutFilter
的filter,如下所示:
@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); } }
这个包装器告诉spring mvc根据请求的Content-Type
值选择一个HttpMessageConverter
。 如果请求主体的Content-Type
是application/xml
,则响应将是XML
。 否则,响应将是JSON
。
另一种解决方案是在每个请求中手动设置Accept
标头和Content-Type
,并避免所有这些黑客攻击。
我面临着和你一样的问题。 以下是我的解决方案和样本。
以下是您需要包含的maven依赖项:
com.fasterxml.jackson.core jackson-core 2.4.3 com.fasterxml.jackson.core jackson-databind 2.4.3 com.fasterxml.jackson.core jackson-annotations 2.4.3 com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.4.3
调度员servlet.xml中
和我的@RequestMapping(您可以使用自己的请求映射)
@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 ; }
如果需要application/xml
则必须存在以下标题
Content-Type:application/xml Accept:application/xml