JSONP и пользовательский фильтр, возвращающий XML вместо Spring MVC - PullRequest
0 голосов
/ 23 марта 2011

Я использую JSONP для вызова службы контроллера в Spring MVC. У меня есть пользовательский фильтр, который возвращает результат, завернутый в обратный вызов. Я использовал этот пример, http://jpgmr.wordpress.com/2010/07/28/tutorial-implementing-a-servlet-filter-for-jsonp-callback-with-springs-delegatingfilterproxy/. Я также использую ContentNegotiatingViewResolver, но мой результат продолжает возвращать XML в обратном вызове. Почему это продолжало бы делать это?

jQuery1509349652162468509_1300839533498(<?xml version="1.0" encoding="UTF-8" standalone="yes"?><followResponse><id>0</id></followResponse>);

сервлет-context.xml

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

Ответы [ 4 ]

1 голос
/ 23 марта 2011

Я предполагаю, что ваш метод контроллера использует @ResponseBody и что возвращаемые вами объекты модели отмечены аннотациями Jaxb2 (в частности, @XmlRootElement).

У меня была та же проблема, что и у вас. Проблема в том, что @ResponseBody обходит ContentNegotiatingViewResolver. Вы можете подтвердить это, добавив некоторые точки останова к методам ContentNegotiatingViewResolver, например, «resolViewName», и посмотрите, действительно ли он получил (не будет).

Текущая работа, которую я использую, заключается в том, чтобы фактически объявить представление json и специально использовать его.

Вы должны добавить что-то вроде этого в ваш xml:

<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>

Затем вы можете изменить свой элемент списка, чтобы он выглядел примерно так:

<beans:ref bean="jsonView" />

Ваш метод контроллера будет возвращать ModelAndView следующим образом:

@RequestMapping(value = "/{username}/get.json", method = RequestMethod.GET)
public ModelAndView getUser(@PathVariable String username) {
    User user = service.getUser(username);
    return new ModelAndView("jsonView", "user", user);
}

Или вы можете просто вернуть представление в виде строки и добавить объявление ModelMap в сигнатуру вашего метода:

@RequestMapping(value = "/{username}/get.json", method = RequestMethod.GET)
public String getUser(@PathVariable String username, ModelMap model) {
    User user = service.getUser(username);
    model.addAttribute("user", user);
    return "jsonView";
}

Надеюсь, это поможет.

(Примечание: распечатка этого из памяти, так что есть вероятность синтаксических ошибок и т. Д.)

Я не нашел более элегантного решения этой проблемы, но если я это сделаю, я опубликую его здесь.

EDIT:

Попробуйте удалить @ResponseBody. Если вы сделаете это, MessageConverters не будут активированы, и ContentNegotiatingViewResolver будет запущен. На данный момент, это должно быть расширение, которое определяет представление (на основе ваших настроек).

Вам не нужно ничего менять, кроме удаления @ResponseBody, тип возвращаемого значения может остаться прежним.

0 голосов
/ 23 марта 2011

Мое временное решение состояло в том, чтобы использовать JSON-анализатор, который принимает XML и конвертирует его в JSON на данный момент. Да, это отстой, когда он анализируется в XML, а затем возвращается в JSON, но сейчас это должно сработать.

String xml = new String(wrapper.getData());

            if(!StringUtils.isEmpty(xml))
            {
                XMLSerializer xmlSerializer = new XMLSerializer(); 
                JSON json = xmlSerializer.read( xml );  
                out.write(json.toString().getBytes());
            }

            out.write(new String(");").getBytes());
0 голосов
/ 23 марта 2011

Приятно видеть, что мой пост был вашим вдохновением!: -D

Вы добавили API картографа Джексона в свои зависимости?Его не будет по умолчанию при создании приложения Spring MVC.Вы должны добавить его самостоятельно, а затем он должен маршалировать ответ на JSON.

0 голосов
/ 23 марта 2011

Проверьте заголовок Accept вашего запроса.

...