Spring MVCで画像/メディアデータを返す
1概要
このチュートリアルでは、Spring MVCフレームワークを使用して画像やその他のメディアを返す方法を説明します。
メッセージ変換
、
Content Negotiation
のように直接
HttpServletResponse
を操作することから始める方法をいくつか説明しますSpringの
Resource
抽象化。それぞれを詳しく見て、それぞれの長所と短所を説明します。
2
HttpServletResponse
を使用する
画像ダウンロードの最も基本的なアプローチは、
response
オブジェクトに対して直接働きかけ、純粋な
Servlet
実装を模倣することです。そして、それは以下のスニペットを使って実証されます:
@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());
}
次のリクエストを発行すると、ブラウザに画像が表示されます。
http://localhost:8080/spring-mvc-xml/image-manual-response.jpg
実装は
org.apache.commons.io
パッケージの
IOUtils
のおかげでかなり簡単で単純です。ただし、このアプローチの欠点は、潜在的な変化に対して頑健ではないことです。 MIMEタイプはハードコーディングされており、変換ロジックの変更やイメージの場所の外部化にはコードの変更が必要です。
次のセクションでは、より柔軟な方法について説明します。
3
HttpMessageConverterを使う
前のセクションでは、リンクを利用しない基本的なアプローチについて説明しました。/spring-httpmessageconverter-rest[メッセージ変換]および
Content Negotiation
Spring MVCの機能フレームワークこれらの機能をブートストラップするには、次のことが必要です。
-
@ ResponseBody
アノテーションでコントローラメソッドにアノテーションを付ける -
の戻り型に基づいて適切なメッセージコンバータを登録する
コントローラメソッド(バイト配列から画像ファイルへの正しい変換に必要な
ByteArrayHttpMessageConverter
など)
3.1. 構成
コンバータの設定を紹介するために、メソッドが
byte[]
型を返すたびにメッセージを変換する組み込みの
ByteArrayHttpMessageConverter
を使用します。
ByteArrayHttpMessageConverter
はデフォルトで登録されていますが、設定は他の組み込み型またはカスタムコンバータと同様です。
メッセージコンバータBeanを適用するには、Spring MVCコンテキスト内に適切な
MessageConverter
Beanを登録し、処理する必要があるメディアタイプを設定する必要があります。
<mvc:message-converters>
タグを使用してXMLで定義できます。
このタグは、次の例のように、
<mvc:annotation-driven>
タグ内に定義する必要があります。
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>image/jpeg</value>
<value>image/png</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
前述の構成部分は、
image/jpeg
および
image/png
応答コンテンツタイプに
ByteArrayHttpMessageConverter
を登録します。
<mvc:message-converters>
tagがmvc設定に存在しない場合は、デフォルトのコンバータセットが登録されます。
また、Java設定
を使用してメッセージコンバータ
を登録することもできます。
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(byteArrayHttpMessageConverter());
}
@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
return arrayHttpMessageConverter;
}
private List<MediaType> getSupportedMediaTypes() {
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.IMAGE__JPEG);
list.add(MediaType.IMAGE__PNG);
list.add(MediaType.APPLICATION__OCTET__STREAM);
return list;
}
3.2. 実装
これでメディア要求を処理するメソッドを実装できます。前述したように、コントローラメソッドに
@ ResponseBody
アノテーションを付け、戻り型として
byte[]
を使用する必要があります。
@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);
}
メソッドをテストするには、ブラウザで次のリクエストを発行します。
http://localhost:8080/spring-mvc-xml/image-byte-array.jpg
利点として、このメソッドは__HttpServletResponseについて何も知りません。変換プロセスは、利用可能なコンバータの使用からカスタム変換の指定まで、高度に設定可能です。
応答のコンテンツタイプは、ハードコーディングする必要はなく、リンク:/path-mvc-content-negotiation-json-xml[negotiated]で、要求パスのサフィックス
.jpg
に基づいています。
このアプローチの欠点は、データソース(ローカルファイル、外部ストレージなど)から画像を取得するためのロジックを明示的に実装する必要があり、応答のヘッダーやステータスコードを制御できないことです。
4
ResponseEntity
クラスを使用する
Response Entity
にラップされた
byte[]
として画像を返すことができます。
Spring MVCの
ResponseEntity
は、HTTP Responseの本文だけでなく、ヘッダとresposeステータスコードの制御も可能にします。
このアプローチに従って、メソッドの戻り型を
ResponseEntity <byte[]>
として定義し、戻り値の
ResponseEntity
オブジェクトをメソッド本体に作成する必要があります。
@RequestMapping(value = "/image-response-entity", method = RequestMethod.GET)
public ResponseEntity<byte[]> 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<byte[]> responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK);
return responseEntity;
}
ResponseEntity
を使用すると、特定のリクエストに対するレスポンスコードを設定できます。
応答コードを明示的に設定することは、例外的なイベントが発生した場合に特に役立ちます。画像が見つからなかった場合(
FileNotFoundException
)または破損している場合(
IOException)このような場合、必要なのはレスポンスコードを設定することだけです。
new ResponseEntity <>(null、ヘッダー、HttpStatus.NOT
FOUND)、
適切なcatchブロック内。
さらに、レスポンスに特定のヘッダを設定する必要がある場合、この方法はパラメータとしてメソッドによって受け入れられる
HttpServletResponse
オブジェクトを使用してヘッダを設定するよりも簡単です。メソッドのシグネチャを明確かつ的確にします。
5
Resource
クラスを使用して画像を返す
最後に、
Resource
オブジェクトの形式で画像を返すことができます。
Resource
インタフェースは、低レベルのリソースへのアクセスを抽象化するためのインタフェースです。これはSpringで標準の
java.net.URL
クラスのより有能な代替品として導入されました。明示的にそれらを取得するコードを書く必要なしにそれは異なるタイプのリソース(ローカルファイル、リモートファイル、クラスパスリソース)への簡単なアクセスを可能にします。
この方法を使用するには、メソッドの戻り型を
Resource
に設定し、メソッドに
@ ResponseBody
アノテーションを付ける必要があります。
5.1. 実装
@ResponseBody
@RequestMapping(value = "/image-resource", method = RequestMethod.GET)
public Resource getImageAsResource() {
return new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg");
}
あるいは、レスポンスヘッダをもっと制御したい場合は、
@RequestMapping(value = "/image-resource", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<Resource> getImageAsResource() {
HttpHeaders headers = new HttpHeaders();
Resource resource =
new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg");
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
このアプローチを使用すると、
ResourceLoader
インターフェース実装を使用してロードできるリソースとして画像を扱います。そのような場合、あなたはあなたのイメージの正確な位置から抽象化し、
ResourceLoader
はそれがどこからロードされるかを決定します。
これは、設定を使用してイメージの場所を制御し、ファイルロードコードを書く必要性を排除するための一般的なアプローチを提供します。
6. 結論
前述のアプローチの中では、フレームワークのメッセージ変換機能から恩恵を受けるアプローチを使用するよりも、基本的なアプローチから始めました。また、応答オブジェクトを直接処理せずに、応答コードと応答ヘッダーを設定する方法についても説明しました。
最後に、イメージの場所から見た柔軟性が追加されました。イメージをどこから取得するかは、その場で変更するのが簡単な構成で定義されているためです。
チュートリアルに続くサンプルコードはhttps://github.com/eugenp/tutorials/tree/master/spring-mvc-xml[GitHub]で入手可能です。