
サーブレット&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が使われることも多くあります。
代表的なビュー技術
| ビュー技術 | 特徴 |
|---|---|
| JSP | ServletとJSPで学んだ知識を活かしやすい |
| JSTL | JSP内で条件分岐や繰り返しをタグとして書ける |
| EL式 | スコープに保存された値を簡単に表示できる |
| Thymeleaf | HTMLに近い形で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とJSTL | Thymeleaf |
|---|---|---|
| 条件によって表示する | c:if | th:if |
| 一覧を繰り返す | c:forEach | th: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を使うために行う設定
| 手順 | 内容 |
|---|---|
| 1 | application.propertiesを編集する |
| 2 | pom.xmlを編集する |
| 3 | JSPを配置するフォルダを作成する |
この設定を行うことで、コントローラのハンドラメソッドが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フォルダが自動で作成されていない場合があります。
その場合は、手動で作成します。
フォルダ作成の手順
| 手順 | 操作 |
|---|---|
| 1 | srcフォルダ内の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の種類 | 配置場所 |
|---|---|
| 直接リクエストされるJSP | src/main/webapp |
| フォワードされるJSP | src/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 | ブラウザからリクエストが送信される |
| 2 | DispatcherServletがリクエストを受け取る |
| 3 | コントローラのハンドラメソッドが実行される |
| 4 | コントローラが必要なデータを準備する |
| 5 | コントローラがビュー名を返す |
| 6 | Springがprefixとsuffixを使ってJSPの場所を決める |
| 7 | JSPへフォワードする |
| 8 | JSPが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とJSTL | Thymeleaf | 考え方 |
|---|---|---|
| c:if | th:if | 条件に合うときだけ表示する |
| c:forEach | th: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におけるビュー開発の基本を押さえていきましょう。
