Şablonlama işlemini kolaylaştırmak için JSP hileleri?


305

İş yerinde bir sürü HTMLdosyayı basit bir JSPprojeye dönüştürmekle görevlendirildim . Gerçekten statik, programlanacak sunucu tarafı mantığı yok. Java için tamamen yeni olduğumu belirtmeliyim. JSP dosyaları, genel içerikler ve değişkenlerle çalışmayı kolaylaştırıyor gibi görünüyor.PHP , ancak şablon devralma gibi bir şey almanın basit bir yolunu bilmek istiyorum (Django stil) veya en azından içeren bir base.jsp dosyasına sahip olmak istiyorum üstbilgi ve altbilgi, böylece daha sonra içerik ekleyebilirim.

Ben Lings , cevabında biraz umut veriyor gibi görünüyor: JSP şablonu mirası Birisi bunu nasıl başaracağını açıklayabilir mi?

Fazla zamanım olmadığı için dinamik yönlendirmenin biraz fazla olduğunu düşünüyorum, bu yüzden URL'lerin doğrudan .jsp dosyalara , ancak öneriye açığım.

Teşekkürler.

Düzenle: Herhangi bir harici kütüphane kullanmak istemiyorum, çünkü kendim ve proje üzerinde çalışan diğerleri için öğrenme eğrisini artıracak ve çalıştığım şirket bunu yapmak için sözleşmeli.

Başka bir düzenleme:JSP tags İçeriğimin gerçekten şablon değişkenleri olmadığından faydalı olup olmayacağından emin değilim . İhtiyacım olan şey bunu yapabilmenin bir yoludur:

base.html:

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

somepage.html

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

çıktı ile:

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

Bunun bana ihtiyacım olan her şeyi yapmam için yeterli çok yönlülük sağlayacağını düşünüyorum. Bu ile elde edilebilir includesama sonra her sarıcı için bir tür dağınık bir üst ve bir alt içerir gerekir.

Yanıtlar:


682

Gibi skaffman önerdi , JSP 2.0 Etiket dosyaları arının dizleri vardır.

Basit örneğinizi ele alalım.

Aşağıdakileri yerleştirin WEB-INF/tags/wrapper.tag

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

Şimdi example.jspsayfanızda:

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

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

Tam olarak düşündüğünüzü yapar.


Yani, bunu biraz daha genel bir şeye genişletelim. 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>

Bunu kullanmak için:

<%@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>

Seni ne satın alıyor? Gerçekten çok, ama daha da iyi oluyor ...


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>

Bunu kullanmak için: (istekte bir kullanıcı değişkenimiz olduğunu varsayalım)

<%@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>

Ancak bu kullanıcı ayrıntı bloğunu başka yerlerde kullanmaktan hoşlanırsınız. Yani, yeniden düzenleyeceğiz. 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/>

Şimdi önceki örnek:

<%@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>

JSP Tag dosyalarının güzelliği, temel olarak genel işaretlemeyi etiketlemenize ve ardından kalbinizin içeriğine yeniden yönlendirmenize izin vermesidir.

JSP Tag Filesgibi hemen hemen gasp şeyler var Tilesen azından benim için, vb. Onları verdiğiniz tek yapı olduğu için, kullanımı daha kolay buluyorum. Ayrıca JSP etiket dosyalarını başka şeyler için de kullanabilirsiniz (yukarıdaki kullanıcı detayı parçası gibi).

İşte yaptığım DisplayTag'e benzer bir örnek, ancak bunların tümü Tag Files (ve Stripesçerçeve, s: tags ..) ile yapılır. Bu, bir tablo, alternatif renkler, sayfada gezinme vb. İle sonuçlanır:

<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>

Tabii ki etiketler JSTL tags(c:if vb.) . Bir etiket dosyası etiketinin gövdesi içinde yapamayacağınız tek şey Java komut dosyası kodunu eklemektir, ancak bu düşündüğünüz kadar bir sınırlama değildir. Eğer scriptlet şeyler gerekiyorsa, ben sadece bir etikete mantık koymak ve etiketi bırakın. Kolay.

Dolayısıyla, etiket dosyaları olmasını istediğiniz her şey olabilir. En temel düzeyde, basit kesme ve yapıştırma yeniden düzenleme işlemidir. Bir yığın düzen alın, kesin, basit bir parametreleştirme yapın ve bir etiket çağırma ile değiştirin.

Daha yüksek bir düzeyde, burada sahip olduğum bu tablo etiketi gibi karmaşık şeyler yapabilirsiniz.


34
Bunun için teşekkürler. JSF'den gelen benim için harika olan JSP etiket dosyalarında bulabileceğim en iyi öğretici. Birden fazla oy verebilsem.
digitaljoel

66
+ 40million. Bulduğum boktan öğreticiden 50.000 kat daha iyi açıkladığınız için teşekkür ederiz. Rails dünyasından geliyor ve ERB eksik, tam da ihtiyacım olan bu. Bir blog yazmalısınız.
cbmeeks

2
Gerçekten güzel bir öğretici. Yaptığınız tablo etiketinin kodunu bizimle paylaşır mısınız? Bir süre önce kendim bir tane yarattım ama yaklaşımınız daha iyi.
Thiago Duarte

4
Bir etiket dosyası etiketi oluşturursanız, bu etiketin JSP dosyasındaki içeriğinde komut dosyası kodu bulunamaz: <t: mytag> burada komut dosyası kodu yok </ t: mytag>. Ancak, etiketin kendisini uygulayan etiket dosyasında, herhangi bir JSP gibi, istediğiniz tüm komut dosyası koduna sahip olabilir.
Will Hartung

4
Not - etiketlerin sırası önemli gibi görünüyor; jsp: özniteliği jsp: body'den önce gelmelidir, yoksa bir hata alırsınız. Ayrıca başka bir hatayı önlemek için jsp: invoke eşleştirmek için karşılık gelen @attribute etiketi ayarlamak zorunda kaldı. GlassFish 3.2.2 Kullanma
Ryan

21

Django tarzı JSP Template devralma etiketi kütüphanesini oldukça kolaylaştırdım. https://github.com/kwon37xi/jsp-template-inheritance

Öğrenme eğrisi olmadan düzenleri yönetmenin kolay olduğunu düşünüyorum.

örnek kod:

base.jsp: düzen

<%@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: içindekiler

<%@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>

10

@Will Hartung ile aynı temel fikri temel alır cevabı ile sihirli tek etiketli genişletilebilir şablon motorum. Hatta dokümantasyon ve bir örnek içerir :-)

WEB-INF / etiketler / 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);
    }
%>

4

Fayans kullanın . Hayatımı kurtardı.

Ancak yapamazsanız, içerme etiketi var php'ye benzeyen .

Süper basit içeriğiniz olmadığı sürece, gövde etiketi aslında ihtiyacınız olanı yapmayabilir. Gövde etiketi, belirtilen bir öğenin gövdesini tanımlamak için kullanılır. Bu örneğe bir göz atın :

<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>

Öğe adını, öğenin sahip olabileceği tüm nitelikleri (bu durumda "lang") ve daha sonra içine giren metni (gövde) belirtirsiniz. Yani eğer

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

Sonra çıktı

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


0

kullanım için dependsecys ekle <% @ tag description = "Kullanıcı Sayfası şablonu" 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>

-1

Bu cevabın bundan yıllar sonra geldiğini biliyorum ve Will Hartung tarafından zaten büyük bir JSP cevabı var, ancak Facelets var, hatta orijinal sorudaki bağlantılı sorunun cevaplarında belirtiliyor.

Facelets SO etiketi açıklaması

Facelets, JavaServer Faces çerçevesi için XML tabanlı bir görüntüleme teknolojisidir. Özel olarak JSF için tasarlanan Facelets, JSP tabanlı görünümlere daha basit ve daha güçlü bir alternatif olarak tasarlanmıştır. Başlangıçta ayrı bir proje olan teknoloji, JSF 2.0 ve Java-EE 6'nın bir parçası olarak standartlaştırıldı ve JSP'yi kullanımdan kaldırdı. Hemen hemen tüm JSF 2.0 hedefli bileşen kitaplıkları artık JSP'yi desteklemez, yalnızca Facelets'i destekler.

Ne yazık ki bulduğum en iyi düz öğretici açıklama bir öğretici sitede değil Wikipedia idi . Aslında, şablonları tanımlayan bölüm orijinal sorunun ne istediğini açıklar .

Java-EE 6'nın JSP'yi kullanımdan kaldırması nedeniyle, JSP'den çok az kazanç elde etmek ya da hiç kazanmamak için daha fazla gerekli olabilecek gibi görünmesine rağmen Facelets ile gitmenizi tavsiye ederim.


Java EE 6, JSP'yi kullanımdan kaldırmadı, JSF'nin görüntüleme teknolojisi olarak JSP kullanılarak kullanımdan kaldırıldı.
Ryan

@Ryan Bu durumda her ikisi de görünüm teknolojisi hakkında konuştuklarından, kullanımdan kaldırıldığını söylemenin yanlışlığı nedir?
Fering

Sorunun JSF ile ilgisi yok. Saf JSP ile ilgili. Cevabınız JSF için olan Facelets kullanmaktır.
Ryan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.