Blog o programování a webu - Java, Spring, Python a jiné

View vrstva s Thymeleaf – náhrada za JSP

Nov 5, 13 • Thymeleaf5 CommentsRead More »

Dnes bych vám chtěl představit Thymeleaf template engine pro XML, XHTML a HTML5. Jedná se plnohodnotnou náhradu JSP, který umožňuje vytvářet tzv. natural templates pomocí dialektů. Šablony které jsou stejně validní jako finální stránka, syntaxe totiž nenaruší strukturu dokumentu. Využití najde především ve vytváření prototypů a také v situaci, kdy je html kód stránky dodán designérem a vývojář jen doplní plnění daty ze serveru.

Motivace
Loni jsem se rozhodl implementovat online tool pro neziskovou organizaci. Při výběru view vrstvy jsem hledal něco, co by mi z prototypu v XHTML (+ Bootstrap, pro rychlý návrh responsivního designu) umožnilo jednoduše získat stránky aplikace. Nakonec jsem vybral Thymeleaf, open source od Daniela Fernándeze a skupiny přispěvatelů, včetně Michala Kreuzmana.

Thymeleaf
Thymeleaf je Java knihovna sloužící jako XML, XHTML či HTML5 template engine a to jak pro view vrstvu webových aplikací, stejně dobře jako pro rich HTML šablony emailů nebo XML.
Jádro knihovny je DOM processing engine, který používá vlastní high-performance DOM implementaci. Při výběru vhodné view vrstvy jsem provedl jednoduché perfomance testy, protože jsem se obával mnoha operací nad DOM, ale u všech testů byla výkonost srovnatelná s JSP.

Nejdůležitější je však snadná integrace se Spring MVC (Spring EL, form binding, i18n…) a jeho konfigurovatelnost a rozšiřitelnost.

Srovnání JSP vs. Thymeleaf
Pro srovnání si vypůjčím obrázky ze stánek Thymeleaf. Stejné srovnání jako s JSP se stejným výsledkem bychom mohli udělat i s Freemarkerem a nebo Velocity. Síla těchto template enginu je jinde, hlavně ve zpracování textů, zatímco Thymeleaf se omezuje pouze na XML.

JSP

<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="s" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
 
<html> 
<head>
    <title>Spring MVC view layer: Thymeleaf vs. JSP</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" media="all" href="<s:url value='/css/thvsjsp.css' />"/>
</head>
 
<body>
<h2>This is a JSP</h2>
 
<s:url var="formUrl" value="/subscribejsp" />
<sf:form modelAttribute="subscription" action="${formUrl}">
 
    <fieldset>
        <div>
            <label for="email"><s:message code="subscription.email" />: </label>
            <sf:input path="email" />
        </div>
        <div>
            <label><s:message code="subscription.type" />: </label>
            <ul>
                <c:forEach var="type" items="${allTypes}" varStatus="typeStatus">
                    <li>
                        <sf:radiobutton path="subscriptionType" value="${type}" />
                        <label for="subscriptionType${typeStatus.count}">
                            <s:message code="subscriptionType.${type}" />
                        </label>
                    </li>
                </c:forEach>
            </ul>
        </div>
 
        <div class="submit">
            <button type="submit" name="save"><s:message code="subscription.submit" /></button>
        </div>
    </fieldset>
 
</sf:form>
</body>
</html>

Stránka zpracovaná web serverem pak vypadá takto
JSP in browser

Thymeleaf

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Spring MVC view layer: Thymeleaf vs. JSP</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" media="all"
          href="../../css/thvsjsp.css" th:href="@{/css/thvsjsp.css}"/>
</head>
 
<body>
<h2>This is a Thymeleaf template</h2>
<form action="#" th:object="${subscription}" th:action="@{/subscribeth}">
 
    <fieldset>
        <div>
            <label for="email" th:text="#{subscription.email}">Email: </label>
            <input type="text" th:field="*{email}" />
        </div>
        <div>
            <label th:text="#{subscription.type}">Type: </label>
            <ul>
                <li th:each="type : ${allTypes}">
                    <input type="radio" th:field="*{subscriptionType}" th:value="${type}" />
                    <label th:for="${#ids.prev('subscriptionType')}"
                           th:text="#{'subscriptionType.'+${type}}">First type</label>
                </li>
                <li th:remove="all"><input type="radio" /> <label>Second Type</label></li>
            </ul>
        </div>
 
        <div class="submit">
            <button type="submit" name="save" th:text="#{subscription.submit}">Subscribe me!</button>
        </div>
    </fieldset>
 
</form>
</body>
</html>

Stránka zpracovaná web serverem pak vypadá takto
Thymeleaf in browser

Když však zobrazíme stránku jako obyčejné html, bez využití web serveru, tak je výsledek naprosto odlišný.
JSP
JSP without web server
Thymeleaf
Thymeleaf without web server

Toto samozřejmě není jediná výhoda, o dalších se ale rozepíšu jindy. Že by nastal konec přepisování prototypů a grafických návrhů do JSP, či nutnosti spustit web server, když je potřeba upravovat html kód stránky, CSS nebo JS?

Seriál Spring MVC + Thymeleaf
Brzy bych chtěl publikovat seriál článků na téma Java na web – rychle, snadno a levně. Půjde o ukázkovou aplikaci postavenou na kombinaci Java, Spring MVC, Thymeleaf, MongoDB, HTML, Bootstrap, CSS, Spring security, nějaký JS a celé to poběží na application cloud platformě Heroku. Rád bych ukázal, že web není jen PHP a že řeči, že Java není na web, jsou jen předsudky.

Doplnění:
V den napsání tohoto postu, 4. 11., byla vydána nová verze 2.1.

Tags: , , ,

5 Responses to View vrstva s Thymeleaf – náhrada za JSP

  1. Jiří Blažek says:

    Pěkné, to jsem neznal. Díky.

  2. Martin Dvoracek says:

    Pekne, zajimave…Skoda, ze planovany clanek “rychle, snadno a levne” nevysel jiz pred rokem – to jsem totiz jako uplny zelenac zacinal psat prvni vetsi aplikaci a nakonec jsem se rozhodl pro java + spring mvc + spring security + hibernate + mysql + jsp + css + js + bootstrap + tomcat…a samozrejme jsem udelal snad kazdou zacatecnickou chybu, kterou jsem mohl, takze jsem si to opravdu uzil :D Kdybys ti nahodou pomohlo od zacatecnika vedet, co mi delalo nejvetsi problemy a jak jsem je pak vyresil, tak se nevahej ozvat na mail.. :)

    Btw – pokud to chces opravdu rychle a snadno, tak imho neni lepsiho nastroje nez je Spring Roo

    • pavek.michal@email.cz says:

      Díky za komentář. Ty problémy by mě zajímaly, takže email určitě napíšu.

  3. Jan33 says:

    Většinu práce u nás odedře Wicket, který používá podobný způsob (statické HTML + ID parametry). Ale uznáván, že třeba na emaily to je velký kanón a tak jsem rád že můžu prozkoumat něco lehčího.

    • pavek.michal@email.cz says:

      Wicket jsou opravdu silnější nástroj. Dal jsem přednost Thymeleaf protože můžu použít čistý Spring MVC, controllery bez čehokoliv navíc.