在工作中,我的任务是将一堆HTML文件转换成一个简单的JSP项目。它完全是静态的,没有服务器端逻辑来编程。我应该提一下,我对Java完全不熟悉。JSP文件似乎可以很容易地使用常见的include和变量,就像PHP一样,但我想知道一个简单的方法来获得像模板继承(Django风格)这样的东西,或者至少能够有一个包含页眉和页脚的base.jsp文件,这样我就可以稍后插入内容。
Ben Lings似乎在他的回答中提供了一些希望:
JSP模板继承
有人能解释一下如何做到这一点吗?
鉴于我没有太多时间,我认为动态路由有点多,所以我很乐意让url直接映射到.jsp文件,但我愿意听取建议。
谢谢。
编辑:我不想使用任何外部库,因为这将增加我自己和其他参与项目的人的学习曲线,而我工作的公司已经签订了这样做的合同。
另一个编辑:我不确定JSP标记是否有用,因为我的内容实际上没有任何模板变量。我需要的是一种能够做到这一点的方法:
base.html:
<html><body>
{ content.body }
</body></html>
somepage.html
<wrapper:base.html>
<h1>Welcome</h1>
</wrapper>
输出为:
<html><body>
<h1>Welcome</h1>
</body></html>
我想这会给我足够多的功能去做我需要的一切。它可以通过包含来实现,但然后我需要为每个包装器设置一个顶部和底部包含,这有点混乱。
我做了一个很简单的,Django风格的JSP模板继承标记库。
https://github.com/kwon37xi/jsp-template-inheritance
我认为它可以很容易地管理布局,没有学习曲线。
示例代码:
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>
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>
基于与@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);
}
%>
我做了一个很简单的,Django风格的JSP模板继承标记库。
https://github.com/kwon37xi/jsp-template-inheritance
我认为它可以很容易地管理布局,没有学习曲线。
示例代码:
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>
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>