суббота, 18 июня 2011 г.

Создание функций в библиотеках тегов

В дескрипторе библиотеки тегов можно кроме тегов определять функции которые потом можно использовать. Вот пример фрагмента такго дескптора:
............
<function>
 <description>Converts the string to all caps</description>
        <name>caps</name>
 <function-class>jsp2.examples.el.Functions</function-class>
 <function-signature>java.lang.String caps( java.lang.String )</function-signature>
    </function>
............


Как видно тут определяется имя, путь к классу с реализацией функции, и указывается для контейнера, какого типа переменные она принимает и какого типа значения из нее ожидать.
Функция реализуется в классе просто -- этот класс должен иметь публичный статический метод с таким именем, как мы определили функции, и соответсвовать <function-signature>

public class Functions {
    .....
    public static String caps( String text ) {
        return text.toUpperCase();
    }
    .....
}

И кстати наши функции могут вызываться из EL(Expression Language)
Для полноты примера определим еще и тег, который будет создавать динамическую переменную контекста. Допустим он будет описываться в том же дескрипторе, что и наша функция.
<tag>
  <description>Populates the page context with a BookBean</description>
  <name>findBook</name>
  <tag-class>jsp2.examples.simpletag.FindBookSimpleTag</tag-class>
  <body-content>empty</body-content>
  <attribute>
    <name>var</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
  </attribute>
</tag>
Этот тег rtexprvalue(RUN-TIME EXPRESSION VALUE) определяет может ли значение атрибута определяться в момент выполнения(а не в момент трансляции в ява-код страницы) -- тоесть может ли на его месте значения использоваться выражение. Хоть у нас и сторит тру, можно смело ставить и фолс, потому что в данном примере мы определяем этот атрибут обычным строковым значением.
Еще стоит обратить внимание на то(ниже будет видно), что тег порождает переменную контекста, но при этом tei-class не определяет ее, в первую очередь это потому что на ися этой переменной может меняться по мере испльзования библиотеки, и определить его заранее в библиотеке мы не можем
А вот определяющий тег класс:
package jsp2.examples.simpletag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.util.HashMap;
import jsp2.examples.BookBean;

/**
 * SimpleTag handler that pretends to search for a book, and stores
 * the result in a scoped variable.
 */
public class FindBookSimpleTag extends SimpleTagSupport {
    private String var;
    
    private static final String BOOK_TITLE = "The Lord of the Rings";
    private static final String BOOK_AUTHOR = "J. R. R. Tolkein";
    private static final String BOOK_ISBN = "0618002251";

    public void doTag() throws JspException {
        BookBean book = new BookBean( BOOK_TITLE, BOOK_AUTHOR, BOOK_ISBN );
        getJspContext().setAttribute( this.var, book );
    }

    public void setVar( String var ) {
 this.var = var;
    }
}

А вот пример использования:
<my:findBook var="book"/>
    <table border="1">
        <thead>
     <td><b>Field</b></td>
     <td><b>Value</b></td>
     <td><b>Capitalized</b></td>
 </thead>
 <tr>
     <td>Title</td>
     <td>${book.title}</td>
     <td>${my:caps(book.title)}</td>
 </tr>
 <tr>
     <td>Author</td>
     <td>${book.author}</td>
     <td>${my:caps(book.author)}</td>
 </tr>
 <tr>
     <td>ISBN</td>
     <td>${book.isbn}</td>
     <td>${my:caps(book.isbn)}</td>
 </tr>
    </table>

Как видно из примера переменная контекста используется после вызова тега findBook прямо в EL, также в EL используется функция, которую мы определили в начале.

Комментариев нет:

Отправить комментарий