Rückgabe von Bild- / Mediendaten mit Spring MVC

1. Übersicht

In diesem Tutorial wird veranschaulicht, wie Bilder und andere Medien mithilfe des Spring MVC-Frameworks zurückgegeben werden.

Wir werden verschiedene Ansätze diskutieren, angefangen von der direkten Manipulation von HttpServletResponse bis hin zu Ansätzen, die von der Nachrichtenkonvertierung, der Inhaltsverhandlung und der Ressourcenabstraktion von Spring profitieren . Wir werden uns jeden einzelnen genauer ansehen und ihre Vor- und Nachteile diskutieren.

2. Verwenden der HttpServletResponse

Der grundlegendste Ansatz des Image-Downloads besteht darin, direkt gegen ein Antwortobjekt zu arbeiten und eine reine Servlet- Implementierung nachzuahmen. Dies wird anhand des folgenden Snippets demonstriert:

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

Wenn Sie die folgende Anforderung ausgeben, wird das Bild in einem Browser gerendert:

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

Die Implementierung ist aufgrund von IOUtils aus dem Paket org.apache.commons.io recht einfach und unkompliziert . Der Nachteil des Ansatzes besteht jedoch darin, dass er gegenüber möglichen Änderungen nicht robust ist. Der MIME-Typ ist fest codiert, und die Änderung der Konvertierungslogik oder die Externalisierung des Bildorts erfordert Änderungen am Code.

Im folgenden Abschnitt wird ein flexiblerer Ansatz erläutert.

3. Verwenden des HttpMessageConverter

Im vorherigen Abschnitt wurde ein grundlegender Ansatz erläutert, bei dem die Funktionen zur Nachrichtenkonvertierung und Inhaltsverhandlung des Spring MVC Framework nicht genutzt werden. Um diese Funktionen zu booten, müssen wir:

  • Kommentieren Sie die Controller-Methode mit der Annotation @ResponseBody
  • Registrieren Sie einen geeigneten Nachrichtenkonverter basierend auf dem Rückgabetyp der Controller-Methode ( ByteArrayHttpMessageConverter wird beispielsweise für die korrekte Konvertierung des Byte-Arrays in eine Bilddatei benötigt).

3.1. Aufbau

Zur Darstellung der Konfiguration der Konverter verwenden wir den integrierten ByteArrayHttpMessageConverter , der eine Nachricht konvertiert, wenn eine Methode den Typ byte [] zurückgibt .

Der ByteArrayHttpMessageConverter ist standardmäßig registriert, die Konfiguration ist jedoch für jeden anderen integrierten oder benutzerdefinierten Konverter analog.

Zum Anwenden der Nachrichtenkonverter-Bean muss eine entsprechende MessageConverter- Bean im Spring MVC-Kontext registriert und die Medientypen eingerichtet werden, die verarbeitet werden sollen. Sie können es über XML mit definierenEtikett.

Dieses Tag sollte im Inneren definiert werden Tag, wie im folgenden Beispiel:

     image/jpeg image/png     

Der oben genannte Konfigurationsteil registriert ByteArrayHttpMessageConverter für die Inhaltstypen image / jpeg und image / png . Wenn Tag ist in der MVC-Konfiguration nicht vorhanden, dann wird der Standardsatz von Konvertern registriert.

Sie können den Nachrichtenkonverter auch mithilfe der Java-Konfiguration registrieren :

@Override public void configureMessageConverters(List
    
      converters) { converters.add(byteArrayHttpMessageConverter()); } @Bean public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() { ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter(); arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes()); return arrayHttpMessageConverter; } private List getSupportedMediaTypes() { List list = new ArrayList(); list.add(MediaType.IMAGE_JPEG); list.add(MediaType.IMAGE_PNG); list.add(MediaType.APPLICATION_OCTET_STREAM); return list; }
    

3.2. Implementierung

Jetzt können wir unsere Methode implementieren, die Medienanfragen verarbeitet. Wie oben erwähnt, müssen Sie Ihre Controller-Methode mit der Annotation @ResponseBody markieren und Byte [] als Rückgabetyp verwenden:

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

Geben Sie zum Testen der Methode die folgende Anforderung in Ihrem Browser aus:

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

Auf der Vorteilsseite weiß die Methode nichts über die HttpServletResponse. Der Konvertierungsprozess ist hochgradig konfigurierbar und reicht von der Verwendung der verfügbaren Konverter bis zur Angabe eines benutzerdefinierten Konverters. Der Inhaltstyp der Antwort muss nicht fest codiert sein, sondern wird basierend auf dem Anforderungspfadsuffix .jpg ausgehandelt .

Der Nachteil dieses Ansatzes besteht darin, dass Sie die Logik zum Abrufen des Bildes aus einer Datenquelle (lokale Datei, externer Speicher usw.) explizit implementieren müssen und keine Kontrolle über die Header oder den Statuscode der Antwort haben.

4. Verwenden der ResponseEntity- Klasse

Sie können ein Bild als Byte [] zurückgeben, das in die Antwortentität eingeschlossen ist . Spring MVC ResponseEntity ermöglicht nicht nur die Steuerung des Hauptteils der HTTP-Antwort, sondern auch des Headers und des Antwortstatuscodes. Nach diesem Ansatz müssen Sie den Rückgabetyp der Methode als ResponseEntity definieren und ein zurückkehrendes ResponseEntity- Objekt im Methodenkörper erstellen .

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

Mit der ResponseEntity können Sie einen Antwortcode für eine bestimmte Anforderung konfigurieren.

Das explizite Festlegen des Antwortcodes ist besonders nützlich, wenn ein außergewöhnliches Ereignis vorliegt, z. B. wenn das Bild nicht gefunden wurde ( FileNotFoundException ) oder beschädigt ist ( IOException) . In diesen Fällen muss lediglich der Antwortcode, z. B. new ResponseEntity (null, headers, HttpStatus.NOT_FOUND), in einem geeigneten catch-Block festgelegt werden.

Wenn Sie in Ihrer Antwort bestimmte Header festlegen müssen, ist dieser Ansatz außerdem einfacher als das Festlegen von Headern mithilfe des HttpServletResponse- Objekts, das von der Methode als Parameter akzeptiert wird. Es macht die Methodensignatur klar und fokussiert.

5. Rückkehr Bild Mit der Ressourcenklasse

Schließlich können Sie ein Bild in Form des Ressourcenobjekts zurückgeben .

Die Ressourcenschnittstelle ist eine Schnittstelle zum Abstrahieren des Zugriffs auf Ressourcen auf niedriger Ebene. Es wird im Frühjahr als leistungsfähigerer Ersatz für die Standardklasse java.net.URL eingeführt. Es ermöglicht den einfachen Zugriff auf verschiedene Arten von Ressourcen (lokale Dateien, entfernte Dateien, Klassenpfadressourcen), ohne dass ein Code geschrieben werden muss, der sie explizit abruft.

Um diesen Ansatz zu verwenden, sollte der Rückgabetyp der Methode auf Resource festgelegt werden, und Sie müssen die Methode mit der Annotation @ResponseBody versehen .

5.1. Implementierung

@ResponseBody @RequestMapping(value = "/image-resource", method = RequestMethod.GET) public Resource getImageAsResource() { return new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); }

oder, wenn wir mehr Kontrolle über die Antwortheader haben wollen:

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

Mit diesem Ansatz behandeln Sie Bilder als Ressourcen, die mithilfe der Implementierung der ResourceLoader- Schnittstelle geladen werden können. In diesem Fall abstrahieren Sie vom genauen Speicherort Ihres Bildes und ResourceLoader entscheidet, von wo es geladen wird.

Es bietet einen gängigen Ansatz, um die Position von Bildern mithilfe der Konfiguration zu steuern und das Schreiben von Code zum Laden von Dateien zu vermeiden.

6. Fazit

Unter den oben genannten Ansätzen haben wir vom grundlegenden Ansatz ausgegangen und dann den Ansatz verwendet, der von der Nachrichtenkonvertierungsfunktion des Frameworks profitiert. Wir haben auch besprochen, wie Sie den Antwortcode und die Antwortheader festlegen können, ohne das Antwortobjekt direkt zu übergeben.

Schließlich haben wir die Flexibilität unter dem Gesichtspunkt der Bildpositionen hinzugefügt, da in der Konfiguration festgelegt ist, woher ein Bild abgerufen werden soll, was im laufenden Betrieb einfacher zu ändern ist.

Das Herunterladen eines Bildes oder einer Datei mit Spring erklärt, wie Sie mit Spring Boot dasselbe erreichen.

Der Beispielcode nach dem Tutorial ist bei GitHub verfügbar.