Thymeleaf – Eine Template-Engine Für Entwickler Und Designer Gerrit Meier
Total Page:16
File Type:pdf, Size:1020Kb
02-2017 | Sommer | www. ijug.eu aktuell JavaPraxis. Wissen. Networking. Das Magazin für Entwickler Aus der Community — für die Community aktuell Java ISSN 2191-6977 Benelux: EUR 5,80 CH: 9,80 CHF 9,80 CH: A: 5,60 EUR 5,60 A: D: 4,90 EUR 4,90 D: Java im Mittelpunkt 02 Big Data Microservices Achtung, Audit 304903 Predictive Analytics Lagom, das neue Nutzung und Vertei- mit Apache Spark Framework lung von Java SE iJUG 191978 Verbund 4 Template-Engine Thymeleaf – eine Template-Engine für Entwickler und Designer Gerrit Meier In den letzten Jahren wurde mit Single Page Applications auf JavaScript-Basis immer mehr der Schritt weg vom serverseitigen Rendering gemacht. Auch die Aussage von Oracle im Rahmen der JavaOne, dass die meisten Anwendungen in der Cloud gänzlich ohne Oberfläche auskommen werden, gibt diesem Ansatz wenig Rückenwind. Warum aber erfreut sich, ganz gegen diesen Trend, die Template-Engine Thymeleaf immer weiter steigender Nutzerzahlen? Der Artikel zeigt, was Thymeleaf anders macht und warum es gerade bei neuen Projekten eine interessante Alternative sein kann. Bei der Entscheidung, ob eine Web-Anwen- allem durch eine übersichtliche, aber den- hen ist (siehe Abbildung 1). Im Vergleich dazu dung server- oder clientseitig gerendert wer- noch nicht einschränkend wirkende Syntax die statisch geöffnete JSP-Quelldatei (siehe den sollte, gibt es viele möglichen Faktoren, auszeichnet, existiert seit dem Jahr 2011. Abbildung 2). die man berücksichtigen und bewerten muss. Dazu gibt es eine hervorragende Integrati- Wer den Sourcecode beider Template-En- Dabei sollte, wie immer, das grundlegende on in das Spring-Ökosystem, unter anderem gines genauerer betrachtet, erkennt schnell, (Kunden-)Problem und dessen Lösung die durch einen Spring Boot Starter [2]. Auf die- dass Thymeleaf im Gegensatz zu JSP keine Hauptrolle spielen. Ist einmal die Entschei- sen Weg lassen sich sehr schnell Anwen- Custom Tags für die Logik verwendet, son- dung getroffen, sich nicht auf JavaScript- dungen unter Verwendung von Thymeleaf- dern mit Pseudo-Attributen arbeitet. Dieser Frameworks wie ReactJS oder Angular zu Templates erstellen und die ersten Schritte Ansatz, auch als „Natural Templating“ be- verlassen, sondern die HTML-Repräsentati- mit der Engine unternehmen. zeichnet, beschreibt vor allem die Nutzung on auf dem Server zu generieren, steht man der Quelldateien als Prototyp/Mocks. vor der nächsten Frage: Mit welcher Engine Natural Templating Ein großer Vorteil besteht darin, dass die soll die Seite verarbeitet werden? Vor der Besprechung der Syntax und der Entwickler diese Quelldateien etwa an einen An dieser Stelle kann zu traditionellen Funktionsweise von Thymeleaf wird ein ein- Grafiker geben können, der diese ohne eine Bibliotheken wie JavaServer Pages (JSP), faches JSP- mit einem Thymeleaf-Template laufende Anwendung auf dem Server weiter Velocity oder Freemarker gegriffen und das verglichen (siehe Listings 1 und 2). Beide Da- stylen kann. Solange die Datei direkt geöff- Rendering wie immer gelöst werden. Ein teien erzeugen die gleiche Ausgabe, wenn net und nicht durch die Engine verarbeitet Blick über den Tellerrand beziehungsweise die Seiten aus einer laufenden Anwendung wird, werden die unbekannten Attribute eine Google-Suche nach Alternativen in der aufgerufen werden. Das Besondere an Thy- vom Browser verworfen und die gemockten Java-Welt bringt einen weiteren Kandidaten meleaf ist, dass das HTML-Template auch Daten aus den bekannten Attributen und zum Vorschein: Thymeleaf [1]. statisch geöffnet werden kann und ein ge- Texten in den HTML-Tags angezeigt. Wird Das Open-Source-Projekt, das sich vor mocktes, grafisch korrektes Ergebnis zu se- die View durch einen Server ausgeliefert, 26 | iii iii iiiiii www.ijug.eu ersetzt Thymeleaf die Attribute, für die ent- sprechende Werte definiert wurden. Alternativ zur Standard-Syntax können auch Data Attributes verwendet werden (also „data-th-href“ statt „th:href“). So lässt sich anstelle mit unbekannten HTML-Attri- Abbildung 1: Statische Ausgabe von Thymeleaf buten, die vom Browser ignoriert werden, mit korrekten HTML5-Attributen arbeiten. Dies betrifft nur den statischen Zustand der Datei und ist aus Sicht des Autors als „nice to have“ einzuordnen. Im weiteren Verlauf gilt die Konvention, die Attribute aus dem Thymeleaf-Namespace zu nutzen. Einfache Syntax Abbildung 2: Statische Ausgabe von JSP Wie man schon am Beispiel erkennen kann, ist die Syntax auch beim ersten Kontakt mit <%@ page contentType="text/html;charset=UTF-8" language="java" %> der Engine leicht zu verstehen. Das liegt vor <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> allem daran, dass sich Thymeleaf lediglich auf zwei Kern-Komponenten im Markup konzen- <html> <head> triert: Expressions und Processors. In Listing <title></title> 3 sind einige grundlegenden Expressions zu <link href="${pageContext.request.contextPath}/css/jug_style.css" rel="stylesheet" type="text/css"/> sehen, die nun genauer beschrieben werden. </head> Als Expression bezeichnet man den Ausdruck <body> im Wert des Thymeleaf-HTML-Attributs. <table> <c:forEach items="${jugs}" var="jug"> In der ersten Zeile wird die wahrschein- <tr class="jug_entry"> lich bekannteste Form angetroffen, Varia- <td><a href="<c:url value="/jug/"/>${jug.id}"><img src="<c:out value="img/${jug.image}"/>"/></a></td> blen in einer (Java-)Web-Anwendung aus- <td><a href="<c:url value="/jug/"/>${jug.id}">${jug.name}</a></td> zugeben: das Einschließen der Variablen in </tr> „${...}“. Mit diesem Ausdruck werden Werte </c:forEach> </table> oder Objekte aus unserem Controller aus- </body> gegeben beziehungsweise verwendet. Als </html> weiterer Bekannter gehört auch der Aus- Listing 1 druck „#{...}“ zum Sprachumfang, der für die Ausgabe von fixen Strings/Messages wie „i18n“-Properties verwendet werden kann. <!DOCTYPE html> Bis jetzt wurde für die meist verwende- <html lang="en" xmlns:th="http://www.thymeleaf.org"> ten Zugriffsarten auf Werte oder Objekte <head> keine neue Syntax eingeführt, sodass hier <meta charset="UTF-8"/> <title>JUG List</title> schon zu erkennen ist, dass die Lernkurve <link th:href="@{/css/jug_style.css}" href="css/jug_style.css" von Thymeleaf erfreulich flach ist. Soll es ein rel="stylesheet" type="text/css"/> wenig mehr Komfort sein, kann man auf die </head> <body> Expression *{...} zurückgreifen. Wie in den <table> Zeilen drei bis fünf zu sehen ist, wird mit <tr class="jug_entry" th:each="jug : ${jugs}"> <td><a href="#"><img th:src="@{'/img/' + ${jug.image}}" src="img/dummy. ihr auf ein umschließendes Objekt zurück- jpg"/></a></td> gegriffen, dessen Attribute werden direkt <td><a href="#" th:text="${jug.name}">Meine Jug</a></td> referenziert. Falls kein äußeres Objekt vor- </tr> </table> handen ist, verhält sich dieser Ausdruck wie </body> der genannte Variablen-Zugriff per ${...}. </html> Sehr nützlich ist die URL-Expression „@ Listing 2 {...}“. In Listing 3 sind mehrere Beispiele zu sehen, allen voran die Verwendung von re- lativen Pfaden in der Anwendung. Hier wird der Context-Pfad der Anwendung auto- ren. Dies bietet zum Beispiel den Vorteil, dabei mit oder ohne Platzhalter erfolgen. matisch ermittelt und ergänzt, sodass ein dass mit relativ elegantem Code in Schlei- Dies führt im ersten Beispiel zu einem Link komplexes beziehungsweise unschönes fen bei jedem Eintrag auf die gleiche URL mit Query-Parameter und im zweiten zur Präfixen per Hand nicht notwendig ist. URL- mit unterschiedlichen Parametern gemappt Ersetzung des Platzhalters. Expressions lassen sich auch parametrisie- werden kann. Die Parametrisierung kann Soll ein Link doch einmal auf eine andere Java aktuell 2-2017 | 27 Template-Engine Anwendung auf dem Server oder ein ganz <span th:text="${jug.name}">Platzhalter</span> <span th:text="#{welcome.message}">Platzhalter</span> anderes System zeigen, kann dieses auch in den URL-Expressions mit angegeben <div th:object="${jug}"> <span th:text="*{name}">Platzhalter</span> werden. Dabei wird der URL ein „~“ (Server </div> relativ) beziehungsweise ein „//“ (Protocol relative) vorangestellt. Im zweiten Fall kann <a th:href="@{/jugs}">JUGs</a> <!-- Parameter ohne Platzhalter: /jug/details?jugId=1 --> alternativ auch die vollständige URL inklu- <a th:href="@{/jug/details(jugId=${jug.id})}">JUG Details</a> sive Protokoll in der Expression verwendet <!-- Parameter mit Platzhalter: /jug/1/details --> <a th:href="@{/jug/{jugId}/details(jugId=${jug.id})}">JUG Details</a> werden. Dies schafft jedoch eine Bindung an <a th:href="@{~/otherApplication}">eine andere Anwendung</a> das Protokoll und erzwingt den Einsatz von <a th:href="@{//otherApplication}">ein anderer Server</a> Environment-Configs, um beispielsweise im Listing 3 Testbetrieb jeglichen Datenverkehr mit an- deren Systemen über HTTP anstatt HTTPS laufen zu lassen. <span th:text="${jug.name}">Reintext</span> Processors <span th:utext="${jug.name}">unescaped Text</span> Unter „Processor“ wird im Thymeleaf- <span th:inline="text">Meine JUG: [[${jug.name}]]!</span> Kontext nicht nur das verwendete HTML- Listing 4 Attribut verstanden, sondern auch seine dahinterliegende Logik und das Resultat bei der Verarbeitung durch die Engine. In Thy- meleaf steht eine theoretisch überschauba- <tbody> <tr th:each="jug : ${jugs}" th:object="${jugs}"> re Anzahl von Processors zur Verwendung <td th:text="*{name}">erste JUG</td> bereit. Theoretisch aus dem Grund, weil es </tr> für jedes denkbare Standard-HTML5-Attri- <tr> <td>zweite JUG</td> but einen Processor gibt. Diese sind intuitiv </tr> so benannt, dass man