サーブレット&JSPの基本|SpringにおけるJSPとThymeleaf

JSPで学んだ画面表示の考え方は、Springでもしっかり活きる。JSTLとThymeleafの共通点を押さえて、ビュー開発の選択肢を広げよう

Spring MVCでは、コントローラがリクエストを受け取り、サービスに処理を依頼し、その結果をビューに渡して画面を表示します。

このビューを作る技術には、いくつかの選択肢があります。

これまでServletとJSPの学習では、JSP、EL式、JSTLを使って画面を作成してきました。

Springでも、JSPをビューとして使うことができます。

そのため、これまで学習してきたJSPの知識は無駄になりません。

むしろ、Spring MVCの画面表示を理解するための大切な土台になります。

一方、実際のSpringを使った開発現場では、Thymeleafというテンプレートエンジンがよく使われます。

Thymeleafは、HTMLに近い形で画面を作成できるビュー技術です。

JSPやJSTLで学んだifによる条件分岐、forに相当する繰り返し、EL式に似た値の表示などの考え方を活かしながら、Springのビューを作成できます。

この記事では、Springにおけるビュー開発の基本として、JSPとThymeleafの関係を整理します。

また、これまで作成してきたEL式とJSTLを用いた「ひとこと広場」の画面表示を題材にして、JSPで書いた場合とThymeleafで書いた場合を比較します。

さらに、Springプロジェクトspring_studyでJSPをビューとして使うために必要な設定として、application.propertiesの編集、pom.xmlの編集、JSP配置用フォルダの作成についても確認します。

Springで使えるビュー技術

Spring MVCでは、ビューをさまざまな技術で作成できます。

ビューとは、利用者に表示する画面のことです。

ServletとJSPで学習してきたMVCモデルでは、JSPがビューを担当していました。

Spring MVCでも、JSPをビューとして使えます。

ただし、Springの現場ではThymeleafが使われることも多くあります。

代表的なビュー技術

ビュー技術特徴
JSPServletとJSPで学んだ知識を活かしやすい
JSTLJSP内で条件分岐や繰り返しをタグとして書ける
EL式スコープに保存された値を簡単に表示できる
ThymeleafHTMLに近い形でSpringの画面を作成できる

Springを学ぶときにJSPを使うと、これまでの知識とつなげて理解しやすくなります。

一方、ThymeleafはSpringとの相性がよく、Spring Bootを使った開発でもよく利用されます。

そのため、まずJSPで考え方を確認し、次にThymeleafではどのように書くのかを比べてみると理解しやすくなります。

JSPの知識はSpringでも活かせる

Springを学び始めると、JSPではなくThymeleafという言葉が出てくるため、これまで学んできたJSPの知識が使えなくなるのではないかと感じるかもしれません。

しかし、心配する必要はありません。

JSPで学んだビューの考え方は、Springでもしっかり役立ちます。

JSPで学んだこととSpringで活きること

JSPで学んだことSpringで活きる考え方
EL式でスコープの値を表示するコントローラから渡された値をビューに表示する
JSTLのc:ifで条件分岐する値があるときだけ画面に表示する
JSTLのc:forEachで繰り返す一覧データを1件ずつ表示する
c:outで安全に出力する利用者が入力した値を画面に安全に表示する
JSPをWEB-INF配下に置く直接アクセスではなく、コントローラ経由で表示する

Thymeleafでも、条件分岐や繰り返し、値の表示といった考え方は変わりません。

書き方は違いますが、画面表示で行うことはよく似ています。

そのため、JSPとJSTLを学んでおくと、Thymeleafへの移行もスムーズになります。

図1:JSPで学んだビューの考え方はThymeleafにもつながる

この図から分かること

JSPとThymeleafは書き方こそ違いますが、ビューとして行うことには多くの共通点があります。

JSPでは、EL式、c:if、c:forEach、c:outを使って、スコープの値を表示したり、条件によって表示を切り替えたり、一覧データを繰り返し表示したりします。

Thymeleafでも、th:if、th:each、[[${...}]]などを使って、同じような表示処理を行えます。

そのため、JSPで学んだ画面表示の考え方は、SpringでThymeleafを学ぶときにも役立ちます。

ひとこと広場の画面表示をJSPで考える

ここでは、これまで作成してきた「ひとこと広場」の画面表示を題材にします。

ひとこと広場では、投稿内容をmessageListという名前で画面に渡し、main.jspで一覧表示していました。

また、入力内容が空だった場合などには、errorMsgを表示することもありました。

JSPでは、次のような流れで画面を作ります。

JSPで行う表示処理

表示したい内容JSPで使うもの
エラーメッセージがあるときだけ表示するc:if
エラーメッセージを画面に出すc:out
投稿一覧を繰り返し表示するc:forEach
投稿者名を表示するc:out
投稿本文を表示するc:out

利用者が入力した投稿本文を表示するときは、c:outを使うと安全です。

c:outは、HTMLとして特別な意味を持つ文字をそのままHTMLとして実行させず、画面に文字として表示するために役立ちます。

ひとこと広場をJSTLで表示する例

ファイル名: main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ひとこと広場</title>
</head>
<body>
<h1>ひとこと広場</h1>

<c:if test="${not empty errorMsg}">
<p><c:out value="${errorMsg}" /></p>
</c:if>

<form action="Main" method="post">
<p>
投稿者名:
<input type="text" name="userName">
</p>
<p>
ひとこと:
<input type="text" name="text">
</p>
<input type="submit" value="投稿">
</form>

<h2>投稿一覧</h2>

<c:forEach var="message" items="${messageList}">
<p>
<c:out value="${message.userName}" />:
<c:out value="${message.text}" />
</p>
</c:forEach>

</body>
</html>

このmain.jspは、ひとこと広場の投稿フォームと投稿一覧を表示するJSPです。

taglibディレクティブでJSTLのCoreタグを使えるようにしています。

errorMsgが空でない場合だけ、c:ifの中にあるエラーメッセージを表示します。

投稿一覧は、messageListをc:forEachで1件ずつ取り出して表示しています。

varにmessageを指定しているため、繰り返しの中ではmessage.userNameやmessage.textで投稿者名と本文を取り出せます。

それぞれの値はc:outで出力しています。

ひとこと広場では、利用者が投稿本文を入力するため、画面に表示するときは安全な出力を意識することが大切です。

Thymeleafではどのように書くか

次に、同じひとこと広場の画面をThymeleafで考えてみます。

Thymeleafでは、HTMLのタグにth:ifやth:eachのような属性を追加して、条件分岐や繰り返しを表現します。

また、値を表示するときは[[${...}]]のような書き方を使えます。

JSTLとThymeleafの対応

やりたいことJSPとJSTLThymeleaf
条件によって表示するc:ifth:if
一覧を繰り返すc:forEachth:each
値を表示するc:out[[${...}]]
スコープの値を参照する${...}${...}

Thymeleafでも、${...}という式を使って値を参照します。

そのため、EL式に慣れている人であれば、Thymeleafの式も比較的理解しやすいです。

ひとこと広場をThymeleafで表示する例

ファイル名: main.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ひとこと広場</title>
</head>
<body>
<h1>ひとこと広場</h1>

<th:block th:if="${errorMsg}">
<p>[[${errorMsg}]]</p>
</th:block>

<form action="/Main" method="post">
<p>
投稿者名:
<input type="text" name="userName">
</p>
<p>
ひとこと:
<input type="text" name="text">
</p>
<input type="submit" value="投稿">
</form>

<h2>投稿一覧</h2>

<th:block th:each="message : ${messageList}">
<p>
[[${message.userName}]]:[[${message.text}]]
</p>
</th:block>

</body>
</html>

このmain.htmlは、先ほどのmain.jspと同じ内容をThymeleafで表現した例です。

htmlタグには、Thymeleafを使うためにxmlns:thを指定しています。

errorMsgがある場合だけ表示する部分では、th:ifを使っています。

投稿一覧を繰り返す部分では、th:eachを使っています。

th:each="message : ${messageList}"は、messageListから1件ずつ取り出し、その1件をmessageという名前で扱うという意味です。

値の表示には[[${message.userName}]]や[[${message.text}]]を使っています。

JSPではc:outを使っていた部分が、Thymeleafでは[[${...}]]に変わっています。

書き方は変わりますが、行っていることはよく似ています。

JSPとThymeleafの共通点

JSPとThymeleafには、共通している考え方がたくさんあります。

どちらも、コントローラから渡された値をビューで表示するために使います。

どちらも、条件分岐や繰り返しを使って、画面の表示内容を変えられます。

共通している考え方

共通点内容
コントローラから受け取った値を表示するerrorMsgやmessageListなどを画面に出す
条件分岐ができるエラーがあるときだけ表示する
繰り返しができる投稿一覧を1件ずつ表示する
式を使って値を参照する${message.text}のように値を取り出す
MVCのViewとして使う処理結果を利用者に見せる役割を持つ

このように見ると、JSPからThymeleafへ移るときに、まったく別の考え方を学び直すわけではないことが分かります。

JSPで、画面表示、スコープの値、条件分岐、繰り返しを学んでいれば、その考え方をThymeleafにも応用できます。

図2:ひとこと広場をJSPとThymeleafで表示する比較

この図から分かること

JSP版のmain.jspでは、c:if、c:forEach、c:outを使って、エラーメッセージや投稿一覧を表示します。

Thymeleaf版のmain.htmlでは、th:if、th:each、[[${...}]]を使って、同じようにエラーメッセージや投稿一覧を表示します。

使うタグや属性は違いますが、条件分岐、繰り返し、値の表示という基本的な考え方は共通しています。

そのため、JSPとJSTLを学んでいると、Thymeleafの学習にも入りやすくなります。

SpringプロジェクトでJSPを使うには設定が必要

SpringプロジェクトでJSPをビューとして使う場合は、いくつかの設定が必要です。

ServletとJSPの動的Webプロジェクトでは、WEB-INF/jspにJSPを配置してフォワードする流れを作っていました。

Springプロジェクトでも、同じようにWEB-INF/jspにJSPを置く構成にできます。

ただし、SpringにJSPファイルの場所と拡張子を知らせる設定が必要です。

JSPを使うために行う設定

手順内容
1application.propertiesを編集する
2pom.xmlを編集する
3JSPを配置するフォルダを作成する

この設定を行うことで、コントローラのハンドラメソッドがreturn "main"; のようにビュー名を返したとき、SpringがWEB-INF/jsp/main.jspを探してフォワードできるようになります。

application.propertiesを編集する

まず、src/main/resourcesの中にあるapplication.propertiesを開きます。

このファイルは、Spring Bootアプリケーションの設定を書くためのファイルです。

JSPをビューとして使う場合は、JSPファイルを探す場所と、ファイルの拡張子を設定します。

application.propertiesに追加する設定

ファイル名: application.properties

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

spring.mvc.view.prefixには、JSPファイルを探すフォルダを指定します。

ここでは、WEB-INF/jspを指定しています。

spring.mvc.view.suffixには、ビュー名の後ろに付ける拡張子を指定します。

ここでは、.jspを指定しています。

この設定により、コントローラでreturn "main"; と書いた場合、Springは/WEB-INF/jsp/main.jspをビューとして探します。

ビュー名とJSPファイルの対応

コントローラの戻り値実際に探されるJSP
return "main";/WEB-INF/jsp/main.jsp
return "login";/WEB-INF/jsp/login.jsp
return "result";/WEB-INF/jsp/result.jsp

このように、prefixとsuffixを設定しておくことで、コントローラではJSPファイルのフォルダ名や拡張子を毎回書かなくてよくなります。

pom.xmlを編集する

次に、spring_studyプロジェクト直下にあるpom.xmlを編集します。

pom.xmlは、Mavenプロジェクトで利用するライブラリや設定を管理するファイルです。

SpringプロジェクトでJSPを使う場合、JSPを実行するために必要なdependencyをdependenciesタグ内に追加します。

編集するときは、pom.xmlを右クリックし、次で開くから汎用コード・エディタを選択します。

開いたエディタで、dependenciesタグの中に、JSP用のdependencyを追加します。

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
   <groupId>jakarta.servlet.jsp.jstl</groupId>
    <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
</dependency>
<dependency>
   <groupId>org.glassfish.web</groupId>
    <artifactId>jakarta.servlet.jsp.jstl</artifactId>
</dependency>

pom.xml編集時の注意点

注意点内容
追加場所dependenciesタグの内側に追加する
タグの対応dependencyタグの開始と終了が正しく対応しているか確認する
保存追加後に上書き保存する
エラー確認pom.xmlに赤いエラー表示が出ていないか確認する

pom.xmlの記述を間違えると、プロジェクトが正しくビルドできなくなることがあります。

dependencyを追加したあとは、保存してエラーが出ていないか確認しましょう。

JSPを配置するフォルダを作成する

最後に、JSPファイルを配置するフォルダを作成します。

今回の構成では、フォワードされるJSPをsrc/main/webapp/WEB-INF/jspに配置します。

Springプロジェクトの作成方法によっては、src/main以下にwebappフォルダが自動で作成されていない場合があります。

その場合は、手動で作成します。

フォルダ作成の手順

手順操作
1srcフォルダ内のmainフォルダを右クリックする
2新規からフォルダーを選択する
3フォルダー名にwebappを入力して完了する
4作成したwebappフォルダを右クリックする
5新規からフォルダーを選択する
6フォルダー名にWEB-INFを入力して完了する
7作成したWEB-INFフォルダを右クリックする
8新規からフォルダーを選択する
9フォルダー名にjspを入力して完了する

大文字と小文字に注意して作成します。

WEB-INFは大文字で書きます。

jspは小文字で書きます。

JSP配置用フォルダの構成

src/main/webapp
         └─ WEB-INF
            └─ jsp
               └─ main.jsp

この構成にしておくと、application.propertiesの設定と対応します。

spring.mvc.view.prefixに/WEB-INF/jsp/を指定しているため、SpringはWEB-INF/jspフォルダの中からJSPファイルを探します。

直接リクエストされるJSPとフォワードされるJSP

SpringプロジェクトでJSPを使う場合も、JSPの置き場所を意識することが大切です。

これまでのServletとJSPの学習でも、直接リクエストされるJSPと、サーブレットからフォワードされるJSPを分けて考えてきました。

JSPの配置場所

JSPの種類配置場所
直接リクエストされるJSPsrc/main/webapp
フォワードされるJSPsrc/main/webapp/WEB-INF/jsp

WEB-INF配下のJSPは、ブラウザから直接アクセスできません。

そのため、コントローラを通して表示する画面に向いています。

たとえば、ひとこと広場のメイン画面であるmain.jspをWEB-INF/jspに配置し、コントローラがreturn "main"; を返すことで表示する流れにできます。

図3:SpringプロジェクトでJSPを使うための設定

この図から分かること

SpringプロジェクトでJSPをビューとして使うには、application.propertiesでJSPの場所と拡張子を設定します。

spring.mvc.view.prefixに/WEB-INF/jsp/を指定し、spring.mvc.view.suffixに.jspを指定します。

この設定により、コントローラがreturn "main"; を返したとき、Springは/WEB-INF/jsp/main.jspを探します。

また、JSPを実行するために必要なdependencyをpom.xmlに追加します。

JSPファイルは、src/main/webapp/WEB-INF/jspに配置します。

SpringでJSPを使うときの流れ

SpringでJSPをビューとして使う場合、コントローラ、ビュー名、JSPファイルの対応を意識します。

JSP表示までの流れ

順番処理
1ブラウザからリクエストが送信される
2DispatcherServletがリクエストを受け取る
3コントローラのハンドラメソッドが実行される
4コントローラが必要なデータを準備する
5コントローラがビュー名を返す
6Springがprefixとsuffixを使ってJSPの場所を決める
7JSPへフォワードする
8JSPがEL式やJSTLを使って画面を表示する

たとえば、ひとこと広場で投稿一覧を表示する場合、コントローラがmessageListを用意して、ビュー名mainを返します。

Springは設定に従ってWEB-INF/jsp/main.jspを探し、そのJSPへフォワードします。

main.jspでは、EL式とJSTLを使ってmessageListを表示します。

Thymeleafへ移行するときの見方

JSPからThymeleafへ移るときは、まず対応関係を押さえると分かりやすくなります。

JSTLのc:ifは、Thymeleafではth:ifに近い役割を持ちます。

JSTLのc:forEachは、Thymeleafではth:eachに近い役割を持ちます。

EL式で値を取り出す考え方は、Thymeleafでも${...}として使われます。

JSPからThymeleafへの考え方

JSPとJSTLThymeleaf考え方
c:ifth:if条件に合うときだけ表示する
c:forEachth:each一覧を繰り返して表示する
c:out[[${...}]]値を画面に表示する
${errorMsg}${errorMsg}errorMsgの値を参照する
${messageList}${messageList}投稿一覧を参照する

JSPとThymeleafは、記述の形は違います。

しかし、ビューがコントローラから受け取った値を表示するという役割は同じです。

JSPで画面表示の基本を理解していれば、Thymeleafの書き方も少しずつ覚えていけます。

Springのビュー開発で押さえたいこと

Springでは、ビューをJSPやThymeleafなどの技術で作成できます。

これまで学習してきたJSP、EL式、JSTLの知識は、Springでも活かせます。

実際の現場ではThymeleafが使われることも多くありますが、JSPで学んだ条件分岐、繰り返し、値の表示の考え方はThymeleafにもつながります。

ひとこと広場の例で見ると、JSPではc:if、c:forEach、c:outを使ってerrorMsgやmessageListを表示します。

Thymeleafでは、th:if、th:each、[[${...}]]を使って同じような表示を行います。

Springプロジェクトspring_studyでJSPを使う場合は、application.propertiesにprefixとsuffixを設定します。

また、pom.xmlにJSP実行に必要なdependencyを追加し、src/main/webapp/WEB-INF/jspフォルダを作成してJSPを配置します。

コントローラがreturn "main"; のようにビュー名を返すと、Springは設定に従って/WEB-INF/jsp/main.jspを探し、フォワードします。

JSPとThymeleafの違いを比べながら、Springにおけるビュー開発の基本を押さえていきましょう。