LoginSignup
5
4

More than 3 years have passed since last update.

ThymeleafからSpringのBeanを直接参照する例

Posted at

Thymeleaf-Springプラグインの恩恵により直参照する

Thymeleafのテンプレート内から、Springのコンテキスト管理にあるBeanを呼び出せます。

用途としては、以下のような生年月日の入力などのように定型のリストボックスやチェックボックスの値を、@Service@Repositoryなどで定義したクラスのpublicメソッドから値を取得して、それを表示できます。必要になるたびに@Controllerを経由することや、@ModelAttributeを定義する必要もありません。

image.png

Controllerの実装

Controllerにてリストボックスの内容を表示する際には、例えばこのようになるでしょう。

ListboxController.java
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/listbox")
public class ListboxController {
    @GetMapping
    public ModelAndView display(ModelAndView mnv) {

        mnv.addObject("listbox", createListbox());
        mnv.addObject("month", 8);
        mnv.setViewName("listbox");
        return mnv;
    }

    @PostMapping
    public ModelAndView selected(ModelAndView mnv, @RequestParam Integer month) {

        mnv.addObject("listbox", createListbox());
        mnv.addObject("month", month);
        mnv.setViewName("listbox");
        return mnv;
    }

    List<Integer> createListbox() {
        return IntStream.rangeClosed(1, 12).boxed().collect(Collectors.toList());
    }
}

装飾部分を一切抜いたHTMLテンプレートは、次のようになります

listbox.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
    <div>
        リストボックスの表示・送信
        <form th:action="@{/listbox}" method="post">
            <select name="month" class="form-control">
                <option th:each="value : ${listbox}" th:value="${value}" th:text="${value}" th:selected="${month == value}" />
            </select>
            <input type="submit"/>
        </form>
    </div>
</body>
</html>

この mnv.addObject("listbox", createListbox()); を必要なすべてのControllerに記載するのでも十分ですが、冒頭にも記載したSpringのBeanたちをThymeleafから直接呼び出すことで、実装の手間を省いてみます。

今回の例に挙げた、1~12の数値を格納したListを返すBeanを定義します。

ListboxRepository.java
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.springframework.stereotype.Repository;

@Repository("listbox")  // bean名:listboxでSpringのコンテナへ格納
public class ListboxRepository {
    public List<Integer> createListbox() {
        return IntStream.rangeClosed(1, 12).boxed().collect(Collectors.toList());
    }
}

続いて、Controllerの実装から先ほどのlistboxを消します。(わかりやすく、行コメントで記載しています)

ListboxController.java
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/listbox")
public class ListboxController {
    @GetMapping
    public ModelAndView display(ModelAndView mnv) {

        //mnv.addObject("listbox", createListbox());
        mnv.addObject("month", 8);
        mnv.setViewName("listbox");
        return mnv;
    }

    @PostMapping
    public ModelAndView selected(ModelAndView mnv, @RequestParam Integer month) {

        //mnv.addObject("listbox", createListbox());
        mnv.addObject("month", month);
        mnv.setViewName("listbox");
        return mnv;
    }

//  List<Integer> createListbox() {
//      return IntStream.rangeClosed(1, 12).boxed().collect(Collectors.toList());
//  }
}

HTMLテンプレートでは、Springのコンテナから参照するように記述を変えます。
@Repositoryで登録した listbox で参照できますから

listbox.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
    <div>
        リストボックスの表示・送信
        <form th:action="@{/listbox}" method="post">
            <select name="month" class="form-control">
                <option th:each="value : ${@listbox.createListbox()}" th:value="${value}" th:text="${value}" th:selected="${month == value}" />
            </select>
            <input type="submit"/>
        </form>
    </div>
</body>
</html>

のように、${@listbox.createListbox()} でメソッドを実行した結果が得られます。

応用例として

日付入力の年月日のような固定値だけでなく一定期間は値が固定であるような項目、例えばシステムやサービスで持っているがWebAPIで公開されていないような情報で、更新頻度の少ない一覧、例えば従業員一覧や施設一覧情報を表示したい場合などに使えるでしょう。

こうすることで、Controllerで行いたい処理とは別のスコープで持たせることができ、Controllerの責務と実装は軽くできます。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4