ModelAndViewを使用する
前作でModelクラスを使ったものをやりましたが、これをModelAndViewクラスに変えてみましょう。「CTRL+SHIFT+P」でspring initから始めてinitializrを起動してください。
「Spring web web」 「thymeleaf」を追加して、pom.xmlで「webjarsのbootstrap」を追加してください。わからない方はModelを使用するを参照してください
変わるのは「DateController.java」だけで、それ以外はModelの時と同じです。
package jp.co.etlab.spmavtest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; @Controller public class DateController { @RequestMapping(value="/", method=RequestMethod.GET) public ModelAndView index(ModelAndView mav) { mav.addObject("message", "日付の計算を行います。日付と差分を入力してください。"); mav.setViewName("index"); return mav; } @RequestMapping(value="/result", method=RequestMethod.POST) public ModelAndView datecalc(@RequestParam("sdate") String ssdate, @RequestParam("dplus") String splusd, ModelAndView mav) { DateModel dm = new DateModel(); dm.setSdate(ssdate); dm.setDplus(splusd); //計算 dm.calcDate(); mav.addObject("message", dm.getSdate() + " の" + Math.abs(dm.getDplus()) + "日" + (dm.getDplus()>0 ? "後" : "前") + "は " + dm.getCdate() + "です"); return mav; } }
関数の引数が「ModelAndView」に変わりました。またaddAttributeがaddObjectに変わりました。またreturnがオブジェクトになり、戻り先はsetViewNameになりました。これだけです。
mavenでinstall,compile,packageしてください。
起動方法を変えましょう。spring boot extension packを入れたので「spring boot dashboard」のボタンが左の列に出来ています。これを使ってtomcatへの登録と停止ができます。
同じようにブラウザで表示、実行ができます。
停止もdashboardでできます
バリデーションを使う
今度はバリデーションを少し使ってみましょう。実はネットに載っている方法を色々やったのですが、うまくいきませんでした。本も購入してやってみましたが、どうもしっくりきません。なのでとりあえずの方法を出しておきます。
今回やっているのは、Model,ModelAndViewなどをやった実験と同じ流れのなかでやります。今まではsdateもdplusもrequiredにしているので抜けることがなかったので、sdateに関してだけrequiredをあえて外しています。dplusはメッセージに関してどうも納得いかないのでまた後程です。
例によってspring initializrで作製してしてください。今度は「spring Web」 「thymeleaf templates」 「validation」と手入力でbootstrap入れてください。
pom.xmlはこんな風になると思います。
<dependencies> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>5.3.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
今度はソースが変わります。implementsでWebMvcConfigurerを入れます。registoryの登録が増えています
package jp.co.etlab.spvalidtest; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import jakarta.validation.Valid; @Controller public class DateController implements WebMvcConfigurer{ @SuppressWarnings("null") @Override public void addViewControllers(ViewControllerRegistry registory) { registory.addViewController("/result").setViewName("result"); } @GetMapping("/") public String getMethodName(DateModel dateModel) { return "index"; } @PostMapping("/result") public String postMethodName(@Valid DateModel dateModel,BindingResult br, Model model) { if (br.hasErrors()) { return "index"; } //計算 dateModel.calcDate(); model.addAttribute("message", dateModel.getSdate() + " の" + Math.abs(dateModel.getDplus()) + "日" + (dateModel.getDplus()>0 ? "後" : "前") + "は " + dateModel.getCdate() + "です"); return "result"; } }
BindingResultでバリデーションが行われ、エラーがあれば.hasErrors()はtrueになります。その時はindexに戻っていますが、 その時dateModelに宣言したmessageが渡って、th:if="${#fields.hasErrors('sdate')}" th:errors="*{sdate}"でエラーがあれば表示されます。
正常時は、今まで通りです。index.htmlがそのバリデーション関係で変わっています
<!doctype html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ModelAndView Test</title> <link th:href="@{/webjars/bootstrap/5.3.0/css/bootstrap.min.css}" rel="stylesheet"> </head> <body> <div class="container"> <main> <div class="py-5 text-center"> <h2>ModelAndView test</h2> <p class="lead" th:text="${message}"></p> </div> <div class="text-center"> <h4 class="mb-3">日付計算</h4> <form class="needs-validation" th:action="@{/result}" th:object="${dateModel}" method="POST"> <div class="row g-12"> <div class="col-sm-6"> <label for="sdate" class="form-label">日付</label> <input type="date" class="form-control" id="sdate" name="sdate" placeholder="yyyy-MM-ddで日付を記述してください" value="" th:field="*{sdate}"> <span class="text-danger" th:if="${#fields.hasErrors('sdate')}" th:errors="*{sdate}">Date Error</span> </div> <div class="col-sm-6"> <label for="plusd" class="form-label">前後日付</label> <input type="number" class="form-control" id="dplus" name="dplus" placeholder="+ -付きで日数を入力してください" value="" required> <span class="text-danger" th:if="${#fields.hasErrors('dplus')}" th:errors="*{dplus}">Data plus Error</span> </div> </div> <hr class="my-4"> <button class="w-100 btn btn-primary btn-lg" type="submit">計算実行</button> </form> </div> </main> <footer class="my-5 pt-5 text-body-secondary text-center text-small"> <p class="mb-1">© 2024 Etlab</p> </footer> </div> <script th:src="@{/webjars/bootstrap/5.3.0/js/bootstrap.min.js}"></script> </body> </html>
formでobjectを展開しています。その要素としてのsdateを見て、バリデーション結果を表示しています。