ChatGPT解决这个技术问题 Extra ChatGPT

使模板更容易的 JSP 技巧?

在工作中,我的任务是将一堆 HTML 文件转换为一个简单的 JSP 项目。它实际上都是静态的,没有要编程的服务器端逻辑。我应该提到我对 Java 完全陌生。 JSP 文件似乎可以很容易地使用常见的包含和变量,很像 PHP,但我想知道一种简单的方法来获得模板继承(Django 样式)之类的东西,或者至少能够拥有包含页眉和页脚的 base.jsp 文件,因此我可以稍后插入内容。

Ben Lings 似乎在他的回答中提供了一些希望:JSP template inheritance有人可以解释如何实现这一目标吗?

鉴于我没有太多时间,我认为动态路由有点多,所以我很高兴将 URL 直接映射到 .jsp 文件,但我愿意接受建议。

谢谢。

编辑:我不想使用任何外部库,因为这会增加我自己和从事该项目的其他人的学习曲线,而我工作的公司已签约执行此操作。

另一个修改:我不确定 JSP tags 是否有用,因为我的内容实际上没有任何模板变量。我需要的是一种能够做到这一点的方法:

base.html:

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

somepage.html

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

输出为:

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

我认为这会给我足够的多功能性来做我需要的一切。它可以通过 includes 来实现,但是我需要为每个包装器添加一个顶部和底部,这有点混乱。


C
Community

作为 skaffman suggestedJSP 2.0 标记文件 是蜜蜂的膝盖。

让我们举个简单的例子。

将以下内容放入 WEB-INF/tags/wrapper.tag

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

现在在您的 example.jsp 页面中:

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

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

这正是你认为的那样。

因此,让我们将其扩展到更一般的东西。 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>

要使用这个:

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

那给你买什么?真的很多,但它变得更好......

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>

要使用它:(假设我们在请求中有一个用户变量)

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

但它使您喜欢在其他地方使用该用户详细信息块。所以,我们将对其进行重构。 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/>

现在前面的例子变成了:

<%@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 标记文件的美妙之处在于它允许您基本上标记通用标记,然后将其重构为您喜欢的内容。

JSP Tag Files 几乎篡夺了 Tiles 之类的东西,至少对我来说是这样。我发现它们更容易使用,因为唯一的结构是你给它的,没有先入为主的。另外,您可以将 JSP 标记文件用于其他事情(例如上面的用户详细信息片段)。

这是一个类似于我所做的 DisplayTag 的示例,但这都是使用标记文件(以及 Stripes 框架,即 s: 标记..)完成的。这会产生一个行表、交替颜色、页面导航等:

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

当然,这些标签与 JSTL tags 一起使用(如 c:if 等)。在标记文件标记的正文中唯一不能做的事情是添加 Java scriptlet 代码,但这并没有您想象的那么大的限制。如果我需要 scriptlet 的东西,我只需将逻辑放入标签中并将标签放入。简单。

所以,标签文件几乎可以是你想要的任何东西。在最基本的层面上,它是简单的剪切和粘贴重构。抓取一大块布局,剪掉它,做一些简单的参数化,然后用标签调用替换它。

在更高的层次上,你可以做一些复杂的事情,比如我在这里的这个表格标签。


谢谢你。这是我能找到的关于 JSP 标记文件的最佳教程,这对来自 JSF 的我来说非常棒。希望我能投超过一票。
+4000万。感谢您对它的解释比我发现的任何蹩脚教程都要好 50,000 倍。来自 Rails 世界并且缺少 ERB,这正是我所需要的。你应该写博客。
真的很不错的教程。您能与我们分享您制作的表格标签的代码吗?我前一段时间自己创建了一个,但你的方法更好。
如果你创建一个标签文件标签,JSP 文件中该标签的内容不能有scriptlet 代码: no scriptlet code here 。但是在实现标签本身的标签文件中,它可以包含您想要的所有 scriptlet 代码,就像任何 JSP 一样。
注意 - 似乎标签的顺序很重要; jsp:attribute 必须在 jsp:body 之前,否则会出错。我还必须设置一个相应的 @attribute 标记来匹配 jsp:invoke 以避免另一个错误。使用 GlassFish 3.2.2
K
KwonNam

我制作了相当简单的 Django 风格的 JSP 模板继承标签库。 https://github.com/kwon37xi/jsp-template-inheritance

我认为无需学习曲线即可轻松管理布局。

示例代码:

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 : 内容

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

C
Community

基于与 @Will Hartung 的答案相同的基本思想,这是我的神奇单标签可扩展模板引擎。它甚至包括文档和示例 :-)

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);
    }
%>

g
geowa4

使用 tiles。它救了我的命。

但如果你不能,还有 include tag,使它类似于 php。

除非您有超级简单的内容,否则 body 标签可能实际上并不能满足您的需要。 body 标签用于定义指定元素的主体。看看 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>

您指定元素名称、该元素可能具有的任何属性(在本例中为“lang”),然后是其中的文本——正文。因此,如果

content.headerName = h1,

content.lang = fr,和

content.body = 法语标题

那么输出将是

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

S
Sandeep Amarnath

这也可以通过 jsp:include 来实现。 Chad Darby 在此视频中很好地解释了 https://www.youtube.com/watch?v=EWbYj0qoNHo


F
Fildor

添加依赖项以供使用 <%@tag description="User Page template" 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>

F
Fering

我知道这个答案是在事实发生几年后出现的,并且 Will Hartung 已经有一个很棒的 JSP 答案,但是有 Facelets,它们甚至在原始问题的链接问题的答案中被提及。

Facelets SO 标记说明

Facelets 是一种用于 JavaServer Faces 框架的基于 XML 的视图技术。专为 JSF 设计的 Facelets 旨在成为基于 JSP 的视图的更简单和更强大的替代方案。最初是一个单独的项目,该技术被标准化为 JSF 2.0 和 Java-EE 6 的一部分,并且已弃用 JSP。几乎所有面向 JSF 2.0 的组件库都不再支持 JSP,只有 Facelets。

遗憾的是,我发现的最简单的教程描述是在 Wikipedia 上,而不是教程网站。事实上,描述 templates 的部分甚至按照原始问题的要求进行。

由于 Java-EE 6 已经弃用了 JSP,我建议使用 Facelets,尽管看起来可能需要更多的东西而对 JSP 几乎没有任何好处。


Java EE 6 没有弃用 JSP,只是弃用了使用 JSP 作为 JSF 的视图技术。
@Ryan因为在这种情况下两者都在谈论视图技术,所以说它已弃用它有什么问题?
这个问题与JSF无关。它是关于纯 JSP 的。您的答案是使用适用于 JSF 的 Facelets。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅