2011-01-16 10 views
5

Spring MVCを使用してRESTを開発すると、XMLとJSONのデータがサポートされます。私は私の春のコンフィグ豆app-servlet.xmlXMLとJSONをサポートするSpring REST 3

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

そして、私の春RESTコントローラーでContentNegotiationViewResorverを書いています:

@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データに応答します。

何か問題がありますか?

+0

? – chris

+0

申し訳ありません..、urlは/rest/customers/teddy.xmlです。このurlはshowCustomerメソッドを呼び出すと想定しています。テディは{id}パラメータです。 –

+0

どのようにそのURLにアクセスしようとしていますか?ウェブブラウザ?要求に適切なコンテンツタイプのエンコーディングヘッダーを送信していますか? – skaffman

答えて

2

"xml"のコンテンツタイプは、 "text/xml"に "application/xml"ではなくマッピングする必要があります。また、拡張子に基づいてコンテンツタイプリゾルバを強制するには、 "ContentNegotiatingViewResolver"の "favorPathExtension"プロパティをtrueに設定することができます(デフォルトでtrueになっている必要があります)。

EDIT:この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となります。 JAXBに精通しているので、これはXStreamではなくJAXB2を使用しています。私が気づいたのは、JAXBアノテーションがCustomerクラスで正しくないと、SpringがJSONを見たのと同じ方法でXMLを提供していなかったことです(CustomerクラスのXMLRootElementアノテーションを削除することでXMLを複製できます)。注釈、私は期待どおりにXMLを返した。 XStreamの設定に問題がある可能性があります。

編集2:あなたは正しいです!私は気が付かなかった、xmlが戻ったら、私はjsonが今働いていると思った。私は問題を参照してくださいAnnotationMethodHandlerAdapterで、@ResponseBodyの処理は少し奇妙です、それは完全にViewResolversを無視し、ContentNegotiatingViewResolverを完全にバイパスして登録されたMessageConvertersを使用して、@回避策の代わりに@ModelAttribute注釈を使用する回避策@ResponseBody 、このようにして、レゾルバが呼び出されます。プロジェクトを[email protected]:bijukunjummen/mvc-samples.gitで今すぐお試しください。これはSpringバグかもしれません。あなたはSpringフォーラムでそれを試してみて、彼らが何を推薦しているか見ることができます。

+0

私はtext/xmlとtext/jsonにコンテンツタイプを変更しました。 faforPathExtensionをtrueに設定します。しかし、私はアプリケーション/休憩/顧客/ teddy.xml –

+0

私はJAXB2を使用して試してみましたかわからない、と私はこの場所でサンプルを入れている - git://github.com/ bijukunjummen/mvc-samples.gitの場合、 /rest/customers/teddy.jsonとxml rest/customers/teddy.xmlに正しくjsonを提供します。 –

+0

私はあなたのプロジェクトを実行しました。 'firefox'、' chrome'、 'poster firefox plugin'を使ってアプリケーションにアクセスしてみてください。 'rest/customers/teddy.json'にアクセスしている間は' xml'値を取得します。私のブラウザの結果はhttp://i52.tinypic.com/29hb4j.jpg –

1

私は同じ問題を抱えていました。私はあなたが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をクラスパスに追加します。

また、ちょっとしたヒントとして、app-servlet.xmlは必要ありません。あなたのウェブで。XMLは、あなたのためにそれらをロードするコンテキストリスナーをゼロとできるように設定を設定します。

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

ヘッダを受け入れ何があなたのサーバーに送信されますか? リクエストしたいコンテンツタイプがこのリストにあることを確認してください。

+0

ドメインクラスに@XmlRootElementアノテーションを追加すると、サーバーはxml形式を返します。 @XStreamAliasアノテーションを追加すると、サーバーはJSON形式を返します。私はサーバーがXMLとJSONの両方を受け入れると思う。 –

0

ブラウザを使用してコントローラにアクセスすると、一般的なブラウザのAcceptヘッダーが送信されます。 application/xmlがAcceptリストに含まれているため、ビューリゾルバと一致せず、最初のもの(application/xml)に一致するか、一致します。

RestClient http://code.google.com/p/rest-client/を使用して、どのようなAcceptヘッダー(送信する場合)を送信するかを完全に制御することをお勧めします。

デフォルトの文字セットはUTF-8ではなくUS-ASCIIですので、text/xmlの使用はお勧めしません。これにより、エンディングの問題が発生する可能性があります。エンコーディングはいつでも指定できますが、appliation/xmlにはUTF-8のデフォルトエンコーディングがあります。

1

私は解決策を得たが、それはあなたの方法ショーの顧客で正しいやり方だ場合、私は知らないまあ:

@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があるとき、contentnegociationviewresolverは無視されます。メソッドはそのようにする必要があります:

あなたは問題がある場合は私の作品

だけでなく、あなたのapp-servlet.xml

このBeanに追加することができますが、私はあなたがこれを追加する必要はないと思います。

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

I got the answers from mkyong.com

1

春3.1は、あなたが@RequestMapping注釈に新しいproduces要素を使用して言及して問題を解決します。これにより、Springがあなたのオブジェクトに適用するHttpMessageConverterを制御することができます。

私はそれについてのブログ記事を書いた:アプリ/顧客/ teddy.xmlあなたのコントローラにマッピングされている

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

関連する問題