在我的网站中,我有一个主 JSP 模板:
<html>
<body>
<nav>...</nav>
<tiles:insertAttribute name="body" />
<footer>...</footer>
</body>
</html>
以及多个页面模板:
<p>This is content</p>
现在我希望页面模板能够定义一些Javascript和CSS包含,因此页面模板必须在主模板的
<head>
之前执行。
在 PHP 中,我可以为此使用输出缓冲:
<? ob_start()
include $slave;
$body = ob_get_clean(); ?>
<html>
<head>
<? foreach($javascripts as $script) ?>
<script src="<?=$script?>" />
<? endforeach ?>
<body>
<nav>...</nav>
<?=$body?>
<footer>...</footer>
</body>
</html>
JSP中有类似的技术吗?或者还有另一种方式来实现我所需要的? 我在 Spring MVC 3 + Apache Tiles 中使用它
1) 启用核心标签库
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
2) 抓取并打印内容
<c:set var="content">You grab content</c:set>
<c:out value="${content}" />
您可以在图块定义中定义一个附加属性(默认为空),然后将该属性插入布局页面的标题部分。这就是 Tiles 应该如何工作的。
或者您可以使用 Sitemesh 而不是 Tiles,它会执行您的建议:它使用一个缓冲响应的过滤器,然后通过提取其一些元素并将它们放入模板中来装饰响应。
我想可以同时使用 Sitemesh 和 Tiles,但恕我直言,它会变得有点太复杂了。
我找到了解决问题的另一种解决方案。
我扩展了我的主模板:
<head>
<tiles:insertAttribute name="head" defaultValue="" />
</head>
我有一个生成图块定义 XML 文件的脚本(已经有了)。如果子模板(例如
view.jsp
)需要额外的 CSS 或 Javascript,我将创建一个单独的文件 view_head.jsp
,其中包含正确的包含内容,并且脚本会将属性 head
设置到该文件。
实际上还有另一种方法可以使用自定义 JspWriter 实现来实现此目的:
// Replace the default output by a buffered output
JspWriter out_default = out;
JspWriterStringBuffer out_buffer = new JspWriterStringBuffer();
out = out_buffer;
// all sub-templates which use "out" will now write to the custom buffer.
// call your custom code, include templates, whatever... here
<%@ include file="sample.jsp" %>
// restore the default output
out = out_default;
JspWriterStringBuffer需要重写相当多的默认函数,但最终实现非常简单。只需将所有内容写入类变量并添加 getter 即可:
import java.io.IOException;
import javax.servlet.jsp.JspWriter;
/**
* Purpose of this class is to implement a dummy JspWriter that simply
* writes added information to a class variable
* which can be queried using getBuffer().
*/
public class JspWriterStringBuffer extends JspWriter {
String buffer = "";
public JspWriterStringBuffer() {
// Note: the chosen buffer size in this example is just random
super(12345678, false);
}
public String getBuffer() {
return buffer;
}
@Override
public int getRemaining() {
return bufferSize - buffer.length();
}
@Override
public void clear() {
buffer = "";
}
@Override
public void clearBuffer() {
buffer = "";
}
@Override
public void close() {
}
@Override
public void flush() {
}
@Override
public void print(Object x) {
buffer += x.toString();
}
@Override
public void println(Object x) {
print(x);
println();
}
@Override
public void print(String x) {
buffer += x;
}
@Override
public void println(String x) {
print(x);
println();
}
@Override
public void print(char x) {
buffer += x;
}
@Override
public void println(char x) {
print(x);
println();
}
@Override
public void print(char[] x) {
buffer += x;
}
@Override
public void println(char[] x) {
print(x);
println();
}
@Override
public void print(double x) {
buffer += x;
}
@Override
public void println(double x) {
print(x);
println();
}
@Override
public void print(float x) {
buffer += x;
}
@Override
public void println(float x) {
print(x);
println();
}
@Override
public void print(long x) {
buffer += x;
}
@Override
public void println(long x) {
print(x);
println();
}
@Override
public void print(int x) {
buffer += x;
}
@Override
public void println(int x) {
print(x);
println();
}
@Override
public void print(boolean x) {
buffer += Boolean.toString(x);
}
@Override
public void println(boolean x) {
print(x);
println();
}
@Override
public void println() {
buffer += System.lineSeparator();
}
@Override
public void newLine() {
println();
}
@Override
public void write(char[] chars, int i, int i1) throws IOException {
for (int j = i; j <= i1; j++) {
print(chars[j]);
}
}
}