Recently I've decided to get some knowledge about writing custom tags. And there is a problem.

In my web app I use some JSTL tags and in every JSP page I have got an identical piece of code:

<c:if test="${sessionScope.locale == 'locale_ru_RU' or empty sessionScope.locale}" >
    <fmt:setBundle basename="locale_ru_RU" />
</c:if>
<c:if test="${sessionScope.locale == 'locale_en_US'}">
    <fmt:setBundle basename="locale_en_US" />
</c:if>

As you can see this construction sets correct resource bundle.

So I'd like to know if there is possibility to wrap up this piece of code and use instead of it a single tag (I know there is another way - just put this code in the individual JSP page and use <%@ include %> directive, but I'd like to try a tag)?

As I understand I should someway set body content (inside tag class, not from JSP) and make container to execute it, but I cannot find any examples about it.

What I have got now:

tld:

<?xml version="1.0" encoding="UTF-8"?>
<taglib   xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
 version="2.0">
<tlib-version>1.0</tlib-version>
<tag>
    <name>setLocale</name>
    <tag-class>com.test.tags.LocaleBundleTag</tag-class>
    <body-content>empty</body-content>
</tag>
</taglib>

and my tag:

public class LocaleBundleTag extends BodyTagSupport {

@Override
public void setBodyContent(BodyContent b) {

    try {
        b.clear();
        b.append("<c:if test=\"${sessionScope.locale == 'locale_ru_RU' or empty sessionScope.locale}\" >");
        b.append("<fmt:setBundle basename=\"locale_ru_RU\" />");
        b.append("</c:if>");
        b.append("<c:if test=\"${sessionScope.locale == 'locale_en_US'}\">");
        b.append("<fmt:setBundle basename=\"locale_en_US\" />");
        b.append("</c:if>");
    } catch (IOException e) {
    }

    super.setBodyContent(b);
}
}

It compiles, but does nothing correctly.

有帮助吗?

解决方案

No, that won't work, because there's no expectation that the body content will then also be processed by the JSP compiler. Rather you would need to implement the fmt:setBundle yourself within your tag.

A JSP Tag file would be easier. Operationally it's not that far removed from the include you mentioned, but it makes refactorings like this really trivial.

I have an extended example here: JSP tricks to make templating easier?

其他提示

You can't use other JSP tags inside a custom tag (ie. one created in a Java class) like that. However, you can create a 'tag file' which allows you to define a custom tag pretty much as you would define a JSP page. Here's a link to get you started: http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSPTags5.html.

However, what you're trying to do looks like something that something else should be able to do for you. Do you use Spring in your app? If so consider looking at Spring's MessageSource and LocaleResolver.

The best way to tackle this would be using a servlet filter. A filter can intercept every request and set attributes in request scope. The java equivalent of the fmt:bundle tag is something like:

Config.set(request, Config.FMT_LOCALE, "ru_RU")
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top