SpringMVCのコントローラの戻り値
ContorollerからView(jspとかhtmlとか)へ戻り値を戻していますが、これが何を表しているかというとファイル名になります。(String型の場合)
@RequestMapping(value = "/", method = RequestMethod.GET) public String home(Locale locale, Model model) { logger.info("Welcome home! The client locale is {}.", locale); Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); String formattedDate = dateFormat.format(date); model.addAttribute("serverTime", formattedDate ); return "home"; }
表示されるのは、WEB-INF\views\home.jspが表示されます。
このhome.jspのhomeとマッピングされています。戻り値に拡張子がないですね。ということで追加してみます。(上記ソースを”home.jsp”と変更するだけ)
これでアクセスしてみます。
404エラーとなり、見てのとおりhome.jsp.jspにアクセスしようとしています。
どこでこの拡張子が付加されているかと言うと、web.xml内の以下部分を見ます。
<servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<param-value>タグで指定されているファイルでViewの指定がされますので、そのファイルを開きます。
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/views/" /> <beans:property name="suffix" value=".jsp" /> <!-- ここでサフィックスに.jspを指定しています --> </beans:bean>
Google翻訳では以下のように翻訳されました。
/ WEB-INF / viewsディレクトリの@Controllersによる.jspリソースへのレンダリングのために選択されたビューを解決します。
絶対にViewはjspファイルなら問題ないですがその他拡張子のファイルも有りえるなら、この1行はコメントアウトしたほうがよいです。
戻り値はString型でも色々ある
String型の戻り値にforwardやredirectといったキーワードをつけることによって違う動きをさせることができます。
redirectする
以下のように記述することによりメソッドをチェーンすることが可能です。
@RequestMapping(value = "/", method = RequestMethod.GET) public String home(Locale locale, Model model) { logger.info("Welcome home! The client locale is {}.", locale); Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); String formattedDate = dateFormat.format(date); model.addAttribute("serverTime", formattedDate ); return "redirect:home1"; // home1メソッドにリダイレクトする } @RequestMapping(value = "/home1", method = RequestMethod.GET) public String home1(Locale locale, Model model) { model.addAttribute("serverTime", "redirect to home1" ); return "home"; }
画面表示内容からhome1メソッドにリダイレクトされているのが確認できます。
forwardする
redirectとよく似ていますが今度はhomeメソッドからhome1メソッドにforwardしてみます。
@RequestMapping(value = "/", method = RequestMethod.GET) public String home(Locale locale, Model model) { logger.info("Welcome home! The client locale is {}.", locale); Date date = new Date(); DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); String formattedDate = dateFormat.format(date); model.addAttribute("serverTime", formattedDate ); return "forward:home1"; // redirectをforwardに変更しただけ } @RequestMapping(value = "/home1", method = RequestMethod.GET) public String home1(Model model) { model.addAttribute("serverTime", "redirect to home1" ); return "home"; }
これもhome1メソッドにforwardされていることが確認できます。
上記だけだと、redirectとforwardの違いがわかりませんが、よくみるとクエリ文字列が違います。
以下のような違いがあります。
キーワード | URLの違い |
---|---|
redirect | 遷移先のパス+クエリ文字列が渡される |
forward | URLに変更がない |
@ResponseBodyをつける
@RequestMappingと同時に@ResponseBodyも付加するとレスポンスをボディに返すことができます。JSONなどを返したいときはこのアノテーションが使えますね。
@RequestMapping(value = "/", method = RequestMethod.GET) @ResponseBody public String home(Locale locale, Model model) { return "text text"; }
以下、実行例です。
画面に直接文字列が帰ってきているのが確認できます。
String型ではなく、ModelAndViewクラスをリターンする
このModelAndViewクラスがよく使われるかなと思います。クラス名のとおり、ModelとViewを管理するクラスです。
@RequestMapping(value = "", method = RequestMethod.GET) public ModelAndView home() { ModelAndView mv = new ModelAndView(); mv.addObject("serverTime", "ModelAndView!!!"); mv.setViewName("home"); // ここでviewを指定する return mv; }
まず、戻り値がString型からModelAndView型に変わります。
addObjectメソッドでModelからの戻り値を設定することになると思います。ここでは簡単にString型にしています。
setViewNameメソッドで、今までreturnしていたview名(jsp)をセットします。
以下、実行例です。
ModelAndViewのインスタンス生成時にView名を指定する
実は、ModelAndViewクラスはコンストラクタでView名を指定することができます。
なので、setViewName()メソッドは分岐がなければ使うことはないはずです。
ModelAndView mv = new ModelAndView("home"); // mv.setViewName("home");と同じ
KHI入社して退社。今はCONFRAGEで正社員です。関西で140-170/80~120万から受け付けております^^
得意技はJS(ES6),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^
コメント