Spring MVCのコントローラのメソッドで使える戻り値にどんなものがあるか、どういう使い方ができるかをざっくりまとめてみた。
@Controller
と@RestController
の違い
先に@Controller
と@RestController
の違いを説明しておく。
Spring MVC ではコントローラクラスにアノテーションで@Controller
または@RestController
を付ける。
@Controller
は主にWebページ用のコントローラで使用する。
Webページ用コントローラはJSPやテンプレートエンジンのViewに遷移してレスポンスのHTMLを生成するので、基本的にメソッドの戻り値はViewの遷移先を指定するのに使用する。
@RestController
はJsonやXML等を返すWebAPI用のコントローラで使用する。
こちらはViewに遷移しないのでメソッドの戻り値はレスポンスのコンテンツになる。
@Controller
戻り値をStringにする
Viewの遷移先を指定する一番単純なやり方。
@RequestMapping("/method1")
public String method1() {
return "/index.html";
}
戻り値をModelAndViewにする
ModevAndViewを使用するとViewに渡したい情報を一緒に返すことができる。
@RequestMapping("/method2")
public ModelAndView method2() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject(new User("紀伊", "太郎"));
modelAndView.setViewName("/index.html");
return modelAndView;
}
フォワード
戻り値で指定する遷移先に"forward:"を付けると他のコントローラメソッドに遷移する。
@RequestMapping("/forward1")
public String forward1() {
return "forward:method1";
}
リダイレクト
リダイレクトしたい場合は"redirect:"を付ける。
@RequestMapping("/redirect1")
public String redirect1() {
return "redirect:method1";
}
外部URLを指定する事もできる。
@RequestMapping("/redirect2")
public String redirect2() {
return "redirect:https://www.google.co.jp/";
}
コントローラで直接コンテンツを返す
メソッドに@ResponseBody
を付けると戻り値で直接レスポンスのコンテンツを返す事ができる。
@RequestMapping("/text1")
@ResponseBody
public String text1() {
return "text content";
}
戻り値をvoidにしてHttpServletResponseを引数で受け取るようにすれば、直接レスポンスを書き込む事もできる。
@RequestMapping("/text2")
public void text2(HttpServletResponse res) throws IOException {
res.getWriter().write("text content");
}
@RestController
戻り値でテキストコンテンツを返す
@RestController
を付けたコントローラのメソッドでは@ResponseBody
を付けなくても戻り値がレスポンスのコンテンツになる。
@RequestMapping("/text1")
public String text1() {
return "text content";
}
HttpServletResponseでテキストコンテンツを返す
@Controller
の場合と同じくHttpServletResponseで直接コンテンツを書き込める。
@RequestMapping("/text2")
public void text2(HttpServletResponse res) throws IOException {
res.getWriter().write("text content");
}
コンテンツタイプを指定する
コンテンツタイプは@RequestMapping
のproducesで指定する。
@RequestMapping(value = "/xml1", produces = "application/xml")
public String xml1() {
return "<a><b>content</b></a>";
}
org.springframework.http.MediaTypeクラスにコンテンツタイプの定数が定義してあるのでこれを使うといい。
@RequestMapping(value = "/xml2", produces = MediaType.APPLICATION_XML_VALUE)
public String xml2() {
return "<a><b>content</b></a>";
}
HTTPステータスやレスポンスヘッダを指定する
HTTPステータスやコンテンツタイプ以外のレスポンスヘッダも指定したい時は、戻り値をResponseEntityにする。
@RequestMapping("/responseEntity")
public ResponseEntity<String> responseEntity() {
HttpHeaders headers = new HttpHeaders();
headers.add("header1", "heaer1-value");
HttpStatus status = HttpStatus.NOT_FOUND;
return new ResponseEntity<>("text content", headers, status);
}
JSONを返す
メソッドの戻り値を任意のクラスにすれば、SpringMVCがJacksonを使用してうまいことやってくれる。
@RequestMapping("/json")
public List<User> json() {
return Arrays.asList(new User("紀伊", "太郎"), new User("紀伊", "花子"));
}
[
{
"lastName": "紀伊",
"firstName": "太郎"
},
{
"lastName": "紀伊",
"firstName": "花子"
}
]
ファイルのダウンロード
よく見かけるサンプルではHttpServletResponseに直接書き込んでるものが多い。
@RequestMapping("/file1")
public void file1(HttpServletResponse res) throws IOException {
File file = new File("pom.xml");
res.setContentLength((int) file.length());
res.setContentType(MediaType.APPLICATION_XML_VALUE);
FileCopyUtils.copy(new FileInputStream(file), res.getOutputStream());
}
戻り値をorg.springframework.core.io.Resource
インターフェースにするともっと簡単に実装できる。
@RequestMapping(value = "/file2", produces = MediaType.APPLICATION_XML_VALUE)
public Resource file2() {
return new FileSystemResource("pom.xml");
}
戻り値がResourceだとContent-Length
は自動的に設定してくれる。
org.springframework.core.io.Resource
の実装クラスでよく使いそうなものをピックアップしておく。
- FileSystemResource
- ClassPathResource
- ServletContextResource
- ByteArrayResource
- InputStreamResource
最後に
ここに書いたのはあくまで自分が知っている範囲の事なので、他にもやり方は色々あると思う。
もっと詳しく知りたい方はSpring Frameworkのドキュメント等を参照してほしい。
また、時間があったらRequestMappingの指定方法やメソッドの引数についてもまとめてみたいと思う。