JSTL тег и EVAL_BODY_AGAIN

июня
13
2012

Содержание

В этой статье будет рассказано о работе с телом пользовательского JSTL-тега: игнорирования тела, включения тела по условию и дублирования тела в нужном количестве.

Перейдем сразу к практике. Рассмотрим одновременно два варианта: игнорирования тела тега и включения тела по условию.

Создадим xml-файл с описанием тега customIf (файл /WEB-INF/customIfTag.tld):


<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" 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 web-jsptaglibrary_2_1.xsd">
	<tlib-version>1.0</tlib-version>
	<short-name>seostella</short-name>
	<uri>/WEB-INF/customIf</uri>
	<tag>
		<name>customIf</name>
		<tag-class>com.seostella.jstl.CustomIf</tag-class>
		<body-content>scriptless</body-content>
		<info>customIf tag displayes body if displayBody attribute is setted to true</info>
        <attribute>
            <name>displayBody</name>
            <required>true</required>
            <description>if statement</description>
            <rtexprvalue>false</rtexprvalue>
        </attribute>		
	</tag>
</taglib>

Как видно из описания, тег будет иметь один обязательный атрибут displayBody. Этот атрибут будет булевого типа, истинное значение которого означает, что тело тега будет отображено на странице, при ложном значении тело тега будет игнорироваться.

Еще один важный момент в описании - значение scriptless тега body-content. Возможные значения этого тега:

Если атрибут body-content не объявлен, то по умолчанию используется значение scriptless.

Код класса, обрабатывающего тег customIf, представлен ниже:


package com.seostella.jstl;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class CustomIf extends TagSupport{
	private static final long serialVersionUID = 1L;
	
	private boolean displayBody = false;
	
	public void setDisplayBody(boolean displayBody) {
		this.displayBody = displayBody;
	}
    
	@Override
        public int doStartTag() throws JspException {
		if( displayBody ){
			return EVAL_BODY_INCLUDE;
		}
		return SKIP_BODY;
    }
}

Как видно из листинга, если значение атрибута displayBody истинно, то функцией doStartTag() возвращаем значение EVAL_BODY_INCLUDE, что означает отображение тела тега на странице. Если атрибут displayBody имеет ложное значение, то метод doStartTag() возвращает значение SKIP_BODY, что, в свою очередь, означает, что тело тега не будет отображаться на странице.

Пример использования тега:


<%@ taglib uri="/WEB-INF/customIfTag.tld" prefix="seostella"%>
<%@ page session="false" pageEncoding="UTF-8"%>
<html>
<head>
<title>CustomIf Tag</title>
</head>
<body>
	<h1>CustomIf Tag</h1>

	<seostella:customIf displayBody="false">
		<p>CustomIf tag body</p>
	</seostella:customIf>

	<ul>
		<li><a href="${pageContext.request.contextPath}/" title="Home">Home</a></li>
	</ul>
</body>
</html>

Теперь перейдем к вопросу о дублировании тела тега в нужном количестве. Объявите тег repeatBody следующим образом:


<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" 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 web-jsptaglibrary_2_1.xsd">
	<tlib-version>1.0</tlib-version>
	<short-name>seostella</short-name>
	<uri>/WEB-INF/repeatBody</uri>
	<tag>
		<name>repeatBody</name>
		<tag-class>com.seostella.jstl.RepeatBody</tag-class>
		<body-content>scriptless</body-content>
		<info>repeatBody tag displayes body repeatCount times</info>
        <attribute>
            <name>repeatCount</name>
            <required>true</required>
            <description>repeat count</description>
            <rtexprvalue>false</rtexprvalue>
        </attribute>
	</tag>
</taglib>

Тег будет содержать лишь один обязательный атрибут repeatCount, с помощью которого будет определяться, сколько раз тело тега отобразится на странице.

Класс RepeatBody, который отвечает за обработку тега:


package com.seostella.jstl;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class RepeatBody extends TagSupport {
	private static final long serialVersionUID = 1L;

	private int i;
	private int repeatCount;

	public void setRepeatCount(int repeatCount) {
		this.repeatCount = repeatCount;
	}

	@Override
	public int doStartTag() throws JspException {
		i = 0;
		if( repeatCount <= 0 ){
			return SKIP_BODY;
		}
		i++;
		return EVAL_BODY_INCLUDE;
	}

	public int doAfterBody() throws JspException {
		while (i < repeatCount) {
			i++;
			return EVAL_BODY_AGAIN;
		}
		return SKIP_BODY;
	}
}

В предыдущем примере было показано как игнорировать тело тега или включать его на странице. В методе doStartTag() проверяется значение атрибута repeatCount и если это значение меньше или равняется нулю, то тело тега игнорируется, иначе - добавляется на страницу, при этом счетчик отображений i увеличивается на единицу.

С помощью метода doAfterBody() производится дублирование тела тега. Если метод возвращает значение EVAL_BODY_AGAIN, то метод doAfterBody() будет повторно вызван. Если возвращается значение SKIP_BODY - выполнение метода прекращается.

Пример использования тега:


<%@ taglib uri="/WEB-INF/repeatBodyTag.tld" prefix="seostella"%>
<%@ page session="false" pageEncoding="UTF-8"%>
<html>
<head>
<title>RepeatBody Tag</title>
</head>
<body>
	<h1>RepeatBody Tag</h1>

	<seostella:repeatBody repeatCount="3">
		<p>RepeatBody tag body</p>
	</seostella:repeatBody>

	<ul>
		<li><a href="${pageContext.request.contextPath}/" title="Home">Home</a></li>
	</ul>
</body>
</html>

< Как создать JSTL тег с динамическими атрибутами

Напишите первое сообщение!

Вы должны войти под своим аккаунтом чтобы оставлять комментарии