2012-04-03 13 views
5

JAX-RS oferuje wspaniały sposób określania typów zawartości w @Produces, a framework automatycznie określi najlepszy typ zawartości z nagłówka HTTP Accept klienta i cuda cudów, nawet przekonwertuj swój obiekt na ten typ (np. XML używając JAXB lub JSON używając Jackson) podczas zwracania informacji do osoby dzwoniącej.Odwzorowywanie typów zawartości rozszerzeń w Apache CXF JAX-RS

Mój (pracujący) klient, jak często robią to klienci, utrudnił proste zadanie, żądając określenia typu zawartości według rozszerzenia w adresie URL, np. api/widgets.json. To zmusi mnie mieć różne getWidgetsXXX() metody, jedna z @Produces("application/json"), inny z @Produces("application/xml") itd

Ale używam Apache CXF i byłem zachwycony, że mogłem configure CXF do mapy różnych typów rozszerzeń do treści uzywajac jaxrs.extensions parametr inicjujący!

<!-- registers extension mappings --> 
<init-param> 
    <param-name>jaxrs.extensions</param-name> 
    <param-value> 
    xml=application/xml 
    json=application/json 
    </param-value> 
</init-param> 

Ale nie mogę znaleźć absolutnie żadnej dokumentacji na temat tego, jak to działa w rzeczywistym świecie. Naiwnie myślałem, że po prostu opisywać metody ze ścieżką z rozszerzeniem i byłoby naśladować Accepts nagłówka:

@Path("/widgets.{extension}") 
@GET 
@Produces({ "application/json", "application/xml" }) 
public List<Widget> getWidgets(); 

Więc ja nazywam go za pomocą api/widgets.json i zwraca XML! Co jest szczególnie dziwne, ponieważ JAX-RS określa, że ​​domyślny typ zawartości jest pierwszym wymienionym na liście.

Gdzie mogę dowiedzieć się, jak korzystać z mapowania typów zawartości rozszerzeń CXF?

P.S. Nie używam Springa.

Odpowiedz

0

W sytuacji, chciałbym oświadczyć, że metoda @Produces typ zawartości */* (czyli pełny wieloznaczny), a następnie wykonaj negocjacji zawartości siebie. Wy prawdopodobnie spojrzenie na metody podpisu jak ten:

@javax.ws.rs.GET 
@javax.ws.rs.Path("{filename}") 
@javax.ws.rs.Produces("*/*") 
javax.ws.rs.core.Response getDirectoryOrFileContents(
     @javax.ws.rs.PathParam("filename") String filename, 
     @javax.ws.rs.core.Context javax.ws.rs.core.HttpHeaders headers); 

który daje dostęp zarówno do żądanego pliku - jeden sposób odgadnąć typ mediów dostarczyć - oraz pełen zestaw nagłówków HTTP (podpowiedź: użyj headers.getAcceptableMediaTypes()), które dają inny sposób. Jak zrównoważyć te dwa, może być "interesujący". (Kod, który muszę to zrobić, jest bardzo specyficzny dla modelu wewnętrznego mojej aplikacji, więc prawdopodobnie nie będzie dla ciebie przydatny.) Następnie zwracasz wynik, konstruując Response, który daje ci dość ścisłą kontrolę nad tym, co klient wraca.

Tak, to jest więcej pracy niż pozwolenie CXFowi na obsługę tego wszystkiego (zwykle generuje wiele podstaw do wykonania tego wszystkiego), ale w złożonym przypadku będziesz zadowolony z kontroli.

+0

Dzięki za cynk. Twoja odpowiedź może okazać się przydatna --- ale obawiam się, że nie odpowiada na pytanie. :( –

4

Dodanie następujących w swoich pracach <jaxrs:server>:

<jaxrs:extensionMappings> 
    <entry key="json" value="application/json" /> 
    <entry key="xml" value="application/xml" /> 
</jaxrs:extensionMappings> 

Źródło: http://cxf.apache.org/docs/jax-rs.html#JAX-RS-Debugging

+0

Masz na myśli w sekcji, w której jest napisane: "Oto przykład tego, jak można to zrobić ze Spring"? –

+0

Ups, nie zauważyłem, że jest to tylko na wiosnę – praseodym

+0

Chociaż nie było to, co OP szukał ponieważ było to dla mnie bardzo pomocne i nie używam Springa. –

0

naśladuje rozszerzeń nagłówka Accept jak się domyślacie.Jednak nie musi zadeklarować extenstion w @Path adnotacji:

@Path("/widgets") 
@GET 
@Produces({ "application/json", "application/xml" }) 
public List<Widget> getWidgets(); 

Można połączyć widgets.xml lub widgets.json

1

Nie wiem, czy które pomagają lub nie, ale ja również stoi ten sam problem przedstawić coś takiego w moich usługach JAX-RS. Osiągnąłem tę funkcjonalność, używając JAX-RS_Content_Negotiation Następująca lokalizacja zawiera szczegółowe informacje na jej temat.

https://docs.jboss.org/resteasy/docs/3.0.6.Final/userguide/html/JAX-RS_Content_Negotiation.html

Po prostu trzeba mapować typy nośników z wartościami, które chcesz

<context-param> 
     <param-name>resteasy.media.type.mappings</param-name> 
     <param-value> 
      html : text/html, json : application/json, xml :   
      application/xml 
     </param-value> 
</context-param> 


@GET 
     @Path("/second/{param}") 
     @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML}) 
     public Response printStudent(@PathParam("param") String msg) { 


} 

teraz mogę uzyskać dostępu do usługi tak i odpowiedź jest zgodna z rozszerzeniem, które mogę umieścić na końcu

http://localhost:8080/RESTfulExample/rest/message/second/bill.json

można umieścić .xml LUB .json na końcu adresu URL i obs e odpowiednio wygeneruje odpowiedź.