JavaのWebアプリケーション開発フレームワークによる、Webサイト開発の顛末記です。

EclipseのMavenを使った、Spring-MVC、Thymeleaf、MyBatis 等のプログラミングテクニックを、
備忘録的に記録しています。実際に動くソースコードを多用して説明していますので、
これからEclipseや、Spring-MVCを始めたいと思っている人にとって、少しでも参考になれば幸いです。
■応用の森 Spring-MVC コントローラの戻り値
Spring-MVC では@Controllerまたは@RestControllerアノテーションが付いたクラスを
コントローラとみなして動作します。
@Controllerアノテーションは、主にWebページ単位制御用のコントローラクラスに使用するアノテーションで、
このクラスのメソッドの戻り値は、基本的にJSPやHTMLの遷移先view名を指定します。
@RestControllerは、JSONやXML等の文字列を返すWebAPI用のコントローラクラスに使用するアノテーションで、
基本的にはViewには遷移しないため戻り値は、コンテンツのBodyそのものとなります。
しかしながら、場合によっては@RestControllerでviewを返したい場合や、その逆に
@Controllerでコンテンツを返したい場合などもないことはありません。
ここでは、@Controllerまたは@RestControllerアノテーションコントローラのハンドラが
どのような戻り値を返すことができるか
簡単なテストを行って一覧にまとめてみました。
○:使用可、△:使い道が今一つ浮かばないので割愛
  @Controller @RestController
view(String/ModelAndView) ○ ※1) ○ ※2)
contents(String) ○ ※3) ○ ※4)
forward(String) ○ ※5) △できなくはないけど。。
redirect(String) ○ ※6) △できなくはないけど。。
FileDownload(Resource/void) ○ ※7) ○ ※7)
※1)@Controllerクラスの@RequestMapping ハンドラ・メソッドのもっとも単純な戻り値です。
   Viewの遷移先を指定します。
   view名はSpring設定ファイル(applicationContext.xml)の<templateResolver>で定義されているprefix配下の
   suffixの拡張子を持つファイルを、拡張子をはずした名前で指定します。
   
   @Controller
   public class MyClass {
    @RequestMapping("/mapping")
    public String handler_method() {
      return "viewname";  //view名 viewname.html に遷移します。
    }
   }

※2)@RestControllerクラスの@RequestMapping ハンドラ・メソッドでViewの遷移先を指定。
   @RestControllerクラスは通常は、コンテンツを返しますが、viewを返すこともできます。
   viewの指定方法は、※1)と同様にModelAndView()の引数に指定することができます。
   
   @RestController
   public class MyClass {
    @RequestMapping("/mapping")
    public ModelAndView handler_method() {
      return new ModelAndView("viewname");  //view名 viewname.html に遷移します。

    }
   }

※3)@Controllerクラスの@RequestMapping ハンドラ・メソッドでView遷移ではなくコンテンツを返す指定。
   メソッドに@ResponseBodyアノテーションを付加することで
   View遷移ではなく文字列形式のコンテンツを返すことができます。
   
   @Controller
   public class MyClass {
    @RequestMapping("/mapping")
    @ResponseBody
    public String handler_method() {
      return "<div>コンテンツ</div>";
    }
   }

※4)@RestControllerクラスの@RequestMapping ハンドラ・メソッドでコンテンツを返す一番単純な戻り値です。
   @Controllerクラスと違い、@ResponseBodyを付ける必要がありません。
   
   @RestController
   public class MyClass {
    @RequestMapping("/mapping")
    public String handler_method() {
      return "{"key":"value"}";  //JSON形式を返す
    }
   }
   
   @RequestMappingでは、コンテンツタイプを指定することができます。
   例)@RequestMapping(value = "/mapping", produces = "application/xml") や
     @RequestMapping(value = "/mapping", produces = "text/html;charset=UTF-8") や
     @RequestMapping(value = "/mapping", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 
   など、色々と指定できます。
   返却文字列に日本語全角文字が含まれている場合、ブラウザで文字化けするので、この指定は必須です。
   JSONや、XMLデータを返したいような場合は、この形式で返すのが適しています。
   

※5)@Controllerクラスの@RequestMapping ハンドラ・メソッドでpageをフォワードする指定。
   戻り値で指定する遷移先に"forward:"を付けると他の@RequestMapping ハンドラ・メソッドにフォワードします。
   ここで注意することは、遷移先はリクエストパターンを含めたURLを指定する必要があります。
   ※)ここでは、リクエストパターンに *.xhtml を使っているので、****.xhtml を指定しています。
   
   @Controller
   public class MyClass {
    @RequestMapping("/mapping")
    public String handler_method() {
      return "forward:/forward_to.xhtml"; // /forward_to.xhtml にフォワードする
    }
   }

※6)@Controllerクラスの@RequestMapping ハンドラ・メソッドでpageをリダイレクトする指定。
   戻り値で指定する遷移先に"redirect:"を付けると他の@RequestMapping ハンドラ・メソッドにリダイレクトします。
   ここで注意することは、遷移先はリクエストパターンを含めたURLを指定する必要があります。
   ※)ここでは、リクエストパターンに *.xhtml を使っているので、****.xhtml を指定しています。
   
   @Controller
   public class MyClass {
    @RequestMapping("/mapping")
    public String handler_method() {
      return "redirect:/redirect_to.xhtml"; // /redirect_to.xhtml にリダイレクトする
    }
   }
   
   リダイレクト先は、まったく別のURLも指定可能です。
   例)return "redirect:https://www.google.co.jp/";
   
   
   ・フォワードとリダイレクトの違いについて
   ネットを探すと、フォワードとリダイレクトの違いについてはいくらでも情報があるので、
   基本的な違いは、それらを読んでもらうことにして、
   Spring-MVCにおける具体的なフォワードとリダイレクトの違いについて簡単に説明します。
   フォワード :・from ⇒ to にフォワードする際に、fromが持っているパラメータを toに継承することができます。
          ・ブラウザのURLは、from のままで、to の処理が実行されます。
          ※この性質上、ブラウザのリロード処理で思わぬ動きをすることがあるので注意が必要です。
   
   リダイレクト:・from ⇒ to にリダイレクトする際に、fromが持っているパラメータは toに継承することはできません。
           例外として、RedirectAttributesというFlash scopeを使うことで、パラメータ値を継承可能となっています。
           ただし、クラスのオブジェクトのようなBeanは継承できないみたいです。
          ・ブラウザのURLは、to に変わります。
           さらに、RedirectAttributesを使用した場合、リダイレクトURLの後ろに、パラメータが付加されて見えてしまう。
           ちょっとカッコ悪いです。

※7)ファイルをダウンロードする指定。
  7-1)Resourceインターフェース形式でダウンロードする。
   
   import org.springframework.core.io.Resource;
   @Controller
   public class MyClass {
    @RequestMapping("/mapping")
    public Resource handler_method() {
      return new FileSystemResource("downloadfile名");
    }
   }
   
   ・メリット :シンプルなコードでファイルのダウンロードが可能
   ・デメリット:ファイルの形式にも拠りますが、ダウンロードファイルは、
          ブラウザに表示され、ファイルとしてダウンロードできない。

  7-2)HttpServletResponse形式でダウンロードする。(昔ながらのやり方)
   
   @Controller
   public class MyClass {
    @RequestMapping("/mapping")
    public void handler_method(HttpServletResponse res) {
      File file = new File("downloadfile名");
      //ファイル名に全角がある場合(Chrome/IE)Safari:NG
      String fname = URLEncoder.encode(file.getName(), "UTF-8");
      //attachment ⇒ inline にすれば、ブラウザで表示
      res.setHeader("Content-Disposition","attachment; filename=\""+fname+"\"");
      //ファイル名に全角がある場合FireFoxは以下で行ける
      //res.setHeader("Content-Disposition","attachment; filename*=\"UTF-8''"+fname+"\"");
      
      res.setContentLength((int) file.length());
      FileCopyUtils.copy(new FileInputStream(file), res.getOutputStream());
    }
   }
   
   ・メリット :ダウンロードファイルは、ファイルとしてダウンロードが可能。
   ・デメリット:特になし。

 

これ以外にも、使える戻り値はまだいろいろとあるみたいですが、
よっぽどのことがない限り、これだけ使い方を知っていれば十分ではないかと思います。