在定义它的标记之外使用JSP-Fragments

时间:2011-09-14 14:06:56

标签: java jsp java-ee jsp-tags jsp-fragments

我想使用JspFragment定义模板。这就是我创建以下Tag类的原因:

public class CreateTemplateTag extends SimpleTagSupport {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void setJspBody(JspFragment jspBody) {
        // Reqister "body" in Template-Registry to use it later on ..
        TemplateRegistry.put(getJspContext(), name, jspBody);
    }
}

上面的类只是将JspFragment(对应于它的主体)存储在“全局”注册表中。 接下来,我创建了一个Tag,它评估以前存储的模板并将其写入页面:

public class UseTemplateTag extends SimpleTagSupport {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void doTag() throws JspException, IOException {
        JspContext ctx = getJspContext();
        ctx.getOut().write(TemplateRegistry.evaluate(ctx, name));
    }
}

注册表是一个非常简单的实现:

public class TemplateRegistry {
    private static final String REGISTRY_KEY = "__TPL_REG__";

    public static void put(JspContext ctx, String name, JspFragment frag) {
        HashMap attribute = (HashMap) ctx.getAttribute(REGISTRY_KEY);
        if(attribute==null) {
            attribute = new HashMap();
            ctx.setAttribute(REGISTRY_KEY,attribute);
        }
        attribute.put(name, frag);
    }

    public static String evaluate(JspContext ctx, String name) {
        HashMap attribute = (HashMap) ctx.getAttribute(REGISTRY_KEY);
        if(attribute!=null) {
            try {
                JspFragment frag = (JspFragment) attribute.get(name);
                StringWriter writer = new StringWriter();
                StringBuffer sb = writer.getBuffer();
                frag.invoke(writer);
                writer.flush();
                return sb.toString();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

如您所见,每次调用evaluate方法时,注册表都会评估相应的JspFragment。

我使用的JSP代码如下:

...

<util:CreateTemplate name="xxx">
 <custom:myTag attr="${var}"/>
 This is ${var}
</util:CreateTemplate>

...

<c:forEach var="var" items="${someStringCollection}">
 <util:UseTemplate name="xxx"/>
</c:forEach>

这很有效,但我不确定这是否允许? 有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

我不确定你的意思是什么。如果它适合你,那很好。它似乎与&lt;%@ include file =“yourfile”%&gt;给出的功能非常相似。我认为您的方法的优点是您可以将模板片段保留在与其余代码相同的页面上。根据文件的大小,这很快就会成为一个缺点。

惯用语企业java会说你应该有很多较小的文件,所以拿这些小模板并为它们制作一个小的包含文件。如果它们各自都是2-3行,那么你最好按自己的方式行事。如果它们增长到20-30行,则可能更容易将它们移动到自己的文件中,这样您就可以更轻松地查看核心页面逻辑,而不会被所有模板包含的注意力分散。