Читать «Java 7 (Наиболее полное руководство)» онлайн - страница 438

Ильдар Шаукатович Хабибуллин

<tag>

<name>head</name>

<tag-class>sdotags.HeadTag</tag-class>

<body-content>JSP</body-content>

<attribute>

<name>size</name>

<required>false</required> <rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

Этот тег реализован классом HeadTag, описанным в листинге 27.7.

Листинг 27.7. Пользовательский тег с простым телом

package sdotags;

import javax.servlet.jsp.*; import j avax.servlet.jsp.tagext.*;

public class HeadTag extends TagSupport{

private String size = "4";

public String getSize(){ return size;

}

public void setSize(String size){ this.size = size;

}

public int doStartTag(){ try{

JspWriter out = pageContext.getOut(); out.print("<font size=\"" + size + "\">"); }catch(Exception e){

System.err.println(e);

}

return EVAL_BODY_INCLUDE;

}

public int doEndTag(){ try{

JspWriter out = pageContext.getOut(); out.print("</font>");

}catch(Exception e){

System.err.println(e);

}

return EVAL_PAGE;

}

}

После этого на странице JSP можно писать пользовательский тег

<sdo:head size = "2" >

Сегодня <jsp:expression>new java.util.Date()</jsp:expression>

</sdo:head>

Текст, написанный в его теле, будет выведен у клиента шрифтом указанного размера.

Обработка тела пользовательского тега

Если тело пользовательского тега требует обработки, то его класс-обработчик должен реализовать интерфейс BodyTag или расширить класс BodyTagSupport. Метод dostartTag ( ) должен вернуть значение eval_body_buffered. После завершения метода dostartTag(), если тело тега не пусто, контейнер вызовет метод doInitBody(), который может выполнить предварительные действия перед обработкой содержимого тела пользовательского тега. Далее контейнер обратится к методу doAfterBody(), в котором и надо проделать обработку тела тега, поскольку к этому моменту тело тега будет прочитано и занесено в объект класса BodyContent.

Класс BodyContent расширяет класс JspWriter, значит, формально является выходным потоком. Однако его удобнее рассматривать как хранилище информации, полученной из тела тега.

Объект класса BodyContent создается после каждой итерации метода doAfterBody( ), и все эти объекты хранятся в стеке.

Ссылку на объект класса BodyContent можно получить двумя способами: методом

public BodyContent getBodyContent();

класса BodyTagSupport или, используя объект pageContext, следующим образом:

BodyContent bc = pageContext.pushBody();

Содержимое тела тега можно прочитать из объекта класса BodyContent тоже двумя способами: или получить ссылку на символьный входной поток методом

public Reader getReader();

или представить содержимое объекта в виде строки методом

public String getString();

После обработки прочитанного содержимого его надо отправить в выходной поток out методом

public void writeOut(Writer out);

Выходной поток out, аргумент этого метода, выводит информацию в стек объектов класса BodyContent. Поэтому его можно получить двумя способами: методом

public JspWriter getPreviousOut();

класса BodyTagSupport или методом