Вопрос

Если мы разрабатываем отдых с помощью Spring MVC, он будет поддерживать данные XML и JSON. Я написал ContentNegotiationViewResorver в моей пружине Bean app-servlet.xml

<bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
        p:order="1">
        <property name="mediaTypes">
            <map>
                <entry key="xml" value="application/xml" />
                <entry key="json" value="application/json" />
            </map>
        </property>
        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                    <property name="marshaller">
                        <bean class="org.springframework.oxm.xstream.XStreamMarshaller"
                            p:autodetectAnnotations="true" />
                    </property>
                </bean>
                <bean
                    class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
            </list>
        </property>
    </bean>

И мой весенний контроллер отдыха:

@Controller
@RequestMapping("/rest/customers")
class CustomerRestController {

protected Log log = LogFactory.getLog(CustomerRestController.class);

@RequestMapping(method = POST)
@ResponseStatus(CREATED)
public void createCustomer(@RequestBody Customer customer,
        HttpServletResponse response) {

    log.info(">>>" + customer.getName());
    response.setHeader("Location", String.format("/rest/customers/%s",
            customer.getNumber()));
}


@RequestMapping(value = "/{id}", method = GET)
@ResponseBody
public Customer showCustomer(@PathVariable String id) {
    Customer c = new Customer("0001", "teddy", "bean");
    return c;
}


@RequestMapping(value = "/{id}", method = PUT)
@ResponseStatus(OK)
public void updateCustomer(@RequestBody Customer customer) {
    log.info("customer: " + customer.getName());
}

Я установил @XStreamAlias("customer") Аннотация в моем классе доменов клиента. Но когда я пытаюсь получить доступ http://localhost:8080/rest/customers/teddy.xml Это всегда ответ JSON Данные.

Я установил @XmlRootElement(name="customer") Аннотация в моем классе доменов клиента. Но когда я пытаюсь получить доступ http://localhost:8080/rest/customers/teddy.json это всегда ответ XML.

Здесь что-то не так ?

Это было полезно?

Решение

Я думаю, что тип контента «XML» должен быть сопоставлен с «text/xml» не для «приложения/xml». Кроме того, чтобы заставить разрешения типа контента на основе расширения, вы можете попытаться установить свойство «FavorPateExtension» для «ContentNegotiationViewResolver» True (хотя это должно было быть правдой по умолчанию!)

РЕДАКТИРОВАТЬ: Я добавил рабочий образец в этом месте GIT - git://github.com/bijukunjummen/mvc-samples.git, если вы поднимаете конечную точку, используя MVN Tomcat: Run, JSON подается в http://localhost:8080/mvc-samples/rest/customers/teddy.json и XML в http://localhost:8080/mvc-samples/rest/customers/teddy.xml. Анкет Это использует Jaxb2, а не Xstream, так как я знаком с Jaxb. Одна вещь, которую я заметил, заключалась в том, что, когда мои аннотации JAXB были не правильными в классе клиентов, Spring служил JSON, а не XML, как вы его видели (вы можете повторить его, удалив аннотацию XMLROOTELEMER из класса клиента), после того, как я исправил свой Аннотации, я вернулся XML, как и ожидалось. Так что может случиться так, что с вашей конфигурацией Xstream что -то не так.

РЕДАКТИРОВАТЬ 2: Вы правы !! Я не заметил, как только я вернулся XML, я предположил, что JSON работает сейчас. Я вижу проблему, в AnnotationMethodHandlerAdapter, обработка для @ResponseBody немного странно, он полностью игнорирует ViewReSolvers и использует зарегистрированные MessageConverters вместо этого полностью обходные ContentNegotiatingViewResolver, один обходной путь на данный момент - использовать @ModelAttribute Аннотация для ответа, вместо @Responsebody, таким образом, что резолюры вида вызываются. Попробуйте сейчас использовать проект в git@github.com:bijukunjummen/mvc-samples.git И посмотрим, работает ли это для вас. Это может быть весенняя ошибка, вы можете попытаться поднять его на весеннем форуме и посмотреть, что они рекомендуют.

Другие советы

Что заголовки принятия отправляются на ваш сервер? Убедитесь, что тип контента, который вы хотели бы запросить, находится в этом списке.

Весна 3.1 решает проблему, которую вы упоминаете, используя новую produces элемент на @RequestMapping аннотация. Это позволяет вам контролировать HttpMessageConverter Эта весна относится к вашему объекту.

Я написал сообщение об этом в блоге:

http://springinpractice.com/2012/02/22/supporting-xml-and-json-web-service-endpoints-in-spring-3-1-using-responsebody/

У меня такая же проблема. Я полагаю, вы используете Spring 3 и использовали <mvc:annotation-driven/>. Анкет Я не совсем уверен, но я думаю, что это создает некоторый конфликт на основе конвертеров сообщений, которые настраивает пространство имен MVC.

Использование пространства имен Oxm сработало для меня:

@XmlRootElement(name="person")
class Person {
   private String firstName;
   private String lastName;
}

@Controller 
@RequestMapping("person")
class PersonController {
   @RequestMapping("list")
   public @ResponseBody Person getPerson() {
      Person p = new Person();
      p.setFirstName("hello");
      p.setLastName("world");
      return p;
   }
}

Конфигурация содержимого (MVC и внутренний резольвер представления находятся в другом контексте):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:oxm="http://www.springframework.org/schema/oxm"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

        <oxm:jaxb2-marshaller id="jaxbMarshaller">
        <oxm:class-to-be-bound name="package.Person" />
    </oxm:jaxb2-marshaller>

    <bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="defaultContentType" value="text/html" />
        <property name="ignoreAcceptHeader" value="true" />
        <property name="favorPathExtension" value="true" />
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
                <entry key="xml" value="application/xml" />
            </map>
        </property>
        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                    <property name="marshaller" ref="jaxbMarshaller" />
                </bean>
            </list>
        </property>
    </bean>
</beans>

В этом примере используется JAXB, поэтому вам понадобятся JAXB-API и JAXB-IMPL на классе.

Кроме того, просто совет, вам не нужен приложение-servlet.xml. В вашем web.xml установите конфигурацию в NULL и позвольте контекстному слушателю загрузить их для вас:

<listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/mvc-context.xml, /WEB-INF/spring/content-negotiation-context.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value/>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

Что ж, у меня есть решение, но я не знаю, правильный ли он в вашем методе показать клиенту:

@RequestMapping(value = "/{id}", method = GET)
@ResponseBody
public Customer showCustomer(@PathVariable String id) {
    Customer c = new Customer("0001", "teddy", "bean");
    return c;
}

В этой части мы используем MVC пружины и в контроллере мы должны вернуть представление, поэтому я удалил аннотацию @ResponseBody и я возвращаю String с именем представления, потому что в нашем XML мы добавили ContentNegotiatingViewResolver И когда у нас есть ResponseBody Контент tegociationViewResolver игнорируется, потому что ждет представление, но мы вернули объект, чтобы метод был таким:

@RequestMapping(value = "/{id}", method = GET)

public String showCustomer(@PathVariable String id, ModelMap model) {
     Customer c = new Customer("0001", "teddy", "bean");
     model.addAttribute("customer",c);
    return "myView";
}

Ну, это работает для меня, если у вас есть проблемы, вы можете добавить к своему app-servlet.xml

Этот фасоль, но я не думаю, что вы должны добавить это.

<bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/views/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

Я получил ответы от mkyong.com

Доступ к контроллеру с помощью брейс -заседания отправит типичный заголовок принятия браузера. Он не будет соответствовать ни одному представлению, и по умолчанию с первым (Application/XML) или соответствует, потому что Application/XML находится в списке приема.

Я могу рекомендовать использовать RestClient http://code.google.com/p/rest-client/ Чтобы получить полный контроль над тем, что принять заголовок (если один вообще) вы хотите отправить.

Я не рекомендую использовать Text/XML в качестве набора символов по умолчанию US-ASCII, а не UTF-8. Это может создать забавные проблемы кодирования в будущем. Вы всегда можете указать кодирование, но приложение/XML имеет кодирование UTF-8 по умолчанию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top