Как FreeMarker поможет быстро сделать HTML-отчет на базе шаблона (+ конвертация в PDF)
Apache FreeMarker это Java-библиотека (лицензия - Apache 2.0) для генерации различных текстовых форматов (HTML, e-mails, конфигурационные файлы, исходные коды, и т.д.) которая базируется на шаблонах и меняющихся входных данных.
Шаблоны пишутся на FreeMarker Template Language (FTL), который будет понятен не только программисту, но, например и верстальщику.
Моделью данных может выступать, к примеру HashMap с String, Number, POJO внутри или, например, при чуть больших усилиях JSON.
Фишка в том, что движок FreeMarker-a позволяет воспользоваться не только набором стандартных функций и конструкций (условия, циклы, работа с числами и строками), но и расширить шаблон вызовами своих функций (пример - конвертация числа в строку прописью, транслитерация строки и проч.).
Кроме того, есть code-completion в IDEA/Eclipse, что при наличии оных позволяет "быстрее" разрабатывать.

Итого, чтобы сгенерировать отчет, необходимо:
- Сконфигурировать движок:
// Укажем версию конфигурации
Configuration cfg = new Configuration(Configuration.VERSION_2_3_25);
// Где будут располагаться файлы с шаблонами
cfg.setDirectoryForTemplateLoading(new File("/where/you/store/templates"));
// Кодировка шаблонов
cfg.setDefaultEncoding("UTF-8");
// Как будут обрабатываться ошибки
// Используем TemplateExceptionHandler.HTML_DEBUG_HANDLER.
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
- Создать модель данных:
(root)
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"
Вот так:
// Это root-объект - HashMap, но мог быть и JavaBean.
Map<String, Object> root = new HashMap<>();
// Добавим "user" в "root"
root.put("user", "Big Joe");
// Создадим "latestProduct"
Product latest = new Product();
latest.setUrl("products/greenmouse.html");
latest.setName("green mouse");
// и добавим "latestProduct" в "root"
root.put("latestProduct", latest);
Собственно Java Bean (класс должен быть public и иметь соотв. getter-ы):
public class Product {
private String url;
private String name;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- Получить шаблон через экземпляр Configuration (файл test.ftlh должен быть создан и находиться в /where/you/store/templates, который мы указали на первом шаге):
Template temp = cfg.getTemplate("test.ftlh");
Пример самого файла:
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
- Свести шаблон и данные, выведем в stdout:
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
- В результате получаем:
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome John Doe!</h1>
<p>Our latest product:
<a href="products/greenmouse.html">green mouse</a>!
</body>
</html>
Дополнительно:
- Список встроенных функций
- Как написать свою функцию
- Как сконвертировать полученный, например, HTML в PDF при помощи flyingsaucer:
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
public static byte[] html2pdf(String html, String fontsPath) throws IOException,
DocumentException {
ITextRenderer renderer = new ITextRenderer();
loadFonts(renderer.getFontResolver(), fontsPath);
renderer.setDocumentFromString(html);
renderer.layout();
ByteArrayOutputStream os = new ByteArrayOutputStream();
renderer.createPDF(os);
return os.toByteArray();
}
Впервые опубликовано в ЖЖ.