Использование JSP-фрагментов вне тега, в котором он был определен - PullRequest
1 голос
/ 14 сентября 2011

Я хочу определить шаблон, используя 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>

Это работает довольно хорошо, но я не уверен,не это разрешено?Есть ли лучший подход?

1 Ответ

0 голосов
/ 17 сентября 2011

Я не уверен, что вы подразумеваете под разрешенным.Если это работает для вас, это нормально.Это похоже на функциональность, предоставленную вам <% @ include file = "yourfile"%>.Я думаю, что преимущество вашего подхода состоит в том, что вы можете хранить фрагменты шаблона на той же странице, что и остальная часть кода.Однако, в зависимости от размера файлов, это может быстро стать недостатком.

Идиоматическая корпоративная java сказала бы, что у вас должно быть много файлов меньшего размера, поэтому возьмите каждый из этих маленьких шаблонов и сделайте для них небольшой включаемый файл,Если они все по 2-3 строки, вам лучше делать это по-своему.Если они вырастут до 20-30 строк, вероятно, будет легче переместить их в свои собственные файлы, чтобы вы могли легче видеть логику основной страницы, не отвлекаясь на все шаблоны, включенные в шаблон.

...