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. Цей атрибут буде булевого типу, значення true якого означає, що тіло тега буде відображено на сторінці, при значенні false тіло тега буде ігноруватися.

Ще один важливий момент в описі - значення 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 тег з динамічними атрибутами

Напишіть перше повідомлення!

Ви повинні увійти під своїм аккаунтом щоб залишати коментарі