これは何? †
Java側コード †
- TemplateEngine?
- Thymeleaf本体
- engine.process(template, ctx, writer)
- template : テンプレートファイル名
- ctx : 埋め込むデータ
- writer : 出力先
- TemplateResolver?
- TemplateEngine?に設定する
- tempalate をどこから取ってくるかを指定する
- Context
package com.example.thymelaefexam;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.IContext;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
@Slf4j
public class ThymeleafExam {
/**
* Template Engine.
* The cost of creation is very high. This is thread safe.
*/
private static TemplateEngine engine = null;
@Data
@AllArgsConstructor
private static class MsgLine {
int no;
boolean status;
String msg;
}
public static void main(String[] args) {
int no = 1;
List<MsgLine> msgList = new ArrayList<>();
msgList.add(new MsgLine(no++, true,"小麦粉をボールに入れる"));
msgList.add(new MsgLine(no++, true,"砂糖をボールに入れる"));
msgList.add(new MsgLine(no++, true,"牛乳をボールに入れる"));
msgList.add(new MsgLine(no++, false,"シナモンをボールに入れる→無かったので省略"));
msgList.add(new MsgLine(no++, true,"よく混ぜる"));
msgList.add(new MsgLine(no++, true,"フライパンで焼く"));
msgList.add(new MsgLine(no++, true,"皿に盛る"));
msgList.add(new MsgLine(no++, true,"はちみつをかける"));
Map<String, Object> contents = new HashMap<>();
contents.put("title", "Task list");
contents.put("lines", msgList);
try {
File outFile = File.createTempFile("report", ".html");
log.info("Start");
log.info("CREATE RPOERT {}", outFile.getAbsolutePath());
execute(new FileWriter(outFile, Charset.forName("UTF-8")), "template", contents);
log.info("End");
} catch (IOException ex) {
log.error("ERROR", ex);
}
}
public static void execute(final Writer outputWriter, final String template, final Map<String, Object> contents) {
// Initialize Template Engine
if (null == engine) {
engine = initializeTemplateEngine();
}
// Create the thymeleaf context
final IContext ctx = makeContext(contents);
// Create html
engine.process(template, ctx, new BufferedWriter(outputWriter));
}
private static TemplateEngine initializeTemplateEngine() {
// Create Engine
final TemplateEngine templateEngine = new TemplateEngine();
// Create Template Resolver (Search tempaltes under the classpath.)
final ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
// Options of resolver
resolver.setTemplateMode("HTML");
resolver.setPrefix("templates/");
resolver.setSuffix(".html");
resolver.setCharacterEncoding("UTF-8");
// Set the resolver on the template Engine.
templateEngine.setTemplateResolver(resolver);
return templateEngine;
}
/**
*
* @param contents
* @return
*/
private static IContext makeContext(final Map<String, Object> contents) {
final Context ctx = new Context();
ctx.setVariables(contents);
return ctx;
}
}
Template †
- Schemaに xmlsns="http://www.w3.org/1999/xhtml" の他に xmlns:th="http://www.thymeleaf.org" を設定する
- http://www.thymeleaf.org は Thymeleaf による XHTML の拡張属性 th:attr を許す。VSCode などで Schema エラーが起きないようにするために入れる
- th:tag
- Thymeleaf によって評価されると tag になる
- Contextに入れられた値を参照できる
- 簡単な演算を行うことができる
Template | 評価後のHTML |
<td th:class="${line.status ? 'ok' : 'ng'}"> | <td class="ok"> |
<pre th:text="${line.msg}"> | <pre>メッセージ</pre> |
- th:each でリストや配列を展開することができる
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="${src}">title</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
table, th {
border-collapse: collapse;
border:1px solid #333;
}
pre {
margin: 0;
}
.ok {
background-color: lightgreen;
}
.ng {
color: white;
background-color: pink;
}
</style>
</head>
<body>
<h1 th:text="${src}"></h1>
<table border="1" style="width:100%">
<thead>
<tr>
<th style="width:100px">No</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr th:each="line : ${lines}">
<td th:text="${line.no}"></td>
<td th:class="${line.status ? 'ok' : 'ng'}"><pre th:text="${line.msg}"></pre></td>
</tr>
</tbody>
</table>
</body>
</html>
出力結果 †
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
table, th {
border-collapse: collapse;
border:1px solid #333;
}
pre {
margin: 0;
}
.ok {
background-color: lightgreen;
}
.ng {
color: white;
background-color: pink;
}
</style>
</head>
<body>
<h1></h1>
<table border="1" style="width:100%">
<thead>
<tr>
<th style="width:100px">No</th>
<th>Message</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td class="ok"><pre>小麦粉をボールに入れる</pre></td>
</tr>
<tr>
<td>2</td>
<td class="ok"><pre>砂糖をボールに入れる</pre></td>
</tr>
<tr>
<td>3</td>
<td class="ok"><pre>牛乳をボールに入れる</pre></td>
</tr>
<tr>
<td>4</td>
<td class="ng"><pre>シナモンをボールに入れる→無かったので省略</pre></td>
</tr>
<tr>
<td>5</td>
<td class="ok"><pre>よく混ぜる</pre></td>
</tr>
<tr>
<td>6</td>
<td class="ok"><pre>フライパンで焼く</pre></td>
</tr>
<tr>
<td>7</td>
<td class="ok"><pre>皿に盛る</pre></td>
</tr>
<tr>
<td>8</td>
<td class="ok"><pre>はちみつをかける</pre></td>
</tr>
</tbody>
</table>
</body>
</html>
Java