はじめに

こんにちは。2017年度新卒、キャスレーコンサルティング SD(システムデザイン)部の石原です。
今回、初めてブログを書かせていただきます。

今回は、「Spring Boot」をテーマに、「Thymeleaf」と「JSP」を使用した簡単なアプリケーションを作成し、
条件分岐タグの「if」と「switch」の実装方法を、確認したいと思います。
その上で、私が感じたそれぞれの特徴を、Goodポイント・Badポイントという形でまとめてみます。

現在私は、Spring Bootを用いて業務を行っていますが、
Spring Bootについては、名前を聞いたことがある程度で、知識が全くありませんでした。
そこで、実際に自分で簡単なプロジェクトを作成することで、理解を更に深めたいと思い、このブログを執筆いたしました。

今回は開発環境として、eclipseをベースにSpring Frameworkを利用するための各種プラグインを追加した
Spring専用の開発環境であるSTS(Spring Tool Suite)を使用します。

Helloプロジェクト

作成するアプリケーションの機能

  • メッセージとクリックボタンを表示
  • ボタンをクリックするとメッセージが表示される

プロジェクト作成手順

「ファイル」→「新規」→「Spring Starter Project」を選択する。

プロジェクト作成1

依存関係には、「Web」と「Thymeleaf」を選択する。

プロジェクト作成2
プロジェクト作成3

つまずきポイント

Thymeleafを使用した画面を表示する場合に、依存関係で「Thymeleaf」を選択していない
画面のアクセス時に、
404エラーが発生してしまうのでご注意下さい。

以上でプロジェクトの作成が完了したので、続いてControllerとHTMLを作成します。

Controller

  • 「ファイル」→「新規」→「クラス」をクリックし作成する。
  • 配置場所は、プロジェクトを作成した際に出来る「HelloApprication.java」と同じ場所に配置する。

※(プロジェクト名+Application.java)
helloプロジェクト

package com.example.demo;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@EnableAutoConfiguration
public class HelloController {

	    @RequestMapping(value="/", method=RequestMethod.GET)
	    public String hello(Model model) {
	        model.addAttribute("click", false);
	        model.addAttribute("message", "please click!");
	        return "hello";
	    }

	    @RequestMapping(value="/", method=RequestMethod.POST)
	    public String click(Model model) {
	        model.addAttribute("click", true);
	        model.addAttribute("afterClickMsg", "It was clicked.");
	        return "hello";
	    }

}

今回は、クリックされたかどうかでボタンを表示するかしないかの判断をします。

それではまず、初期画面遷移時のhelloメソッドを見ていきましょう。

■初期表示の際に実行される処理

model.addAttribute("click", false);

※falseを設定することで、クリックされていない状態になります。

次に、ボタンクリック時のclickメソッドを見ていきましょう。

■ボタンクリック時に実行される処理

model.addAttribute("click", true);

※trueを設定することで、クリックされた状態になります。

ちなみに、messageとafterClickMsgの値は、それぞれ画面に表示するメッセージです。

最後に、returnで画面のファイル名を返します。
今回は、”hello.html”というファイル名なので、”hello”と返しますが、
例えば、ファイル名を”goodBye.html”にした場合は、returnで”goodBye”を返します。

注意すべきポイント

  • @Controller

Controllerクラスに、「@Controller」アノテーションを付与した場合は、
returnで画面のファイル名を返すと、src/main/resource/templates配下の
「ファイル名.html」を読み込んでくれます。

  • @RestController

Controllerクラスに、「@RestController」アノテーションを付与すると、
returnで指定した文字列が、画面に表示されてしまうので注意が必要です。

以上でControllerの作成が完了したため、続いて表示を行うテンプレートを作成します。
テンプレートは、Thymeleaf・JSPの両方を作成してみました。

Thymeleaf

  • 「ファイル」→「新規」→「その他」→「web」→「HTMLファイル」をクリックし作成する。
  • 配置場所は、src/main/resource/templates配下に配置する。

HelloHTML

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hello Thymeleaf</title>
</head>
<body>
	<div th:unless="${click}">
    	<p th:text="${message}"></p>
			<form method="post" action="/">
				<input type="submit" value="Click" />
			</form>
	</div>
    <div th:if="${click}">
    	<p th:text="${afterClickMsg}"></p>
    	<input type="submit" value="Click" th:disabled="${click == true}"/>
    </div>
</body>
</html>

Thymeleafで「if」タグを使用したい場合は、上記のように th:if=”${click}” と記述します。

“${click}”の値に応じて、以下のメッセージを表示する事ができます。

<p th:text="${afterClickMsg}"></p>

※{click}の値がtrue以外に、”on”、”yes”などの文字列、0以外の文字列、0以外の数値も同様の判定となります。

一方、th:unless=”${click}”というタグも存在します。

“${click}”の値に応じて、以下のメッセージを表示する事ができます。

<p th:text="${message}">

上記のように記述した場合、${click}の値が

※${click}の値がfalse以外に、”off”、”no”などの文字列、文字列の0、数値の0も同様の判定となります。

Controllerで初期表示の際は、”click”にfalse、ボタンがクリックされたら、”click”にtrueをセットしているので
“click”の値によって表示、非表示を判断させることが出来ます。

JSP

  • 「ファイル」→「新規」→「その他」→「web」→「JSPファイル」をクリックし作成する。
  • 配置場所は、src/main配下にwebapp/WEB-INF/viewsを作成し、配置する。

JSPキャプチャ

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
<%@ page session="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
<%@ page session="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hello JSP</title>
</head>
<body>
	<div>
        <c:if test="${click == false}" >
        	<c:out value="${message}" />
        	<form method="post" action="/">
				<input type="submit" value="Click" />
			</form>
        </c:if>
    </div>
	<div>
        <c:if test="${click == true}" >
        	<c:out value="${afterClickMsg}" />
        	<div>
    	    	<input type="submit" value="Click" disabled="disabled"/>
        	</div>
        </c:if>
	</div>
</body>
</html>

今回は、JSTL(JSP Standard Tag Library)を用いたので、変数を埋め込むことが可能で、
Thymeleafと比べても、構造に大きな違いはありません。

書き方としては、
c:if test=”${click == true}”のように、test属性に条件を記述します。

c:if=”${click == true}”と書きたくなりますが、条件はtest属性に記述するので注意が必要です。

つまずきポイント

JSPを用いる際は、設定の面で注意すべき部分があります。
(私自身、JSPを読み込ませるようにする設定に、時間を割いてしまいました。)

Thymeleafであれば、プロジェクト作成時に
Thymeleafとの依存関係を選択するだけで、特別な設定は必要ありません。
※自動で、pom.xml等の設定を行ってくれます。

ところが、画面にJSPを使用する場合、以下の設定が必要です。

  • pom.xml
  • application.propaties

まず、pom.xmlの

<dependencies>

の部分に

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>

 

<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

を追記します。
(私は、今回JSTLのタグを使用したかったので、JSTLも設定しました。)

そしてapplication.propatiesには

spring.mvc.view.prefix: /WEB-INF/views/
spring.mvc.view.suffix: .jsp

を記述します。

注意すべきポイント

そして、最後に忘れてはいけないのが、プロジェクトの更新です。

  • Maven⇒プロジェクトの更新
  • 実行⇒Maven Install

画面を確認する

Mavenから、プロジェクトの更新とMaven Installまで完了したら、
実行⇒Spring Boot Appで起動し、ブラウザでlocalhost:8080に接続すれば、画面が表示されます。

Thymeleaf_if文

ボタンをクリックすると、ifタグの動作により、ボタンがグレーアウトになります。

Thmeleaf_if文_クリック後

さて、「if」について理解が深まったところで、
複数の場合分けが出来る、「switch」についても簡単な画面を、作成してみました。

HelloSwitchプロジェクト

作成するアプリケーションの機能

  • メッセージとラジオボタン(dog,cat,rabbit)、クリックボタンを表示
  • ラジオボタンのいずれかを選択し、クリックボタンを押下すると、選択した動物の鳴き声を表示

プロジェクト、各ファイルは「Helloプロジェクト」と同様の手順で、作成します。

Controller

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class HelloController {

	   @RequestMapping(value="/", method=RequestMethod.GET)
	    public String hello(Model model) {
	        model.addAttribute("click", false);
	        model.addAttribute("message", "please click!");
	        return "hello";
	    }

	    @RequestMapping(value="/", method=RequestMethod.POST)
	    public String click(@RequestParam("animal")String animal, Model model) {
	        model.addAttribute("click", true);

	        if("dog".equals(animal)){
	    		model.addAttribute("chosenAnimal", 1);
	    	}else if("cat".equals(animal)){
	    		model.addAttribute("chosenAnimal", 2);
	    	}else if("rabbit".equals(animal)){
	    		model.addAttribute("chosenAnimal", 3);
	    	}

	        return "hello";
	    }

}

helloメソッドは、先程のHelloプロジェクトと同じものを使用し、clickメソッドで場合分けを行います。
ラジオボタンで、dogが選択された場合は1、catの場合は2、rabbitの場合は3を、chosenAnimalにセットします。

Thymeleaf

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hello Thymeleaf</title>
</head>
<body>
	<div th:unless="${click}">
    	<p th:text="${message}">please wait...</p>
			<form method="post" action="/">
				<input type="radio" name="animal" value="dog"/>dog
				<input type="radio" name="animal" value="cat"/>cat
				<input type="radio" name="animal" value="rabbit"/>rabbit
				<input type="submit" value="Click" />
			</form>
	</div>
	<div th:if="${click}" th:switch="${chosenAnimal}">
			<p th:case ="1">わん</p>
			<p th:case ="2">にゃん</p>
			<p th:case ="3">...?</p>
	</div>
</body>
</html>

Thymeleafのswitch文は、Javaのswitch文とほぼ同じと言っても良いでしょう。

<div th:switch="${chosenAnimal}">
    <p th:case =="1">わん</p>
    <p th:case =="2">にゃん</p>
    <p th:case =="3">...?</p>
</div>

${chosenAnimal}の値が
1なら”わん” が
2なら”にゃん”が
3なら”…?”が表示されます。

${chosenAnimal}にはControllerで
場合分けをして数値をセットしているので、セットされている値で表示を切り替えることが出来ます。

JSP

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
<%@ page session="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hello JSP</title>
</head>
<body>
	<div>
        <c:if test="${click == false}" >
        	<c:out value="${message}" />
        	<form method="post" action="/">
				<input type="radio" name="animal" value="dog"/>dog<br>
				<input type="radio" name="animal" value="cat"/>cat<br>
				<input type="radio" name="animal" value="rabbit"/>rabbit<br>
				<input type="submit" value="Click" />
			</form>
        </c:if>
    </div>
	<div>
        <c:if test="${click == true}" >
        	<c:choose>
				<c:when test="${chosenAnimal == 1}">わん</c:when>
				<c:when test="${chosenAnimal == 2}">にゃん</c:when>
				<c:when test="${chosenAnimal == 3}">...?</c:when>
			</c:choose>
        </c:if>
	</div>
</body>
</html>

JSTLのswitch文は、Javaのswitch文と少々異なり、

<c:choose>
    <c:when test="${chosenAnimal} = 1">わん</c:when>
    <c:when test="${chosenAnimal} = 2">にゃん</c:when>
    <c:when test="${chosenAnimal} = 3">...?</c:when>
</c:choose>

上記のように記述します。

c:chooseタグは、switch文であることを見分けるためと表現すると、少し分かりやすくなると思います。

Thymeleafのように、swicthの部分に条件を書くのではなく、

<switch文を使いますよ宣言タグ>
    <条件>テキストなど</条件>
    <条件>テキストなど</条件>
    <条件>テキストなど</条件>
</switch文を終わりますよ宣言タグ>

といった考え方で、記述してあげると分かりやすいと思います。

つまずきポイント

記述に問題はなさそうだが、画面にアクセスしてみると500エラーとなる
という現象が起こった場合は、タグの後ろに全角スペースが含まれている可能性を考えてみてください。
※コピー&ペーストなどでテンプレートを作成した際などは、特に注意してください。

画面を確認する

先程のHelloプロジェクト同様、Mavenからプロジェクトの更新とMaven Installを実行し、
Spring Bootを起動した上で、ブラウザでlocalhost:8080にアクセスして確認します。

Thymeleaf_swicth文

dogを選択してクリックすると、switch(choose)タグの動作により”わん”と画面に表示されます。

Thymeleaf_swicth文_クリック後

Thymeleafの良いところ

以上、「if」と「swicth」を用いたプロジェクトを、実際に1から作成することで、
それぞれの特徴を知る、良い機会になりました。

では、それぞれどのような特徴があるのでしょうか。
実装してみて、私が感じたことを以下にまとめます。

Good Bad
Thymeleaf 表示に影響を与えない 特になし
画面側は変数を定義するのみで、Javaのコードを
意識しなくて良い
HTMLベースで作られているので、ソースが読みやすい
1つのdivタグに属性を重ねて記述できる
= 記述量が減る
JSP Javaのコードの埋め込みが可能 HTMLとJavaのコードが混ざり、
ソースが読みづらくなる
タグライブラリを使用可能

JSPには、Javaのコードを埋め込めるので、便利だと思っていたのですが、
逆にこれがデザインと混在してしまい、分業がし辛いというデメリットにもなるようです。

このような特徴から考えてみると、Thymeleafは基本的に「th:○○」で書くということを押さえておけば
HTMLに追記する形で利用出来るため、学習コストをあまりかけず、すぐ使えます。

表示に影響を与えない

また、「th:」で書かれた独自属性の値が、タグの値に置き換えられてレンダリングされますが、
レンダリングがされなければ、表示に影響を与えないという特徴もあります。

つまり、

<p th:text="${message}">こんにちは</p>

という記述で考えると、
この記述のあるHTMLが、直接参照された場合には”${message}”には値がないので
「こんにちは」が出力されるだけで、悪影響を及ぼすことがありません。

一方、JSPの場合、ソースコードが表示されてしまうため、直接参照することが出来ません。

条件式も表現できる

また、Tymeleafには高度な値の組み込みを行うための仕組みとして、
プログラミングの構文に相当する機能が、備わっています。

今回取り上げた「if」「switch」に加え、
Javaでいう三項演算子の役割をする、「条件式」が挙げられます。

“${—条件式—}? ‘A’ : ‘B'”

上記のように記述することで、条件式がtrueならAが、条件式がfalseならBが評価されます。

繰り返しも出来る

さらに繰り返しも、実現可能です。

<tr th:each="user : ${userList}">
    <td th:text="${user.id}"></td>
    <td th:text="${user.name}"></td>
    <td th:text="${user.age}"></td>
</tr>

上記のように、記述します。

Javaでいう拡張for文を、イメージすると分かりやすいです。
userが変数、userListがコレクションで、userListの値を一つずつ取り出してuserに代入するので
変数.フィールドの形で値を表示させることが出来ます。

ThymeleafとJSP

これらはすべて、「th:」つまりタグの話です。
JSPで実現しようとした場合、JSPにJavaを埋め込む形、つまり

JSP
となります。

一方、ThymeleafはHTMLタグに記載される属性なので

Thymeleaf属性

と考えられます。
こういった点からも、よりHTMLに近い形、影響を及ぼさないと言われるのだと思います。

おわりに

以上の観点から考えると、どちらを使うべきか?使いたいか?と聞かれたら
私個人としては、Thymeleafを使用したいと思います。

ブログの内容は以上となりますが、
今回の執筆にあたり、プロジェクトの作成から自分で行うことでThymeleaf、JSPの書き方は勿論、
小さなプロジェクトでも自分で作ってみる、動かしてみる事が身に付ける近道であることを実感しました。

新しい事を勉強したらとにかくやってみる、
そして自分の知っているものと比較してみる、小さなことから確実に。が大切ですね。

思ったよりもThymeleafとJSPの実装に時間がかかり、
おまけで実装してみようと思っていたJSFまで手が回らなかったので
何かの機会に3つの比較が出来たら良いなと思います。

最後までご覧頂き、ありがとうございました。