2016-02-08 16 views
6

Potrzebuję napisać usługę spoczynku, która akceptuje XML/JSON jako dane wejściowe (metoda POST) i XML/JSON jako dane wyjściowe (w oparciu o format wejściowy). Próbowałem poniżej, aby to osiągnąć, ale nie pomogło.Endpoint metoda akceptuje zarówno XML/JSON, ale podczas odpowiadania zawsze daje JSON lub XML na podstawie kolejności określonej w @RequestMapping -produces. Każda pomoc będzie naprawdę doceniana .Przyjmowanie/zwracanie żądania i odpowiedzi XML/JSON - Spring MVC

Mój końcowy metoda:

@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 Klasa: 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; 
    } 
} 

POJO Klasa: 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; 
    } 
} 

wiosna-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 Wejście:

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

XML wejściowe:

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

Sprawdź tę próbkę. http://howtodoinjava.com/spring/spring-restful/spring-rest-hello-world-xml-example/ –

Odpowiedz

0

Zarejestruj filtr, który przechwytuje każdy wniosek wypaczać HttpServletRequest do implementacji HttpServletRequestWrapper i zwraca wartość Content-Type dla Accept cel. Na przykład, można zarejestrować filtr o nazwie SameInSameOutFilter jak następuje:

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

To owija aktualny wniosek w 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); 
    } 
} 

Owijka ta opowiada MVC wiosny, aby wybrać HttpMessageConverter oparta na życzenie za Content-Type wartości. Jeśli jednostka żądania o numerze Content-Type to application/xml, odpowiedź będzie miała postać XML. W przeciwnym razie odpowiedź będzie wynosić JSON.

Drugim rozwiązaniem jest ręczne ustawienie nagłówka Accept wraz z Content-Type w każdym żądaniu i unikanie tych wszystkich hacków.

13

Najlepszą praktyką w zakresie obsługi różnych formatów danych za pomocą tego samego kontrolera jest umożliwienie ramom wykonania wszystkich prac związanych z ustaleniem mechanizmów rozrządowych i likwidujących.

Krok 1 Use minimalna konfiguracja kontrolera

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

Nie ma potrzeby, aby określić consumes i produces tutaj. Jako przykład możesz wziąć pod uwagę, że ta sama metoda może obsługiwać inne formaty w przyszłości, takie jak bufory protokołów Google, EDI itp. Pozostawienie kontrolerów wolnych od consumes i produces pozwoli Ci dodawać formaty danych poprzez globalną konfigurację zamiast konieczności zmodyfikuj kod kontrolera.

Krok 2 Use ContentNegotiatingViewResolver zamiast 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> 

Niech widok rezolwer zdecydować, jak odczytać dane przychodzące i jak napisać go z powrotem.

Krok 3 Use Accepts i Content-Type nagłówki HTTP

uderzania kontrolera z prawidłowymi wartościami nagłówek HTTP zmusi ContentNegotiatingViewResolver do organizowania i dane unmarshal automatycznie stosując odpowiednie reprezentacje danych.

Jeśli chcesz wymieniać dane w formacie JSON, ustaw oba nagłówki na application/json. Jeśli chcesz zamiast tego XML, ustaw zarówno na application/xml.

Jeśli nie chcesz używać nagłówków HTTP (które najlepiej powinieneś), możesz po prostu dodać .json lub .xml do adresu URL, a ContentNegotiatingViewResolver zrobi resztę.


Możesz sprawdzić my sample app że utworzony przy użyciu fragmentów kodu, który działa dobrze dla JSON i XML.

+0

Potrzebowałby dodatkowo org.springframework.web.servlet.view.xml.MappingJackson2XmlView do obsługi XML. – anre

4

Dodawanie do odpowiedzi Manish jest wyżej, jeśli nie chce stosować xml użyć konfiguracji oparty tej konfiguracji Java instead-

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

i stoi ten sam problem jak twój. Poniżej znajduje się moje rozwiązanie i przykład.

Poniżej jest zależność, że trzeba to:

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

dyspozytor-servlet.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> 

i mój @RequestMapping (można użyć własnego mapowania żądanie)

@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 ; 
    } 
Powiązane problemy