在定义 JSP 片段的标记之外使用 JSP 片段

发布于 2024-12-04 19:32:48 字数 2328 浏览 4 评论 0原文

我想使用 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(对应于其主体)存储在“全局”注册表中。 接下来,我创建了一个标签,它评估先前存储的模板并将其写入页面:

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

如您所见,每次调用评估方法时,注册表都会评估适当的 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>

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

勿忘心安 2024-12-11 19:32:48

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

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

I'm not sure what you mean by allowed. If it works for you it's fine. It seems very similar to the functionality given to you by <%@include file="yourfile" %>. I think the advantage to your approach is that you can keep the template snippets on the same page as the rest of the code. Depending on the size of the files, this can quickly become a disadvantage however.

Idiomatic enterprise java would say you should have lots of smaller files, so take each of those little templates and make a small include file for them. If they are all 2-3 lines each, you're better off doing it your way. If they grow to be 20-30 lines, it will probably easier to move them into their own files so you can more easily see the core page logic without being distracted by all the template includes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文