JavaEEでは、JSF(JavaServer Faces)というJavaベースのWebアプリケーションフレームワークを用いて画面表示を行うことが多いが、JSFの代わりにThymeleafというテンプレートエンジンを用いることもできる。
今回は、JavaEEのプロジェクトを作成し、Thymeleafによる画面表示を行ってみたので、その手順やサンプルプログラムを共有する。
前提条件
下記記事の環境構築が完了していること。
やってみたこと
動的Webプロジェクトの作成
JavaEEのプロジェクトの作成は、動的Webプロジェクトを作成後、必要なライブラリを追加することによって行う。その手順は以下の通り。
1) パッケージ・エクスプローラー上で右クリックし、「新規」メニューから「その他」を選択する。

2) Webメニューの「動的Webプロジェクト」を選択し、「次へ」ボタンを押下する。

3) プロジェクト名を入力し、ターゲット・ランタイムにGlassFishを選択した状態で、「次へ」ボタンを押下する。

5) 「web.xml デプロイメント記述子の生成」にチェックを入れ、「完了」ボタンを押下する。

JavaEEのプロジェクトで必要なライブラリの配置
作成した動的Webプロジェクトを、JavaEEプロジェクトとして動作させるには、以下のjarファイルが必要である。
- disruptor-3.3.2.jar
- javax.mvc-api-1.0-edr2.jar
- log4j-api-2.4.jar
- log4j-core-2.4.jar
- log4j-slf4j-impl-2.4.jar
- ognl-3.1.jar
- ozark-1.0.0-m02.jar
- ozark-thymeleaf-1.0.0-m02.jar
- slf4j-api-1.7.12.jar
- thymeleaf-2.1.4.RELEASE.jar
- unbescape-1.1.0.RELEASE.jar
例えば、「distruptor-3.3.2.jar」は、以下のURLの「jar」リンクを押下することで取得できる。
https://mvnrepository.com/artifact/com.lmax/disruptor/3.3.2

また、取得したライブラリは全て、以下のように、WebContent/WEB-INF/lib下にコピーして貼り付ける。

サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。

なお、上記の赤枠は、今回追加・変更したプログラムである。
アプリケーション定義クラスの内容は以下の通りで、アプリケーションのルートパスを指定している。
package demo;
import javax.ws.rs.ApplicationPath;
/**
* JAX-RSアプリケーションのルートパスを@ApplicationPathアノテーションで
* 指定するためのクラス
* なお、JAX-RSとは、JavaEEでREST(HTTPをベースとしたアーキテクチャスタイル)に
* 準拠したWebサービスを作るための機能のことをいう
*/
@ApplicationPath("/app")
public class DemoApplication extends javax.ws.rs.core.Application {
}また、コントローラクラスの内容は以下の通りで、indexメソッドでメッセージを設定し、初期表示画面に遷移するようになっている。
package demo;
import javax.inject.Inject;
import javax.mvc.Models;
import javax.mvc.annotation.Controller;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* コントローラクラス
*/
@Path("/demo")
@Controller
public class DemoController {
/**
* Modelオブジェクト
*/
@Inject
Models models;
/**
* メッセージを設定し、初期表示画面に遷移する
*
* @return 初期表示画面
*/
@GET
@Path("/index")
@Produces(MediaType.TEXT_HTML)
public String index() {
models.put("message", "これはテストです");
return "index";
}
}さらに、Thymeleafをテンプレートエンジンに設定するクラスの内容は以下の通り。
package demo;
import java.io.IOException;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.mvc.engine.ViewEngineContext;
import javax.mvc.engine.ViewEngineException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.glassfish.ozark.engine.ViewEngineBase;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
/**
* Thymeleafをテンプレートエンジンに利用するためのクラス
*/
@ApplicationScoped
public class ThymeleafViewEngine extends ViewEngineBase {
/**
* サーブレットコンテキスト
*/
@Inject
private ServletContext servletContext;
/**
* テンプレートエンジン
*/
private TemplateEngine engine;
/**
* 指定したビュー名をサポートしているか判定
* @param view ビュー名
*/
public boolean supports(String view) {
return !view.contains(".");
}
/**
* オブジェクト生成後に行う処理
*/
@PostConstruct
public void postConstruct() {
// ViewにThymeleafを使用することを指定する
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setSuffix(".html"); // Viewファイルの拡張子
resolver.setPrefix("/WEB-INF/templates/"); // Viewファイルの配置場所
resolver.setTemplateMode("HTML5"); // Viewファイルのモード
resolver.setCacheable(false); // Viewファイルをキャッシュするか
resolver.setCharacterEncoding("UTF-8"); // Viewファイルの文字コード
// (これを指定しないと日本語が文字化けする)
// Viewのテンプレートエンジンに先ほどの設定内容を反映する
engine = new TemplateEngine();
engine.setTemplateResolver(resolver);
}
/**
* 指定したビュー名に対応する画面を表示
* @param ViewEngineContext ビューエンジンのコンテキスト
*/
public void processView(ViewEngineContext context) throws ViewEngineException {
try {
HttpServletRequest request = context.getRequest();
HttpServletResponse response = context.getResponse();
WebContext ctx
= new WebContext(request, response, servletContext, request.getLocale());
ctx.setVariables(context.getModels());
request.setAttribute("view", context.getView());
// 指定したビュー(HTMLファイル)名に対応するHTMLを解析し画面に表示する
engine.process(context.getView(), ctx, response.getWriter());
} catch (IOException e) {
throw new ViewEngineException(e);
}
}
}また、初期表示画面の内容は以下の通りで、Spring Bootのときと同じような内容を記載している。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>初期表示画面</title>
</head>
<body>
初期表示画面に遷移しました。<br/><br/>
設定されたメッセージ: <span th:text="${message}">メッセージ</span>
</body>
</html>さらに、beans.xmlの内容は以下の通りで、「bean-discovery-mode=”all”」の設定を追加している。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> <!-- bean-discovery-mode="all"で、全てのクラスをCDIでインジェクションさせる対象としている --> <!-- なお、CDIとは、Java EEでDI(依存性の注入)やインスタンスのスコープの管理を行う機能のことをいう --> </beans>
その他、動的Webプロジェクトを作成時と同じ内容であるが、glassfish-web.xml、web.xmlの内容はそれぞれ以下の通り。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
<context-root>/demo</context-root>
</glassfish-web-app><?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID"
version="3.1">
<!-- Webアプリケーションの表示名 -->
<display-name>demo</display-name>
<!-- URLがスラッシュ(/)で終わっていた場合に表示させるファイル名 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
サンプルプログラムの実行
サンプルプログラムの実行結果は、以下の通り。
1) demoプロジェクトをサーバーに追加するために、サーバービューのGlassFishサーバーを選択し右クリックし、「追加および除去」を選択する。

2) demoプロジェクトを選択した状態で「追加」ボタンを押下する。

3) 「構成済み」欄にdemoプロジェクトが移動するので、「完了」ボタンを押下する。

4) 以下のように、GlassFishサーバーにdemoプロジェクトが追加されていることが確認できる。

5) GlassFishサーバーを選択し右クリックし、「開始」を選択する。

6) GlassFishサーバーが起動すると、以下のように、サーバーのステータスが「始動済み、同期済み」に変更される。

7) Webブラウザ上で「http:// (ホスト名):(ポート番号)/(Webアプリケーションの表示名)/(アプリケーションのルートパス)/(コントローラクラスパス)/(コントローラメソッドパス)」とアクセスすると、下記画面(index.html)が表示されることが確認できる。

なお、(Webアプリケーションの表示名)はweb.xmlで、(アプリケーションのルートパス)はDemoApplication.javaで、それぞれ指定している。
要点まとめ
- JavaEEのプロジェクトの作成は、動的Webプロジェクトを作成後、必要なライブラリを追加することによって行う。
- アプリケーションのルートパスは、「javax.ws.rs.core.Application」クラスのサブクラスで定義する。
- コントローラクラスで、画面遷移に必要なパス指定等を行う。
- Thymeleafをテンプレートエンジンに利用する定義は、ViewEngineBaseクラスのサブクラスで行う。
- 全てのクラスをCDIでインジェクションさせる対象とするには、beans.xmlで「bean-discovery-mode=”all”」を指定する。







