Help us understand the problem. What is going on with this article?

SpringBoot + JPA + Thymeleafで簡単なCRUDを作る⑤〜テンプレートの共通化〜

More than 1 year has passed since last update.

内容

  • 前回の続き
  • SpringBootで簡単なCRUDアプリを作る
  • 今回はThymeleafの共通部分をくくりだすリファクタリングをする

現状の確認

  • ここまで以下の4つのhtmlファイルを作成している
src/main/resources/templates
└── players
    ├── edit.html
    ├── index.html
    ├── new.html
    └── show.html
  • 以下のように4つ全てのファイルでheadタグの内容はほとんど同じものになっている
    • 違うのはtitleだけ
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>XXXX - baseball</title>
    <link rel="stylesheet" href="/css/bootstrap.css" />
    <script src="/js/jquery.js"></script>
    <script src="/js/bootstrap.js"></script>
  </head>
  <body>
    <!-- ここはページによって違う -->
  </body>
</html>
  • もしも新しくCSSやJavaScriptの読み込みを追加したりmetaタグを追加することになった場合、全てのファイルに同じ修正を加える必要がありメンテナンス性が良くない
  • なので共通部分をくくりだしそれを全てのファイルから使うように修正する

手順

dependenciesの追加(SpringBoot2系の場合のみ)

  • mavenの人はpom.xml、gradleの人はbuild.gradleにライブラリのdependenciesを追加する
  • SpringBoot1系の場合はなくても動作する
pom.xml
<dependency>
  <groupId>nz.net.ultraq.thymeleaf</groupId>
  <artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
build.gradle
compile('nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect')

共通ファイルの作成

  • src/main/resources/templateslayout.htmlというファイルを作成し以下の内容を記述する
<!DOCTYPE html>
<!-- ① -->
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
  <head>
    <meta charset="utf-8" />
    <!-- ② -->
    <title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">baseball</title>
    <link rel="stylesheet" href="/css/bootstrap.css" />
    <script src="/js/jquery.js"></script>
    <script src="/js/bootstrap.js"></script>
  </head>
  <body>
    <!-- ③ -->
    <div layout:fragment="content"></div>
  </body>
</html>
  • ①:これまでのファイルとの違いは以下の記述が追加されている点である。
    • xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
    • この記述を追加することで共通ファイルとして扱うことができるようになる
  • ②:titleはページごとに変更したいためその対応を記述している
    • $DECORATOR_TITLEには各ページで定義したtitleが代入される
    • $CONTENT_TITLEには共通ファイル(このファイル)に定義したtitleが代入される
    • 今回の例の場合は以下のようなフォーマットでtitleが設定されることになる
    • 各ページのタイトル - baseball
  • ③:<div layout:fragment="content"></div>という目印をつけておくことで、各ページのコンテンツをこの部分と入れ替えることができる

共通ファイルの利用

  • まずはsrc/main/resources/templates/players/index.htmlを修正する
<!DOCTYPE html>
<!-- ① -->
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout">
  <head>
    <!-- ② -->
    <title>Listing Players</title>
  </head>
  <body>
    <!-- ③ -->
    <div class="container" layout:fragment="content">
      <h1>Listing Players</h1>
      <!-- 長いので省略 -->
    </div>
  </body>
</html>
  • ①:以下の2つの記述が追加されている
    • A: xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
    • B: layout:decorator="layout"
    • Aは共通ファイルと同様のもので、これを書くことで共通ファイルの利用ができるようになる
    • Bは利用する共通ファイルを指定している
      • =の右辺が共通ファイルの拡張子を除いたファイル名と一致している
      • 例えばもし共通ファイルがtemplate/sample/common.htmlにあったとすると、Bの記述は以下のようになる
        • layout:decorator="sample/common"
      • SpringBoot2系の人はこのままでも動くが公式のサンプルに従うと以下のよう書くと良い
        • layout:decorate="~{sample/common}"
  • ②:headタグの中身がtitleだけになっている
    • css等の読み込みは共通ファイルでやっているので全て削除している
    • titleは各ページ固有の内容も設定するようにしているのでここで渡している
      • この例では共通ファイルのtitleと組み合わさって以下のようなtitleになる
        • Listing Players - baseball
    • もしこのページのみでheadタグに記載したい内容がある場合は、ここに記載するとことで共通ファイルの内容に追加して定義することができる
  • ③:layout:fragment="content"とすることでこの記述以下のhtmlを、共通ファイルでlayout:fragment="content"と記述した部分と入れ替えることができる

他のファイルも同様の修正を加える

  • src/main/resources/templates/players/new.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout">
  <head>
    <title>New Player</title>
  </head>
  <body>
    <div class="container" layout:fragment="content">
      <!-- 長いので省略 -->
    </div>
  </body>
</html>
  • src/main/resources/templates/players/edit.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout">
  <head>
    <title>Editing Player</title>
  </head>
  <body>
    <div class="container" layout:fragment="content">
      <!-- 長いので省略 -->
    </div>
  </body>
</html>
  • src/main/resources/templates/players/show.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout">
  <head>
    <title>Show Player</title>
  </head>
  <body>
    <div class="container" layout:fragment="content">
      <!-- 長いので省略 -->
    </div>
  </body>
</html>

動作確認

  • 従来と同様の動作をすればOK
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away