1

I want to define a template using a JspFragment. That's why I created the following Tag class:

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

The above class simply stores the JspFragment (which corresponds to its body) in a "global" registry. Next, I created a Tag, which evaluates a previously stored template and writes it to the page:

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

The registry is a very simple implementation:

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

As you can see, the registry evaluates the appropriate JspFragment each time the evaluate method is called.

The JSP code I used follows:

...

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

This works quite well, but I'm not sure whether or not this is allowed? Is there a better approach?

4

1 回答 1

0

我不确定你所说的允许是什么意思。如果它对你有用,那很好。它似乎与 <%@include file="yourfile" %> 提供给您的功能非常相似。我认为您的方法的优点是您可以将模板片段与其余代码保持在同一页面上。然而,根据文件的大小,这可能很快成为一个缺点。

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

于 2011-09-17T06:15:53.237 回答