Beeld- / mediagegevens retourneren met Spring MVC

1. Overzicht

In deze zelfstudie laten we zien hoe u afbeeldingen en andere media kunt retourneren met behulp van het Spring MVC-framework.

We zullen verschillende benaderingen bespreken, beginnend bij direct manipuleren HttpServletResponse dan over te stappen op benaderingen die profiteren van Message Conversion, Content Negotiation en Spring's Bron abstractie. We zullen ze allemaal nader bekijken en hun voor- en nadelen bespreken.

2. Gebruik de HttpServletResponse

De meest basale benadering van het downloaden van afbeeldingen is om rechtstreeks tegen een reactie object en bootst een pure na Servlet implementatie, en het wordt gedemonstreerd met behulp van het volgende fragment:

@RequestMapping (value = "/ image-manual-response", method = RequestMethod.GET) public void getImageAsByteArray (HttpServletResponse response) gooit IOException {InputStream in = servletContext.getResourceAsStream ("/ WEB-INF / images / image-example.jpg) "); response.setContentType (MediaType.IMAGE_JPEG_VALUE); IOUtils.copy (in, response.getOutputStream ()); }

Als u het volgende verzoek verzendt, wordt de afbeelding in een browser weergegeven:

//localhost:8080/spring-mvc-xml/image-manual-response.jpg

De implementatie is redelijk eenvoudig en eenvoudig dankzij IOUtils van de org.apache.commons.io pakket. Het nadeel van de aanpak is echter dat deze niet robuust is tegen de mogelijke veranderingen. Het mime-type is hard gecodeerd en de verandering van de conversielogica of het externaliseren van de beeldlocatie vereist wijzigingen in de code.

In de volgende sectie wordt een meer flexibele benadering besproken.

3. Gebruik de HttpMessageConverter

In het vorige gedeelte werd een basisbenadering besproken die geen gebruik maakt van de functies voor berichtconversie en inhoudsonderhandeling van het Spring MVC Framework. Om deze functies op te starten, moeten we:

  • Annoteer de controllermethode met de @ResponseBody annotatie
  • Registreer een geschikte berichtconverter op basis van het retourtype van de controllermethode (ByteArrayHttpMessageConverter bijvoorbeeld nodig voor de juiste conversie van bytes-array naar een afbeeldingsbestand)

3.1. Configuratie

Om de configuratie van de converters te demonstreren, zullen we de ingebouwde ByteArrayHttpMessageConverter die een bericht converteert wanneer een methode de byte[] type.

De ByteArrayHttpMessageConverter is standaard geregistreerd, maar de configuratie is analoog voor elke andere ingebouwde of aangepaste converter.

Voor het toepassen van de berichtconversie-bean moet een geschikt MessageConverter bean in Spring MVC-context en het instellen van mediatypen die het moet verwerken. U kunt het definiëren via XML, met label.

Deze tag moet binnen worden gedefinieerd tag, zoals in het volgende voorbeeld:

     afbeelding / jpeg afbeelding / png 

Het bovengenoemde configuratiedeel wordt geregistreerd ByteArrayHttpMessageConverter voor afbeelding / jpeg en afbeelding / png reactie-inhoudstypen. Als tag is niet aanwezig in de mvc-configuratie, dan wordt de standaardset converters geregistreerd.

U kunt ook de berichtenconverter registreren met behulp van Java-configuratie:

@Override public void configureMessageConverters (List converters) {converters.add (byteArrayHttpMessageConverter ()); } @Bean openbare ByteArrayHttpMessageConverter byteArrayHttpMessageConverter () {ByteArrayHttpMessageConverter arrayHttpMessageConverter = nieuwe ByteArrayHttpMessageConverter (); arrayHttpMessageConverter.setSupportedMediaTypes (getSupportedMediaTypes ()); return arrayHttpMessageConverter; } privélijst getSupportedMediaTypes () {Lijstlijst = nieuwe ArrayList (); list.add (MediaType.IMAGE_JPEG); list.add (MediaType.IMAGE_PNG); list.add (MediaType.APPLICATION_OCTET_STREAM); retourlijst; }

3.2. Implementatie

Nu kunnen we onze methode implementeren die verzoeken om media afhandelt. Zoals hierboven vermeld, moet u uw controllermethode markeren met de @ResponseBody annotatie en gebruik byte[] als het terugkerende type:

@RequestMapping (value = "/ image-byte-array", method = RequestMethod.GET) public @ResponseBody byte [] getImageAsByteArray () gooit IOException {InputStream in = servletContext.getResourceAsStream ("/ WEB-INF / images / image-example .jpg "); retourneer IOUtils.toByteArray (in); }

Om de methode te testen, dient u het volgende verzoek in uw browser in:

//localhost:8080/spring-mvc-xml/image-byte-array.jpg

Aan de andere kant weet de methode niets over de HttpServletResponse, het conversieproces is zeer configureerbaar, variërend van het gebruik van de beschikbare converters tot het specificeren van een aangepaste conversie. Het inhoudstype van het antwoord hoeft niet hard gecodeerd te zijn, maar er wordt onderhandeld op basis van het achtervoegsel van het verzoekpad .jpg.

Het nadeel van deze aanpak is dat je expliciet de logica moet implementeren voor het ophalen van de afbeelding uit een gegevensbron (lokaal bestand, externe opslag, etc.) en dat je geen controle hebt over de headers of de statuscode van het antwoord.

4. Gebruik de ResponseEntity Klasse

U kunt een afbeelding retourneren als byte[] verpakt in de Reactie-entiteit. Lente MVC ResponseEntity maakt niet alleen controle mogelijk over de body van de HTTP-respons, maar ook over de header en de responsstatuscode. Als u deze aanpak volgt, moet u het retourtype van de methode definiëren als ResponseEntity en creëer terugkerende ResponseEntity object in de hoofdtekst van de methode.

@RequestMapping (value = "/ image-response-entity", method = RequestMethod.GET) openbare ResponseEntity getImageAsResponseEntity () {HttpHeaders headers = nieuwe HttpHeaders (); InputStream in = servletContext.getResourceAsStream ("/ WEB-INF / images / image-example.jpg"); byte [] media = IOUtils.toByteArray (in); headers.setCacheControl (CacheControl.noCache (). getHeaderValue ()); ResponseEntity responseEntity = nieuwe ResponseEntity (media, headers, HttpStatus.OK); return responseEntity; }

De ... gebruiken ResponseEntity stelt u in staat om een ​​responscode voor een bepaald verzoek te configureren.

Het expliciet instellen van de responscode is vooral handig in het geval van een uitzonderlijke gebeurtenis, bijv. als de afbeelding niet werd gevonden (FileNotFoundException) of is beschadigd (IOException). In deze gevallen hoeft u alleen de responscode in te stellen, bijv. nieuwe ResponseEntity (null, headers, HttpStatus.NOT_FOUND), in een geschikt vangblok.

Als u bovendien een aantal specifieke headers in uw antwoord moet instellen, is deze aanpak eenvoudiger dan het instellen van headers door middel van HttpServletResponse object dat door de methode als parameter wordt geaccepteerd. Het maakt de handtekening van de methode duidelijk en gericht.

5. Afbeelding retourneren met de Bron Klasse

Ten slotte kunt u een afbeelding retourneren in de vorm van de Bron voorwerp.

De Bron interface is een interface voor het abstraheren van toegang tot bronnen op laag niveau. Het wordt in het voorjaar geïntroduceerd als een beter alternatief voor de standaard java.net.URL klasse. Het biedt gemakkelijke toegang tot verschillende soorten bronnen (lokale bestanden, externe bestanden, klassenpadbronnen) zonder de noodzaak om een ​​code te schrijven die ze expliciet ophaalt.

Om deze benadering te gebruiken, moet het retourtype van de methode worden ingesteld op Bron en je moet de methode annoteren met de @ResponseBody annotatie.

5.1. Implementatie

@ResponseBody @RequestMapping (value = "/ image-resource", method = RequestMethod.GET) openbare bron getImageAsResource () {retourneer nieuwe ServletContextResource (servletContext, "/WEB-INF/images/image-example.jpg"); }

of, als we meer controle willen over de antwoordheaders:

@RequestMapping (value = "/ image-resource", method = RequestMethod.GET) @ResponseBody openbare ResponseEntity getImageAsResource () {HttpHeaders headers = nieuwe HttpHeaders (); Resource resource = nieuwe ServletContextResource (servletContext, "/WEB-INF/images/image-example.jpg"); retourneer nieuwe ResponseEntity (resource, headers, HttpStatus.OK); }

Met deze benadering behandelt u afbeeldingen als bronnen die kunnen worden geladen met de ResourceLoader interface implementatie. In dat geval abstraheer je van de exacte locatie van je afbeelding en ResourceLoader beslist van waar het wordt geladen.

Het biedt een algemene benadering om de locatie van afbeeldingen te bepalen met behulp van de configuratie, en elimineert de noodzaak om code voor het laden van bestanden te schrijven.

6. Conclusie

Van de bovengenoemde benaderingen zijn we uitgegaan van de basisbenadering en vervolgens de benadering gebruikt die profiteert van de berichtconversiefunctie van het raamwerk. We hebben ook besproken hoe de set de responscode en responsheaders kan krijgen zonder het responsobject rechtstreeks te overhandigen.

Ten slotte hebben we flexibiliteit toegevoegd vanuit het oogpunt van de afbeeldingslocaties, omdat waar een afbeelding moet worden opgehaald, wordt gedefinieerd in de configuratie die gemakkelijker direct kan worden gewijzigd.

Download een afbeelding of een bestand met Spring legt uit hoe u hetzelfde kunt bereiken met Spring Boot.

De voorbeeldcode die volgt op de tutorial is beschikbaar op GitHub.