当前位置: 首页 > 知识库问答 >
问题:

接受/返回 XML/JSON 请求和响应 - Spring MVC

丰辰沛
2023-03-14

我需要编写一个 rest 服务,它接受 XML/JSON 作为输入(POST 方法)和 XML/JSON 作为输出(基于输入格式)。我尝试了以下方法来实现这一目标,但没有帮助。终结点方法同时接受 XML/JSON,但在响应时,它始终根据 @RequestMapping -produces 中指定的顺序提供 JSON 或 XML。任何帮助将不胜感激。

我的endpoint方法:

@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班:学生.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;
    }
}

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

<?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>

Json输入:

{
"id":2014,
"name":"test",
"graduationtime":"09/05/2014",
"courses":[
{
"courseName":"Math",
"score":150
},
{
"courseName":"Che",
"score":150
}
]
}

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>

共有3个答案

陶鹏
2023-03-14

注册一个拦截每个请求的过滤器,将HttpServletRequest扭曲为HttpServletRequest estWrapper的实现,并返回接受标头的Content-Type值。例如,您可以注册一个名为SameInSameOutFilter的过滤器,如下所示:

@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);
    }
}

它将当前请求包装在<code>SameInSameOutRequest<code>中:

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根据请求的< code>Content-Type值选择一个< code > HttpMessageConverter 。如果请求正文的< code>Content-Type是< code>application/xml,则响应将是< code>XML。否则,响应将是< code>JSON。

另一种解决方案是在每个请求中手动设置接受标头以及Content-Type并避免所有这些黑客攻击。

翁昊乾
2023-03-14

补充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;
}
公孙智
2023-03-14

使用同一个控制器处理不同数据格式的最佳实践是让框架完成确定编组和解编组机制的所有工作。

步骤1:使用最小控制器配置

@RequestMapping(value = "/getxmljson", method = RequestMethod.POST)
@ResponseBody
public Student processXMLJsonRequest(@RequestBody Student student) {
  return student;
}

这里不需要指定消耗产生。例如,考虑到您可能希望将来使用相同的方法来处理其他格式,例如Google协议缓冲区、EDI等。使控制器免于消耗产生将允许您通过全局配置添加数据格式,而不必修改控制器代码。

步骤 2:使用 ContentNegotiatingViewResolver 而不是 RequestMappingHandlerAdapter

  <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="defaultViews">
      <list>
        <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
      </list>
    </property>
  </bean>

让视图解析器决定如何读取传入的数据以及如何写回。

步骤 3:使用接受内容类型 HTTP 标头

用正确的HTTP头值访问您的控制器将强制< code > contentnegotiatingviewrolver 使用适当的数据表示自动封送和解封送数据。

如果您想以JSON格式交换数据,请将两个头设置为<code>application/JSON</code>。如果希望使用XML,请将两者设置为<code>application/XML</code>。

如果您不想使用HTTP头(理想情况下您应该使用),您可以简单地添加< code >。json或< code >。xml转换为URL,而< code > contentnegotiatingviewrolver 将完成剩下的工作。

您可以查看我使用您的代码片段创建的示例应用程序,这些代码片段适用于JSON和XML。

 类似资料:
  • 本文向大家介绍playframework Java:接受JSON请求,包括了playframework Java:接受JSON请求的使用技巧和注意事项,需要的朋友参考一下 示例            

  • 我正在尝试对远程服务器进行api调用,最初,我遇到以下错误:

  • 我有一个使用swagger UI的swagger标记文档,它总是返回text/html,但应该返回application/json。POST请求和其他类型返回Application/JSON,但这个特定的GET请求不返回。服务endpoint代码正确。如果我将请求更改为POST,它将返回application/json。因此,在swagger中只有type GET不返回正确的类型。有什么想法,如何

  • 问题内容: 我正在使用Node的模块发出 HTTP 请求,但是在上,返回的块似乎并不满足完整的请求响应。这是我的代码: 有没有办法在结束请求之前等待完整的输出?难道我做错了什么?谢谢! 问题答案: 您还应该收听“结束”事件

  • 我见过龙卷风文档和示例,其中self.write方法被广泛用于在超文本标记语言上呈现一些值,其中POST请求在处理程序中运行。但是我找不到关于如何将响应返回给客户的清晰信息。 例如,我正在从我的客户端调用Tornado服务器上的POST请求。接受post请求的代码为: 有了这个,我可以找到cbtp的值,有了,我可以用HTML打印它。但是,相反,我想以JSON格式将这个值返回给客户机,比如我想知道如

  • 在实现之前,我正在考虑生成REST API的JSON响应的结构。我在SO上浏览了许多问答,阅读了许多文章、推荐和伪标准。 要求 通知客户一些有用的元信息-HTTP状态代码等。 分页和过滤信息-偏移,限制和过滤查询(API客户端知道影响结果的所有参数)。 关于数据采集的信息-集合中的总记录计数和返回项的数量。API客户端然后能够创建分页。 上一页和下一页的链接(只是考虑,不确定这是否适用于API客户