2011-03-23 107 views
0

我正在使用JSONP在Spring MVC中調用控制器服務。我有一個自定義過濾器,返回回調中包裝的結果。我用這個例子,http://jpgmr.wordpress.com/2010/07/28/tutorial-implementing-a-servlet-filter-for-jsonp-callback-with-springs-delegatingfilterproxy/。我也在使用ContentNegotiatingViewResolver,但是我的結果不斷在回調中返回XML。爲什麼它會繼續這樣做?JSONP和自定義篩選器在Spring MVC中返回XML代碼

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

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

回答

1

我的猜測是,你控制的方法是使用和@ResponseBody的模型對象your're返回都標了JAXB2註釋(特別是@XmlRootElement)。

我有你有同樣的問題。問題是,@ResponseBody繞過ContentNegotiatingViewResolver。您可以通過爲ContentNegotiatingViewResolver的方法添加一些斷點(如「resolveViewName」)來確認此情況,並確定它是否實際上被擊中(它不會)。

當前的工作圍繞我使用的是實際申報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); 
} 

或者,您可以返回視圖爲tring,並在你的方法簽名中添加聲明一個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"; 
} 

希望這會有所幫助。

(注:從內存中輸入了這一點,所以有語法錯誤潛力等)

我還沒有找到一個更優雅的解決這個問題還沒有,但如果我這樣做,我會後這裏。

編輯:

嘗試刪除 @ResponseBody。如果這樣做,MessageConverters將不會被激活,並且ContentNegotiatingViewResolver將被觸發。此時,它應該是決定視圖的擴展(基於您的設置)。

你不應該改變比@ResponseBody去除任何其他的返回類型可以保持不變。

+0

這是一個解決JSONP請求的工作? – 2011-03-23 16:03:26

+0

這是一個通用的返回JSON的工作。我的應用程序具有普通的控制器,它們只是使用jstl視圖,但它們也以XML或JSON的形式公開數據。當以@ResponseBody的形式返回pojo時,一切正常,但是當我試圖返回一個標記爲Jaxb註釋的pojo時,因爲它總是返回XML(即使擴展名爲.json,並且我正確配置了ContentNegotiatingViewResolver以支持擴展)。我想這個信息可能至少讓你更接近可接受的解決方案。 – 2011-03-23 16:08:46

+0

我猜如果你可以從這裏取任何東西,它使用@ResponseBody將繞過ContentNegotiatingViewResolver,而是使用註冊的MessageConverters。在這種情況下,適當的轉換器由「接受」標題選擇。上面提到您忽略了接受標頭,但這僅適用於ContentNegotiatingViewResolver,不適用於由AnnotationMethodHandlerAdapter選擇的MessageConverters。 – 2011-03-23 16:42:28

0

檢查您請求的Accept頭。

+0

我很無視他們。他們不同,因爲它是想要的文字/ JavaScript。 – 2011-03-23 16:04:06

0

很高興看到我的博客文章是你的靈感! :-D

你有沒有添加的傑克遜映射器API,以你的依賴?在創建Spring MVC應用程序時,它不會默認存在。你必須自己添加它,然後它應該對JSON做出迴應。

+0

是的一切都正確添加。 JSON和XML在返回時工作正常,它只是JSONP和JQuery。我認爲這與Accept Headers有關,但我忽略了我認爲的那些。是很好的解決方案。 – 2011-03-23 16:01:43

0

我的臨時解決方案是使用JSON解析器,該解析器將XML轉換爲JSON並暫時將其轉換爲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());