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を見て、バリデーション結果を表示しています。