Spring ответ mvc rest json и xml
У меня есть требование вернуть результат из базы данных либо как строку в xml-структуре, либо как json-структуру.
У меня есть решение, но я не знаю, если это лучший способ решить эту проблему.
У меня есть два метода:
@RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET)
public ResponseEntity<String> getContentByIdsAsJSON(@PathVariable("ids") String ids)
{
String content = null;
StringBuilder builder = new StringBuilder();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "text/html; charset=utf-8");
// responseHeaders.add("Content-Type", "application/json; charset=utf-8");
List<String> list = this.contentService.findContentByListingIdAsJSON(ids);
if (list.isEmpty())
{
content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><error>no data found</error>";
return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED);
}
for (String json : list)
{
builder.append(json + "\n");
}
content = builder.toString();
return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED);
}
@RequestMapping(value = "/content/{ids}", method = RequestMethod.GET)
public ResponseEntity<String> getContentByIdsAsXML(@PathVariable("ids") String ids)
{
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "application/xml; charset=utf-8");
String content = this.contentService.findContentByListingIdAsXML(ids);
if (content == null)
{
content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><error>no data found</error>";
return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED);
}
return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED);
}
для первого метода мне нужно лучшее решение, которое я уже задал здесь:
spring ответ mvc rest mongo dbobject
Следующее, что я вставлял в конфигурацию json converter:
<bean id="jsonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
когда я изменяю тип содержимого в первом методе на "application/json", он работает, но тогда ответ xml больше не работает, потому что json-конвертер хочет преобразовать строку xml в json-структуру я думаю.
что я могу сделать, что spring определяет разницу, что один метод должен возвращать json-тип, а другой - обычный xml в качестве строки?
Я попробовал его с флагом accept:
@RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET, headers = "Accept=application/json")
но это не работает. Я получаю следующую ошибку:
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.StackOverflowError
Я надеюсь, что кто-то может мне помочь.
Ответы
Ответ 1
Если вы используете Spring 3.1, вы можете использовать новый элемент produces
в аннотации @RequestMapping
, чтобы гарантировать, что вы создаете XML или JSON по своему усмотрению даже в одном приложении.
Я написал сообщение об этом здесь:
http://springinpractice.com/2012/02/22/supporting-xml-and-json-web-service-endpoints-in-spring-3-1-using-responsebody/
Ответ 2
Whoa... когда вы работаете с Spring, предположите, что кто-то другой столкнулся с той же проблемой. Вы можете сбрасывать все поколение JSON на стороне сервера, потому что все, что вам нужно сделать, это:
- Включите JSON Jackson JSON в ваше приложение.
- Установите возвращаемый тип
RequestMapping
в @ResponseBody(yourObjectType)
Spring автоматически преобразует ваш объект в JSON. В самом деле. Работает как магия.
Doc для @ResponseBody
: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-responsebody
Ответ 3
Вы можете использовать ContentNegotiationViewResolver, как показано ниже:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="defaultContentType" value="application/json" />
<property name="ignoreAcceptHeader" value="true" />
<property name="favorPathExtension" value="true" />
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</map>
</property>
<property name="defaultViews">
<list>
<ref bean="xmlView"/>
<ref bean="jsonView"/>
</list>
</property>
</bean>
<bean id="jsonView"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="contentType" value="application/json;charset=UTF-8"/>
<property name="disableCaching" value="false"/>
</bean>
<bean id="xmlView"
class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="contentType" value="application/xml;charset=UTF-8"/>
<constructor-arg>
<ref bean="xstreamMarshaller"/>
</constructor-arg>
</bean>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="autodetectAnnotations" value="true" />
<property name="annotatedClass" value="demo.domain.xml.XMLResponse"/>
<property name="supportedClasses" value="demo.domain.xml.XMLResponse"/>
</bean>
В вашем контроллере:
@RequestMapping(value = "/get/response.json", method = RequestMethod.GET)
public JSONResponse getJsonResponse(){
return responseService.getJsonResponse();
}
@RequestMapping(value = "/get/response.xml", method = RequestMethod.GET)
public XMLResponse getXmlResponse(){
return responseService.getXmlResponse();
}
Ответ 4
Если кто-то использует Spring Boot для ответа XML, добавьте следующую зависимость,
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
И в классе модели, который вы возвращаете, добавьте @XmlRootElement
.
@Entity
@Table(name = "customer")
@XmlRootElement
public class Customer {
//... fields and getters, setters
}
и в вашем контроллере добавьте produces="application/xml"
. Это даст ответ в формате xml.
Ответ 5
Здесь я написал метод, который принимает XML как параметр запроса из URL-адреса вашего запроса URL
Здесь я отправляю XML на свой URL-адрес "baseurl/user/createuser/"
public class UserController {
@RequestMapping(value = "createuser/" ,
method=RequestMethod.POST, consumes= "application/xml")
@ResponseBody
ResponseEntity<String> createUser(@RequestBody String requestBody ) {
String r = "<ID>10</ID>"; // Put whatever response u want to return to requester
return new ResponseEntity<String>(
"Handled application/xml request. Request body was: "
+ r,
new HttpHeaders(),
HttpStatus.OK);
}
}
Я протестировал его, используя хром-плакат, где вы можете отправить любой xml в теле контента, например:
"<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <userEntity><id>3</id><firstName>saurabh</firstName><lastName>shri</lastName><password>pass</password><userName>[email protected]</userName></userEntity>"
Этот XML будет захвачен моим методом createUser и сохранен в String requestBody, который я могу использовать далее
Ответ 6
Самый простой способ сделать это, чтобы получить ответ JSON:
Используя Spring 3.1, вы можете сделать следующее:
-
В вашем файле pom.xml(надеясь, что вы используете проект maven), добавьте зависимость maven для jackson-mapper (http://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl/1.9.13)
-
Измените свой код следующим образом и проверьте конечную точку на почтальоне:
@RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET)
public @ResponseBody String getContentByIdsAsJSON(@PathVariable("ids") String ids){
String content = "";
StringBuilder builder = new StringBuilder();
List<String> list = this.contentService.findContentByListingIdAsJSON(ids);
if (list.isEmpty()){
content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><error>no data found</error>";
return content;
}
for (String json : list){
builder.append(json + "\n");
}
content = builder.toString();
return content;
}