JSP技巧使模板更容易?

本文翻譯自:JSP tricks to make templating easier?

At work I've been tasked with turning a bunch of HTML files into a simple JSP project. 在工作中,我的任務是將一堆HTML文件轉換爲一個簡單的JSP項目。 It's really all static, no serverside logic to program. 它實際上是靜態的,無需編程的服務器端邏輯。 I should mention I'm completely new to Java. 我應該提到我對Java完全不熟悉。 JSP files seem to make it easy to work with common includes and variables, much like PHP , but I'd like to know a simple way to get something like template inheritance ( Django style) or at least be able to have a base.jsp file containing the header and the footer, so I can insert content later. JSP文件似乎可以很容易地使用常見的包含和變量,就像PHP一樣,但我想知道一種簡單的方法來獲得類似模板繼承( Django樣式)或者至少能夠擁有base.jsp包含頁眉和頁腳的文件,所以我可以稍後插入內容。

Ben Lings seems to offer some hope in his answer here: JSP template inheritance Can someone explain how to achieve this? Ben Lings似乎在這裏給出了一些希望: JSP模板繼承有人可以解釋如何實現這個目標嗎?

Given that I don't have much time I think dynamic routing is a little much, so I'm happy to just to have URLs map directly onto .jsp files, but I'm open to suggestion. 鑑於我沒有太多時間,我認爲動態路由有點多,所以我很高興只是將URL直接映射到.jsp文件,但我願意接受建議。

Thanks. 謝謝。

edit: I don't want to use any external libraries, because it would increase the learning curve for myself and others who work on the project, and the company I work for has been contracted to do this. 編輯:我不想使用任何外部庫,因爲它會增加我自己和其他從事該項目的人的學習曲線,而我所工作的公司已經簽約這樣做。

Another edit: I'm not sure if JSP tags will be useful because my content doesn't really have any template variables. 另一個編輯:我不確定JSP tags是否有用,因爲我的內容實際上沒有任何模板變量。 What I need is a way to be able to do this: 我需要的是一種能夠做到這一點的方法:

base.html:

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

somepage.html

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

with the output being: 輸出爲:

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

I think this would give me enough versatility to do everything I need. 我認爲這會給我足夠的多功能性來做我需要的一切。 It could be achieved with includes but then I would need a top and a bottom include for each wrapper, which is kind of messy. 它可以通過includes實現,但是我需要爲每個包裝器提供頂部和底部包含,這有點混亂。


#1樓

參考:https://stackoom.com/question/5RD1/JSP技巧使模板更容易


#2樓

Use tiles . 使用瓷磚 It saved my life. 它救了我的命。

But if you can't, there's the include tag , making it similar to php. 但如果你不能,那就是include標籤 ,使它類似於php。

The body tag might not actually do what you need it to, unless you have super simple content. 除非你有超級簡單的內容,否則body標籤可能實際上並不是你需要的。 The body tag is used to define the body of a specified element. body標籤用於定義指定元素的主體。 Take a look at this example : 看看這個例子

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

You specify the element name, any attributes that element might have ("lang" in this case), and then the text that goes in it--the body. 您可以指定元素名稱,元素可能具有的任何屬性(在本例中爲“lang”),然後指定其中的文本 - 正文。 So if 因此,如果

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

Then the output would be 那麼輸出就是

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

#3樓

I made quite easy, Django style JSP Template inheritance tag library. 我做了相當簡單的Django樣式JSP模板繼承標記庫。 https://github.com/kwon37xi/jsp-template-inheritance https://github.com/kwon37xi/jsp-template-inheritance

I think it make easy to manage layouts without learning curve. 我認爲無需學習曲線就可以輕鬆管理佈局。

example code : 示例代碼:

base.jsp : layout base.jsp:佈局

<%@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 : contents view.jsp:內容

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

#4樓

Based on the same basic idea as in @Will Hartung 's answer, here is my magic one-tag extensible template engine. 基於與@Will Hartung的回答相同的基本思想,這是我的魔術單標籤可擴展模板引擎。 It even includes documentation and an example :-) 它甚至包括文檔和示例:-)

WEB-INF/tags/block.tag: WEB-INF /標籤/ 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);
    }
%>

#5樓

As skaffman suggested , JSP 2.0 Tag Files are the bee's knees. 正如Skaffman所說JSP 2.0標記文件是蜜蜂的膝蓋。

Let's take your simple example. 讓我們舉一個簡單的例子。

Put the following in WEB-INF/tags/wrapper.tag 將以下內容放在WEB-INF/tags/wrapper.tag

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

Now in your example.jsp page: 現在在你的example.jsp頁面中:

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

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

That does exactly what you think it does. 這完全符合你的想法。


So, lets expand upon that to something a bit more general. 所以,讓我們把它擴展到更一般的東西。 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>

To use this: 要使用它:

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

What does that buy you? 這會給你帶來什麼? A lot really, but it gets even better... 很多,但它變得更好......


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>

To use this: (assume we have a user variable in the request) 要使用它:(假設我們在請求中有一個用戶變量)

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

But it turns you like to use that user detail block in other places. 但它讓你想在其他地方使用那個用戶細節塊。 So, we'll refactor it. 所以,我們將重構它。 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/>

Now the previous example becomes: 現在前面的例子變成了:

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

The beauty of JSP Tag files is that it lets you basically tag generic markup and then refactor it to your heart's content. JSP標記文件的優點在於它允許您基本標記通用標記,然後將其重構爲您的內容。

JSP Tag Files have pretty much usurped things like Tiles etc., at least for me. JSP Tag Files有很多篡改像Tiles等的東西,至少對我而言。 I find them much easier to use as the only structure is what you give it, nothing preconceived. 我發現它們更容易使用,因爲唯一的結構是你給它的,沒有任何先入爲主。 Plus you can use JSP tag files for other things (like the user detail fragment above). 另外,您可以將JSP標記文件用於其他內容(例如上面的用戶詳細信息片段)。

Here's an example that is similar to DisplayTag that I've done, but this is all done with Tag Files (and the Stripes framework, that's the s: tags..). 這是一個類似於我已經完成的DisplayTag的示例,但這都是使用Tag Files(以及Stripes框架,即s:tags ...)完成的。 This results in a table of rows, alternating colors, page navigation, etc: 這會產生一個行表,交替顏色,頁面導航等:

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

Of course the tags work with the JSTL tags (like c:if , etc.). 當然,標籤使用JSTL tags (如c:if等)。 The only thing you can't do within the body of a tag file tag is add Java scriptlet code, but this isn't as much of a limitation as you might think. 在標記文件標記的主體中唯一不能做的就是添加Java scriptlet代碼,但這並不像你想象的那麼多。 If I need scriptlet stuff, I just put the logic in to a tag and drop the tag in. Easy. 如果我需要scriptlet的東西,我只需將邏輯放入標籤並將標籤放入。容易。

So, tag files can be pretty much whatever you want them to be. 因此,標記文件可以是您想要的任何內容。 At the most basic level, it's simple cut and paste refactoring. 在最基本的層面上,它是簡單的剪切和粘貼重構。 Grab a chunk of layout, cut it out, do some simple parameterization, and replace it with a tag invocation. 抓取一大塊佈局,將其剪切掉,進行一些簡單的參數化,然後用標籤調用替換它。

At a higher level, you can do sophisticated things like this table tag I have here. 在更高的層次上,你可以做一些複雜的事情,比如我在這裏的這個表格標籤。


#6樓

I know this answer is coming years after the fact and there is already a great JSP answer by Will Hartung, but there is Facelets, they are even mentioned in the answers from the linked question in the original question. 我知道這個答案是在事實發生多年之後,Will Hartung已經有了很好的JSP答案,但是有Facelets,它們甚至在原始問題中的鏈接問題的答案中被提及。

Facelets SO tag description Facelets SO標籤描述

Facelets is an XML-based view technology for the JavaServer Faces framework. Facelets是JavaServer Faces框架的基於XML的視圖技術。 Designed specifically for JSF, Facelets is intended to be a simpler and more powerful alternative to JSP-based views. Facelets專爲JSF設計,旨在成爲基於JSP的視圖的更簡單,更強大的替代方案。 Initially a separate project, the technology was standardized as part of JSF 2.0 and Java-EE 6 and has deprecated JSP. 最初是一個單獨的項目,該技術被標準化爲JSF 2.0和Java-EE 6的一部分,並且已經棄用了JSP。 Almost all JSF 2.0 targeted component libraries do not support JSP anymore, but only Facelets. 幾乎所有JSF 2.0目標組件庫都不再支持JSP,而只支持Facelets。

Sadly the best plain tutorial description I found was on Wikipedia and not a tutorial site. 遺憾的是,我發現最好的簡單教程描述是在維基百科上,而不是教程網站。 In fact the section describing templates even does along the lines of what the original question was asking for. 事實上,描述模板的部分甚至與原始問題所要求的一致。

Due to the fact that Java-EE 6 has deprecated JSP I would recommend going with Facelets despite the fact that it looks like there might be more required for little to no gain over JSP. 由於Java-EE 6已棄用JSP,我建議使用Facelets,儘管事實上看起來可能需要更多,而不是通過JSP獲得。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章