tamuraです。 今回はDI(Dependency Injection)を使っていきます。
目標
- サービスを定義する
- サービスの実装を作る
part3のソースをベースにしています。
構成
このようなディレクトリ構成にします。
rc/
main/
java/
hello/
AppConfig.java
bean/
GreetingBean.java
controller/
GreetingController.java
service/
GreetingService.java
impl/
GreetingServiceImpl.java
init/
Initializer.java
resources/
templates/
greeting.html
result.html
サービスの定義
インターフェイスでサービスを定義します。 今回は入力した項目が正常かどうかをチェックするサービスを定義してみます。
src/main/java/hello/service/GreetingService.java
package hello.service;
import hello.bean.GreetingBean;
public interface GreetingService {
boolean validate(GreetingBean bean);
}
サービスの実装
上で定義したサービスを実装します。 普通にimplements
をつけて実装する他に、@Component
アノテーションを付与します。
今回はidが0だったら入力エラーと判定するように作っています。
src/main/java/hello/service/impl/GreetingServiceImpl.java
package hello.service.impl;
import org.springframework.stereotype.Component;
import hello.bean.GreetingBean;
import hello.service.GreetingService;
@Component
public class GreetingServiceImpl implements GreetingService {
@Override
public boolean validate(GreetingBean bean) {
if (bean.getId() == 0) {
return false;
}
else {
return true;
}
}
}
サービスの呼び出し
コントローラから呼び出すため、コントローラにサービスを持たせます。
src/main/java/hello/controller/GreetingController.java
package hello.controller;
import hello.bean.GreetingBean;
import hello.service.GreetingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class GreetingController {
@Autowired
private GreetingService greetingService;
@RequestMapping(value="/greeting", method=RequestMethod.GET)
public String greetingForm(Model model) {
model.addAttribute("greeting", new GreetingBean());
return "greeting";
}
@RequestMapping(value="/greeting", method=RequestMethod.POST)
public String greetingSubmit(@ModelAttribute GreetingBean greeting, Model model) {
model.addAttribute("greeting", greeting);
// part4で追加
if (!greetingService.validate(greeting)) {
model.addAttribute("errmsg", "入力したIDが正しくありません");
}
return "result";
}
}
@Autowired
アノテーションを付与することで、Springが自動的にインターフェイスに対する実装をセット(DI)してくれます。 この書き方でも良いのですが、単体試験をする際に自分でDIしなくてはいけないため、ちょっと面倒です。 私はsetterを用意するようにします。
※ setterよりもコンストラクタのほうがオススメ。コンストラクタの引数が多いということは、そのクラスに役割を多く持たせすぎていると判断できるため。
private GreetingService greetingService;
@Autowired
public void setGreetingService(GreetingService greetingService) {
this.greetingService = greetingService;
}
@Autowired
がついているメソッドでDIをやってくれます。非常に便利です。
その他
ビュー
エラーメッセージを表示するように変更します。
src/main/resources/templates/result.html
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Greeting Started: Handling Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Result</h1>
<p th:text="'id: ' + ${greeting.id}" />
<p th:text="'content: ' + ${greeting.content}" />
<!-- エラーメッセージ -->
<p th:text="${errmsg}" />
<a th:href="@{/greeting}">Submit another message</a>
</body>
</html>
Bean
Greeting.java
をGreetingBean.java
に変更します。 パッケージも変更します。
src/main/java/hello/bean/GreetingBean.java
package hello.bean;
public class GreetingBean {
private long id;
private String content;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
実行
mvn clean package tomcat7:deploy
でTomcatにデプロイして動きを確認します。 idに0を入れてsubmitした場合にエラーメッセージが出れば、今回追加したサービスが動いていることになります。