Http Message Converters with the Spring Framework
1. Oversikt
Denne artikkelen beskriver hvordan du konfigurerer HttpMessageConverters på våren.
Enkelt sagt, vi kan bruke meldingsomformere til å marshallere og unmarshall Java-objekter til og fra JSON, XML, etc - over HTTP.
2. Grunnleggende
2.1. Aktiver web-MVC
Til å begynne med må webapplikasjonen være konfigurert med Spring MVC-støtte. En praktisk og veldig tilpassbar måte å gjøre dette på er å bruke @EnableWebMvc kommentar:
@EnableWebMvc @ Configuration @ ComponentScan ({"com.baeldung.web"}) offentlig klasse WebConfig implementerer WebMvcConfigurer {...}
Merk at denne klassen implementerer WebMvcConfigurer - som vil tillate oss å endre standardlisten over Http Converters med vår egen.
2.2. Standard meldingsomformere
Som standard er følgende HttpMessageConverter Forekomster er forhåndsaktivert:
- ByteArrayHttpMessageConverter - konverterer byte-arrays
- StringHttpMessageConverter - konverterer strenger
- ResourceHttpMessageConverter - konverterer org.springframework.core.io.Ressurs for alle typer oktettstrømmer
- SourceHttpMessageConverter - konverterer javax.xml.transform.Source
- FormHttpMessageConverter - konverterer skjemadata til / fra en MultiValueMap.
- Jaxb2RootElementHttpMessageConverter - konverterer Java-objekter til / fra XML (bare lagt til hvis JAXB2 er til stede på klassestien)
- MappingJackson2HttpMessageConverter - konverterer JSON (bare lagt til hvis Jackson 2 er til stede på klassestien)
- MappingJacksonHttpMessageConverter - konverterer JSON (bare lagt til hvis Jackson er til stede på klassestien)
- AtomFeedHttpMessageConverter - konverterer Atom-feeds (bare lagt til hvis Roma er til stede på klassestien)
- RssChannelHttpMessageConverter - konverterer RSS-feeder (bare lagt til hvis Roma er til stede på klassestien)
3. Klient-server-kommunikasjon - Bare JSON
3.1. Innholdsforhandling på høyt nivå
Hver HttpMessageConverter implementering har en eller flere tilknyttede MIME-typer.
Når du mottar en ny forespørsel, Våren vil bruke “Aksepterer”-Hode for å bestemme medietypen den trenger å svare med.
Den vil da prøve å finne en registrert omformer som er i stand til å håndtere den spesifikke medietypen. Til slutt vil den bruke dette til å konvertere enheten og sende svaret tilbake.
Prosessen er lik for å motta en forespørsel som inneholder JSON-informasjon. Rammeverket vil bruke "Innholdstype”-Tittel for å bestemme medietypen til forespørselen.
Den vil da søke etter en HttpMessageConverter som kan konvertere kroppen sendt av klienten til et Java-objekt.
La oss avklare dette med et raskt eksempel:
- klienten sender en GET-forespørsel til / foos med Aksepterer topptekst satt til søknad / json - for å få alle Foo ressurser som JSON
- de Foo Spring Controller treffes og returnerer det tilsvarende Foo Java-enheter
- Spring bruker deretter en av Jackson-meldingsomformerne for å samle enhetene til JSON
La oss nå se på detaljene i hvordan dette fungerer - og hvordan vi kan utnytte @ResponseBody og @RequestBody kommentarer.
3.2. @ResponseBody
@ResponseBody på en Controller-metode indikerer for Spring at returverdien av metoden serialiseres direkte til hoveddelen av HTTP-svaret. Som diskutert ovenfor, “Aksepterer”-Overskrift spesifisert av klienten vil bli brukt til å velge riktig Http Converter for å samle enheten.
La oss se på et enkelt eksempel:
@GetMapping ("/ {id}") offentlig @ResponseBody Foo findById (@PathVariable lang id) {return fooService.findById (id); }
Nå vil klienten spesifisere "Godta" overskriften til søknad / json i forespørselen - eksempel krølle kommando:
curl --header "Godta: application / json" // localhost: 8080 / spring-boot-rest / foos / 1
De Foo klasse:
offentlig klasse Foo {privat lang id; privat strengnavn; }
Og Http-responsorganet:
{"id": 1, "name": "Paul",}
3.3. @Fotball
Vi kan bruke @Fotball kommentar om argumentet til en Controller-metode for å indikere at hoveddelen av HTTP-forespørselen er deserialisert til den bestemte Java-enheten. For å bestemme riktig omformer vil Spring bruke "Content-Type" -overskriften fra klientforespørselen.
La oss se på et eksempel:
@PutMapping ("/ {id}") offentlig @ResponseBody ugyldig oppdatering (@RequestBody Foo foo, @PathVariable String id) {fooService.update (foo); }
La oss deretter konsumere dette med et JSON-objekt - vi spesifiserer “Content-Type“ å være søknad / json:
curl -i -X PUT -H "Content-Type: application / json" -d '{"id": "83", "name": "klik"}' // localhost: 8080 / spring-boot-rest / foos / 1
Vi får tilbake 200 OK - et vellykket svar:
HTTP / 1.1 200 OK Server: Apache-Coyote / 1.1 Innholdslengde: 0 Dato: Fre, 10. januar 2014 11:18:54 GMT
4. Konfigurasjon av egendefinerte omformere
Vi kan også tilpasse meldingsomformerne ved å implementere WebMvcConfigurer grensesnitt og overordnet configureMessageConverters metode:
@EnableWebMvc @Configuration @ComponentScan ({"com.baeldung.web"}) offentlig klasse WebConfig implementerer WebMvcConfigurer {@Override public void configureMessageConverters (List omformere) {messageConverters.add (createXmlHttpMessageConverter ()); messageConverters.add (ny MappingJackson2HttpMessageConverter ()); } private HttpMessageConverter createXmlHttpMessageConverter () {MarshallingHttpMessageConverter xmlConverter = ny MarshallingHttpMessageConverter (); XStreamMarshaller xstreamMarshaller = ny XStreamMarshaller (); xmlConverter.setMarshaller (xstreamMarshaller); xmlConverter.setUnmarshaller (xstreamMarshaller); returnere xmlConverter; }}
I dette eksemplet lager vi en ny omformer - MarshallingHttpMessageConverter - og bruke Spring XStream-støtten til å konfigurere den. Dette gir stor fleksibilitet siden Vi jobber med API-er på lavt nivå i det underliggende marshalling-rammeverket - i dette tilfellet XStream - og vi kan konfigurere det slik vi vil.
Merk at dette eksemplet krever at du legger til XStream-biblioteket i klassestien.
Vær også oppmerksom på at ved å utvide denne støtteklassen, vi mister standardmeldingskonvertere som tidligere var forhåndsregistrert.
Vi kan selvfølgelig nå gjøre det samme for Jackson - ved å definere vår egen MappingJackson2HttpMessageConverter. Vi kan nå angi en egendefinert ObjectMapper på denne omformeren og ha den konfigurert slik vi trenger det.
I dette tilfellet var XStream den valgte marshaller / unmarshaller implementeringen, men andre liker CastorMarshaller kan også brukes.
På dette punktet - med XML aktivert på baksiden - kan vi konsumere API-en med XML-representasjoner:
curl --header "Godta: application / xml" // localhost: 8080 / spring-boot-rest / foos / 1
4.1. Vårstøvelstøtte
Hvis vi bruker Spring Boot, kan vi unngå å implementere WebMvcConfigurer og legge til alle meldingsomformerne manuelt som vi gjorde ovenfor.
Vi kan bare definere forskjellige HttpMessageConverter bønner i sammenheng, og Spring Boot vil legge dem automatisk til autokonfigurasjonen som den oppretter:
@Bean public HttpMessageConverter createXmlHttpMessageConverter () {MarshallingHttpMessageConverter xmlConverter = ny MarshallingHttpMessageConverter (); // ... return xmlConverter; }
5. Bruke Spring’s RestTemplate Med Http Message Converters
I tillegg til på serversiden kan Http Message Conversion konfigureres på klientsiden på våren RestTemplate.
Vi skal konfigurere malen med “Aksepterer”Og”Innholdstype”Overskrifter når det er aktuelt. Så prøver vi å konsumere REST API med full marshalling og unmarshalling av Foo Ressurs - både med JSON og med XML.
5.1. Henter ressursen med nr Aksepterer Overskrift
@Test offentlig ugyldig testGetFoo () {String URI = “// localhost: 8080 / spring-boot-rest / foos / {id}"; RestTemplate restTemplate = new RestTemplate (); Foo foo = restTemplate.getForObject (URI, Foo. klasse, "1"); Assert.assertEquals (nytt heltal (1), foo.getId ());}
5.2. Henter en ressurs med applikasjon / xml Godta topptekst
La oss nå eksplisitt hente ressursen som en XML-representasjon. Vi skal definere et sett med omformere og sette disse på RestTemplate.
Fordi vi bruker XML, skal vi bruke samme XStream marshaller som før:
@Test offentlig ugyldig gittConsumingXml_whenReadingTheFoo_thenCorrect () {String URI = BASE_URI + "foos / {id}"; RestTemplate restTemplate = ny RestTemplate (); restTemplate.setMessageConverters (getMessageConverters ()); HttpHeaders headers = nye HttpHeaders (); headers.setAccept (Arrays.asList (MediaType.APPLICATION_XML)); HttpEntity entity = new HttpEntity (headers); ResponseEntity response = restTemplate.exchange (URI, HttpMethod.GET, entity, Foo.class, "1"); Foo ressurs = respons.getBody (); assertThat (resource, notNullValue ()); } privat liste getMessageConverters () {XStreamMarshaller marshaller = ny XStreamMarshaller (); MarshallingHttpMessageConverter marshallingConverter = ny MarshallingHttpMessageConverter (marshaller); Liste omformere = ArrayList(); converters.add (marshallingConverter); omformere; }
5.3. Henter en ressurs med søknad / json Godta topptekst
På samme måte, la oss nå konsumere REST API ved å be om JSON:
@Test offentlig ugyldig gittConsumingJson_whenReadingTheFoo_thenCorrect () {String URI = BASE_URI + "foos / {id}"; RestTemplate restTemplate = ny RestTemplate (); restTemplate.setMessageConverters (getMessageConverters ()); HttpHeaders headers = nye HttpHeaders (); headers.setAccept (Arrays.asList (MediaType.APPLICATION_JSON)); HttpEntity entity = new HttpEntity (headers); ResponseEntity response = restTemplate.exchange (URI, HttpMethod.GET, entity, Foo.class, "1"); Foo ressurs = respons.getBody (); assertThat (resource, notNullValue ()); } privat liste getMessageConverters () {Liste omformere = ny ArrayList(); converters.add (ny MappingJackson2HttpMessageConverter ()); omformere; }
5.4. Oppdater en ressurs med XML Innholdstype
Til slutt, la oss også sende JSON-data til REST API og spesifisere medietypen for disse dataene via Innholdstype Overskrift:
@Test offentlig ugyldig gittConsumingXml_whenWritingTheFoo_thenCorrect () {String URI = BASE_URI + "foos / {id}"; RestTemplate restTemplate = ny RestTemplate (); restTemplate.setMessageConverters (getMessageConverters ()); Foo ressurs = ny Foo (4, "jason"); HttpHeaders headers = nye HttpHeaders (); headers.setAccept (Arrays.asList (MediaType.APPLICATION_JSON)); headers.setContentType ((MediaType.APPLICATION_XML)); HttpEntity entity = new HttpEntity (resource, headers); ResponseEntity response = restTemplate.exchange (URI, HttpMethod.PUT, entity, Foo.class, resource.getId ()); Foo fooResponse = respons.getBody (); Assert.assertEquals (resource.getId (), fooResponse.getId ()); }
Det som er interessant her er at vi kan blande medietypene - vi sender XML-data, men vi venter på JSON-data tilbake fra serveren. Dette viser hvor kraftig vårkonverteringsmekanismen egentlig er.
6. Konklusjon
I denne opplæringen så vi på hvordan Spring MVC tillater oss å spesifisere og tilpasse Http Message Converters til automatisk marshall / unmarshall Java-enheter til og fra XML eller JSON. Dette er selvfølgelig en forenklet definisjon, og det er så mye mer som konverteringsmekanismen for meldinger kan gjøre - som vi kan se fra det siste testeksemplet.
Vi har også sett på hvordan vi kan bruke den samme kraftige mekanismen med RestTemplate klient - noe som fører til en fullstendig typesikker måte å konsumere API på.
Som alltid er koden presentert i denne artikkelen tilgjengelig på Github.