tamuraです。
今回はDI(Dependency Injection)を使っていきます。


目標

  • サービスを定義する
  • サービスの実装を作る

part3のソースをベースにしています。

構成

このようなディレクトリ構成にします。

src/
  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を用意するようにします。

    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.javaGreetingBean.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した場合にエラーメッセージが出れば、今回追加したサービスが動いていることになります。