it-swarm.com.de

JSP-Tricks, um das Templating zu erleichtern?

Bei der Arbeit wurde ich beauftragt, eine Reihe von HTML-Dateien in ein einfaches JSP-Projekt umzuwandeln. Es ist wirklich alles statisch, keine serverseitige Logik zum Programmieren. Ich sollte erwähnen, dass ich Java noch nicht kennen. JSP-Dateien scheinen die Verwendung allgemeiner Include-Variablen und Variablen zu vereinfachen, ähnlich wie PHP, aber ich würde gerne einen einfachen Weg kennenlernen, um etwas wie Vorlagenvererbung (Django-Stil) zu erhalten oder zumindest eine base.jsp haben zu können Datei, die die Kopfzeile und die Fußzeile enthält, damit ich den Inhalt später einfügen kann.

Ben Lings scheint in seiner Antwort hier etwas Hoffnung zu geben: JSP-Template-Vererbung Kann jemand erklären, wie das zu erreichen ist?

Angesichts der Tatsache, dass ich nicht viel Zeit habe, denke ich, dass dynamisches Routing ein wenig zu viel ist. Daher bin ich froh, dass URLs direkt auf .jsp-Dateien abgebildet werden.

Vielen Dank.

edit: Ich möchte keine externen Bibliotheken verwenden, da dies die Lernkurve für mich und andere Projektbeteiligte erhöhen würde. Dafür wurde das Unternehmen beauftragt, für das ich arbeite.

Noch eine Änderung: Ich bin nicht sicher, ob JSP tags nützlich ist, da mein Inhalt keine Vorlagenvariablen enthält. Was ich brauche, ist eine Möglichkeit, dies zu tun:

base.html:

<html><body>
{ content.body }
</body></html>

somepage.html

<wrapper:base.html>
<h1>Welcome</h1>
</wrapper>

mit der Ausgabe:

<html><body>
<h1>Welcome</h1>
</body></html>

Ich denke, das würde mir genug Flexibilität geben, um alles zu tun, was ich brauche. Es könnte mit includes erreicht werden, aber dann würde ich für jeden Wrapper einen oberen und einen unteren Include benötigen, was irgendwie chaotisch ist.

295
Scott

Wie von Skaffman empfohlen , sind JSP 2.0-Tag-Dateien die Knie der Biene.

Nehmen wir ein einfaches Beispiel.

Geben Sie Folgendes in WEB-INF/tags/wrapper.tag ein

<%@tag description="Simple Wrapper Tag" pageEncoding="UTF-8"%>
<html><body>
  <jsp:doBody/>
</body></html>

Jetzt in deiner example.jsp Seite:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:wrapper>
    <h1>Welcome</h1>
</t:wrapper>

Das macht genau das, was Sie denken.


Also, lass uns das auf etwas allgemeineres ausdehnen .WEB-INF/tags/genericpage.tag

<%@tag description="Overall Page template" pageEncoding="UTF-8"%>
<%@attribute name="header" fragment="true" %>
<%@attribute name="footer" fragment="true" %>
<html>
  <body>
    <div id="pageheader">
      <jsp:invoke fragment="header"/>
    </div>
    <div id="body">
      <jsp:doBody/>
    </div>
    <div id="pagefooter">
      <jsp:invoke fragment="footer"/>
    </div>
  </body>
</html>

Um dies zu benutzen:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:genericpage>
    <jsp:attribute name="header">
      <h1>Welcome</h1>
    </jsp:attribute>
    <jsp:attribute name="footer">
      <p id="copyright">Copyright 1927, Future Bits When There Be Bits Inc.</p>
    </jsp:attribute>
    <jsp:body>
        <p>Hi I'm the heart of the message</p>
    </jsp:body>
</t:genericpage>

Was hat dich das gekauft? Sehr viel, aber es wird noch besser ...


WEB-INF/tags/userpage.tag

<%@tag description="User Page template" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
<%@attribute name="userName" required="true"%>

<t:genericpage>
    <jsp:attribute name="header">
      <h1>Welcome ${userName}</h1>
    </jsp:attribute>
    <jsp:attribute name="footer">
      <p id="copyright">Copyright 1927, Future Bits When There Be Bits Inc.</p>
    </jsp:attribute>
    <jsp:body>
        <jsp:doBody/>
    </jsp:body>
</t:genericpage>

Um dies zu verwenden: (Nehmen wir an, wir haben eine Benutzervariable in der Anfrage)

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:userpage userName="${user.fullName}">
  <p>
    First Name: ${user.firstName} <br/>
    Last Name: ${user.lastName} <br/>
    Phone: ${user.phone}<br/>
  </p>
</t:userpage>

Es kann jedoch dazu führen, dass Sie den Benutzerdetailblock an anderen Stellen verwenden möchten. Also werden wir es umgestalten .WEB-INF/tags/userdetail.tag

<%@tag description="User Page template" pageEncoding="UTF-8"%>
<%@tag import="com.example.User" %>
<%@attribute name="user" required="true" type="com.example.User"%>

First Name: ${user.firstName} <br/>
Last Name: ${user.lastName} <br/>
Phone: ${user.phone}<br/>

Nun wird das vorige Beispiel:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:userpage userName="${user.fullName}">
  <p>
    <t:userdetail user="${user}"/>
  </p>
</t:userpage>

Das Schöne an JSP-Tag-Dateien ist, dass Sie generische Markierungen grundsätzlich mit Tags versehen und sie nach Herzenslust umgestalten können.

JSP Tag Files hat ziemlich viele Dinge wie Tiles usurpiert, zumindest für mich. Ich finde sie viel einfacher zu benutzen, da die einzige Struktur das ist, was Sie ihr geben, nichts vorgefasstes. Außerdem können Sie JSP-Tag-Dateien für andere Zwecke verwenden (z. B. das Benutzerdetailfragment oben).

Hier ist ein Beispiel, das dem von DisplayTag ähnelt, das ich gemacht habe, aber dies geschieht alles mit Tag-Dateien (und dem Stripes-Framework, das sind die s: tags ..). Daraus ergibt sich eine Tabelle mit Zeilen, abwechselnden Farben, Seitennavigation usw.:

<t:table items="${actionBean.customerList}" var="obj" css_class="display">
  <t:col css_class="checkboxcol">
    <s:checkbox name="customerIds" value="${obj.customerId}"
                onclick="handleCheckboxRangeSelection(this, event);"/>
  </t:col>
  <t:col name="customerId" title="ID"/>
  <t:col name="firstName" title="First Name"/>
  <t:col name="lastName" title="Last Name"/>
  <t:col>
    <s:link href="/Customer.action" event="preEdit">
      Edit
      <s:param name="customer.customerId" value="${obj.customerId}"/>
      <s:param name="page" value="${actionBean.page}"/>
    </s:link>
  </t:col>
</t:table>

Natürlich arbeiten die Tags mit dem JSTL tags (wie c:if usw.). Das einzige, was Sie nicht innerhalb eines Tag-Datei-Tags tun können, ist das Hinzufügen von Java-Scriptlet-Code. Dies ist jedoch nicht so sehr eine Einschränkung, wie Sie vielleicht denken. Wenn ich Scriptlet-Sachen brauche, füge ich einfach die Logik in ein Tag ein und füge das Tag ein. Einfach.

Tag-Dateien können also alles sein, was Sie wollen. Auf der einfachsten Ebene ist es ein einfaches Refactoring zum Ausschneiden und Einfügen. Schnappen Sie sich ein Stück Layout, schneiden Sie es aus, führen Sie einige einfache Parametrierungen durch und ersetzen Sie es durch einen Aufruf eines Tags.

Auf einer höheren Ebene können Sie anspruchsvolle Dinge tun, wie dieses Tabellen-Tag, das ich hier habe.

658
Will Hartung

Ich habe es mir leicht gemacht, die JSP Template-Vererbungs-Tag-Bibliothek im Django-Stil zu erstellen . https://github.com/kwon37xi/jsp-template-inheritance

Ich denke, es ist einfach, Layouts ohne Lernkurve zu verwalten.

beispielcode:

base.jsp: Layout

<%@page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://kwonnam.pe.kr/jsp/template-inheritance" prefix="layout"%>
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>JSP Template Inheritance</title>
    </head>

<h1>Head</h1>
<div>
    <layout:block name="header">
        header
    </layout:block>
</div>

<h1>Contents</h1>
<div>
    <p>
    <layout:block name="contents">
        <h2>Contents will be placed under this h2</h2>
    </layout:block>
    </p>
</div>

<div class="footer">
    <hr />
    <a href="https://github.com/kwon37xi/jsp-template-inheritance">jsp template inheritance example</a>
</div>
</html>

view.jsp: Inhalt

<%@page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://kwonnam.pe.kr/jsp/template-inheritance" prefix="layout"%>
<layout:extends name="base.jsp">
    <layout:put name="header" type="REPLACE">
        <h2>This is an example about layout management with JSP Template Inheritance</h2>
    </layout:put>
    <layout:put name="contents">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin porta,
        augue ut ornare sagittis, diam libero facilisis augue, quis accumsan enim velit a mauris.
    </layout:put>
</layout:extends>
21
KwonNam

Basierend auf der gleichen Grundidee wie in der Antwort von @Will Hartung , ist hier meine magische One-Tag-Erweiterungsvorlagen-Engine. Es enthält sogar eine Dokumentation und ein Beispiel :-)

WEB-INF/tags/block.tag:

<%--
    The block tag implements a basic but useful extensible template system.

    A base template consists of a block tag without a 'template' attribute.
    The template body is specified in a standard jsp:body tag, which can
    contain EL, JSTL tags, nested block tags and other custom tags, but
    cannot contain scriptlets (scriptlets are allowed in the template file,
    but only outside of the body and attribute tags). Templates can be
    full-page templates, or smaller blocks of markup included within a page.

    The template is customizable by referencing named attributes within
    the body (via EL). Attribute values can then be set either as attributes
    of the block tag element itself (convenient for short values), or by
    using nested jsp:attribute elements (better for entire blocks of markup).

    Rendering a template block or extending it in a child template is then
    just a matter of invoking the block tag with the 'template' attribute set
    to the desired template name, and overriding template-specific attributes
    as necessary to customize it.

    Attribute values set when rendering a tag override those set in the template
    definition, which override those set in its parent template definition, etc.
    The attributes that are set in the base template are thus effectively used
    as defaults. Attributes that are not set anywhere are treated as empty.

    Internally, attributes are passed from child to parent via request-scope
    attributes, which are removed when rendering is complete.

    Here's a contrived example:

    ====== WEB-INF/tags/block.tag (the template engine tag)

    <the file you're looking at right now>

    ====== WEB-INF/templates/base.jsp (base template)

    <%@ page trimDirectiveWhitespaces="true" %>
    <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
    <t:block>
        <jsp:attribute name="title">Template Page</jsp:attribute>
        <jsp:attribute name="style">
            .footer { font-size: smaller; color: #aaa; }
            .content { margin: 2em; color: #009; }
            ${moreStyle}
        </jsp:attribute>
        <jsp:attribute name="footer">
            <div class="footer">
                Powered by the block tag
            </div>
        </jsp:attribute>
        <jsp:body>
            <html>
                <head>
                    <title>${title}</title>
                    <style>
                        ${style}
                    </style>
                </head>
                <body>
                    <h1>${title}</h1>
                    <div class="content">
                        ${content}
                    </div>
                    ${footer}
                </body>
            </html>
        </jsp:body>
    </t:block>

    ====== WEB-INF/templates/history.jsp (child template)

    <%@ page trimDirectiveWhitespaces="true" %>
    <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
    <t:block template="base" title="History Lesson">
        <jsp:attribute name="content" trim="false">
            <p>${shooter} shot first!</p>
        </jsp:attribute>
    </t:block>

    ====== history-1977.jsp (a page using child template)

    <%@ page trimDirectiveWhitespaces="true" %>
    <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
    <t:block template="history" shooter="Han" />

    ====== history-1997.jsp (a page using child template)

    <%@ page trimDirectiveWhitespaces="true" %>
    <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
    <t:block template="history" title="Revised History Lesson">
        <jsp:attribute name="moreStyle">.revised { font-style: italic; }</jsp:attribute>
        <jsp:attribute name="shooter"><span class="revised">Greedo</span></jsp:attribute>
    </t:block>

--%>

<%@ tag trimDirectiveWhitespaces="true" %>
<%@ tag import="Java.util.HashSet, Java.util.Map, Java.util.Map.Entry" %>
<%@ tag dynamic-attributes="dynattributes" %>
<%@ attribute name="template" %>
<%
    // get template name (adding default .jsp extension if it does not contain
    // any '.', and /WEB-INF/templates/ prefix if it does not start with a '/')
    String template = (String)jspContext.getAttribute("template");
    if (template != null) {
        if (!template.contains("."))
            template += ".jsp";
        if (!template.startsWith("/"))
            template = "/WEB-INF/templates/" + template;
    }
    // copy dynamic attributes into request scope so they can be accessed from included template page
    // (child is processed before parent template, so only set previously undefined attributes)
    Map<String, String> dynattributes = (Map<String, String>)jspContext.getAttribute("dynattributes");
    HashSet<String> addedAttributes = new HashSet<String>();
    for (Map.Entry<String, String> e : dynattributes.entrySet()) {
        if (jspContext.getAttribute(e.getKey(), PageContext.REQUEST_SCOPE) == null) {
            jspContext.setAttribute(e.getKey(), e.getValue(), PageContext.REQUEST_SCOPE);
            addedAttributes.add(e.getKey());
        }
    }
%>

<% if (template == null) { // this is the base template itself, so render it %>
    <jsp:doBody/>
<% } else { // this is a page using the template, so include the template instead %>
    <jsp:include page="<%= template %>" />
<% } %>

<%
    // clean up the added attributes to prevent side effect outside the current tag
    for (String key : addedAttributes) {
        jspContext.removeAttribute(key, PageContext.REQUEST_SCOPE);
    }
%>
9
amichair

Verwenden Sie tile . Es hat mein Leben gerettet.

Aber wenn nicht, gibt es das include-Tag , das es ähnlich wie PHP macht. 

Das Body-Tag kann möglicherweise nicht das tun, wozu Sie es benötigen, es sei denn, Sie haben sehr einfachen Inhalt. Mit dem body-Tag wird der Körper eines angegebenen Elements definiert. Werfen Sie einen Blick auf dieses Beispiel :

<jsp:element name="${content.headerName}"   
   xmlns:jsp="http://Java.Sun.com/JSP/Page">    
   <jsp:attribute name="lang">${content.lang}</jsp:attribute>   
   <jsp:body>${content.body}</jsp:body> 
</jsp:element>

Sie geben den Elementnamen, alle Attribute an, die dieses Element haben könnte (in diesem Fall "lang"), und dann den darin enthaltenen Text - den Hauptteil. Also wenn 

  • content.headerName = h1,
  • content.lang = fr und
  • content.body = Heading in French

Dann wäre die Ausgabe

<h1 lang="fr">Heading in French</h1>
4
geowa4

hinzufügen von Abhängigkeiten zur Verwendung <% @ tag description = "Benutzerseitenvorlage" pageEncoding = "UTF-8"%>

<dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>javax.servlet.jsp.jstl-api</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
    </dependencies>
0

Ich weiß, dass diese Antwort Jahre später folgen wird, und es gibt bereits eine großartige Antwort auf die JSP von Will Hartung, aber es gibt Facelets, die sogar in den Antworten der verknüpften Frage in der ursprünglichen Frage erwähnt werden.

Beschreibung der Facelets SO

Facelets ist eine XML-basierte Ansichtstechnologie für das JavaServer Faces-Framework. Facelets wurde speziell für JSF entwickelt und soll eine einfachere und leistungsfähigere Alternative zu JSP-basierten Ansichten sein. Anfänglich ein separates Projekt, wurde die Technologie im Rahmen von JSF 2.0 und Java-EE 6 standardisiert und hat JSP nicht mehr unterstützt. Fast alle auf JSF 2.0 bezogenen Komponentenbibliotheken unterstützen keine JSP mehr, sondern nur noch Facelets.

Leider war die beste einfache Tutorialbeschreibung, die ich gefunden habe, auf Wikipedia und keine Tutorial-Site. Tatsächlich funktioniert der Abschnitt, der templates beschreibt, sogar so, wie er ursprünglich gestellt wurde.

Aufgrund der Tatsache, dass Java-EE 6 JSP abgelehnt hat, würde ich empfehlen, mit Facelets zu arbeiten, obwohl es so aussieht, als ob es für wenig bis gar keinen Gewinn über JSP erforderlich wäre.

0
Fering