このページに書いてあること
Springにおいて、リクエストのパスなどを設定する@RequestMappingの使い方と、それを少し発展させた使い方を説明します。
※特別なことではないんですが、Spring系の本とかでも省略されていることがあるので、意外と知らない人いるのでは?
具体的には,consumesとproducesについてです。
前提
- Spring MVC(Bootでも同じ)の4.x以上。
まずは結論とサンプル
package com.example.demo;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SampleController {
@RequestMapping(method=RequestMethod.GET,value="/sample",consumes = "application/json",produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String execute1() {
System.out.println("execute1");
return "{\"success\":\"aaa\"}";
}
@RequestMapping(method=RequestMethod.GET,value="/sample",consumes = "application/x-www-form-urlencoded",produces = MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public String execute2() {
System.out.println("execute2");
return "<test>success</test>";
}
}
このコードでSpring Bootを起動してリッスンさせ、GETリクエストのヘッダにapplication/jsonまたはapplication/x-www-form-urlencodedを指定してアクセスした場合、パスは同じにもかかわらず実行されるメソッドが変わります。
さらに、レスポンスのタイプもJSONとXMLで変えています。
リクエスト
このURLにhttp://localhost:8080/sampleに以下の2パターンでリクエストを送ります。
- content-typeにapplication/jsonを付与
- content-typeにapplication/x-www-form-urlencodedを付与
それぞれのリクエストに対するレスポンスは以下。
- {"success": "aaa"}
- <test>success</test>
それぞれJSONとXMLで返ってきた。
これはproducesで指定したcontent-typeで返ってきているということになります。
@RequestMappingの使い方
@RequestMappingはControllerクラスのメソッドに付与するアノテーションで、URLやHTTPメソッドの指定をするために使用します。
例えば、http://localhost:8080/sampleというURLを用意したいときに以下のようにします。
@Controller
public class SampleController {
@RequestMapping(method=RequestMethod.GET,value="/sample")
@ResponseBody
public String execute1() {
System.out.println("execute1");
return "success";
}
@RequestMapping(method=RequestMethod.GET,value="/sample2")
@ResponseBody
public String execute2() {
System.out.println("execute2");
return "success";
}
}
このコードでは@RequestMappingにより以下のことをしています。
- GETメソッドを受信
- URLは/sampleと/sample2が使用可能
このようになっています。
「method=XX」で受信可能なHTTPメソッドを指定しています。例えばGETやPOST、DELETEなどを指定します。対応していないメソッドでリクエストをした場合は404 Not Foundでエラーとなります。
「value=xxx」でURLを指定しています。ここに指定した文字列がURLとして外部に公開された上で、一致した場合はそのメソッドが実行されます。
つまり、/sampleというパスでアクセスすると、execute1()というメソッドが実行され、コンソールにexecute1という文字列が表示されます。
ただこれだけなんですが、@RequestMappingの引数はもう少し種類があって、それらを使うことでプレゼンテーション層を簡単に分けることができるようになります。
consumes
受信するcontent-typeを指定するものです。
@RequestMapping(method=RequestMethod.GET,value="/sample",consumes = "application/json")
とすることで、リクエストのヘッダにあるcontent-typeが"application/json"の場合のみ受け付けてメソッドを実行するようになります。
ここにapplication/xmlなどを指定したら、そのcontent-typeを持つ場合に受理します。
どんなときに役立つか
例えば、処理は同じなんだけども複数の形式のリクエストを取り扱いたいような場合です。具体的にはJSON形式とPOST電文を両方扱いたいとかですね。
これらはリクエストの形式が違いますから、consumesがなかった場合は同じメソッドでリクエストを受け付けたあと、メソッドの内部で電文形式をcontent-typeなどから判別して変換してやる必要が出てしまいます。
結構めんどくさいですよね。Springの機能が使えなくなり、自前で変換してやらないといけません。
consumesがあればcontent-typeごとにメソッドを簡単に分離できるようになりますから、電文形式の違いに悩む必要はなくなります。
こんな感じになります。それを、consumesを使うことで、同じurlでメソッドを分けることができますから、リクエスト受信時のデータ変換をSpringの自動変換に任せることができるようになります、
これは、他のcontent-typeを追加することになった場合の修正も容易になるので是非使っていきましょう。
produces
レスポンスのタイプを指定するためのものです。
画面を返したければtext/htmlですし、JSONで返したければapplication/jsonとなります。
自前でいろいろなコンテンツタイプで返却したいときに使います。
@RequestMapping(method=RequestMethod.GET,value="/sample",consumes = "application/x-www-form-urlencoded",produces = MediaType.APPLICATION_XML_VALUE)
どんなときに役立つか
この例ではXMLを返すように指定しています。consumesと組み合わせることで、JSONできたときはJSONで返す、XMLできたときはXMLで返すなどの使い方をすることにより、同じ機能を様々なフォーマットで提供できるようになります。
これを使わない場合、consumesの時と同様に返したい形式をif分で一生懸命判定してやる必要がありますから、だいぶ楽になります。