[an error occurred while processing this directive] IT • archiv :: Print

IT • archiv


[an error occurred while processing this directive]

[an error occurred while processing this directive]

Создание пользовательских библиотек JSP тегов

[an error occurred while processing this directive](none) [an error occurred while processing this directive](none)[an error occurred while processing this directive] ::
[an error occurred while processing this directive](none)
[an error occurred while processing this directive]([an error occurred while processing this directive](none)[an error occurred while processing this directive])

[an error occurred while processing this directive](none) JSP 1.1 предоставляет крайне важную способность: определять собственные JSP теги. Вы определяете тег, его атрибуты и его тело. Затем теги группируются в коллекции, называемые tag libraries (библиотеки тегов), которые могут затем использоваться в JSP файлах. Таким образом, возможность определять библиотеки тегов позволяют Java разработчикам сложное поведение серверной стороны приводить к простым и легко используемым элементом, которые могут легко включать разработчиками в JSP страницы.

Пользовательские теги выполняют некоторые из задач, исполняемых “бинами”: инкапсулирование сложного поведения в простые и доступные формы. Однако между “бинами” и тегами существуют отличия. Во-первых, “бины” не могут манипулировать содержимым JSP, в то время как теги могут. Во-вторых, при использовании тегов сложные операции могут быть упрощены. В-третьих, теги не требуют много работы для их создания. В-четвертых, “бины” часто определяются в одном сервлете и затем используются в других сервлетах или JSP страницах, тогда как теги обычно определяют более изолированное поведение. В конце концов, теги доступны только в JSP1.1, в то время как “бины” доступны и в JSP 1.0.

В то время как эта статья готовилась к печати, не было официального релиза Tomcat 3.0, собственно поддерживающего теги, поэтому в этой главе примеры используют бета – версию Tomcat 3.1. В Tomcat 3.1 немного другая структура директорий. Разница в используемой структуре директорий приведена в табл. 1.

Таблица 1. Структура директорий Tomcat.

 

Tomcat 3.0

Tomcat 3.1

Расположение скриптов startup и shutdown install_dir install_dir/bin
Стандартная директория верхнего уровня для сервлетов и классов поддержки install_dir/webpages/ WEB-INF/classes install_dir/webapps/ ROOT/WEB-INF/classes
Стандартная директория верхнего уровня для HTML и JSP файлов install_dir/webpages install_dir/webapps/ROOT
  1. Компоненты, которые составляют Библиотеку тега (Tag Library).
  2. Для того, что использовать пользовательские JSP теги, необходимо определить три отдельных компонента: класс обработчик, который определяет поведение тега, файл-описатель библиотеки тега, который устанавливает соответствие имен элементов XML с реализациями тегов, и JSP файл, который использует библиотеку тегов. Далее в этом главе дается общее представление каждого из этих компонентов. В следующих главах будет детально объясняться, как строить эти компоненты для тегов различных стилей.

    Класс обработчик (The Tag Handler Class).

    Во время определения нового тега, первая задача – определить Java класс, который расскажет системе, что нужно делать при обнаружении тега. Этот класс должен реализовать javax.servlet.jsp.tegext.Tag. Это обычно выполняется при расширении класса TagSupport или BodyTagSupport. В примере 1 показан пример простого тега, который вставляет в JSPстраницу, которая использует тег, “Custom tag example (coreservlets.tags.ExampleTag)”. Не нужно заботиться о понимании точного поведения этого класса; это станет ясно из следующего раздела. При использовании Tomcat 3.1 файл класса должен находиться в install_dir/webapps/ROOT/WEB-INF/ classes/coreservlets/tags/ExampleTag.class.

    Пример 1 ExampleTag.java

    Package coreservlets.tags;
    
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import java.io.*;
    
    /** Очень простой JSPтег, который добавляет строку
     * (“Custom tag example ...”) на выход.
     * Действительное имя тега здесь не определяется
     * оно дается файлом описателя библиотеки тегов (Tag Library
     * Descriptor TLD), на который ссылается директива taglib в JSP
     * файле. */
    
    public class ExampleTag extends TagSupport {
      puplic int doStartTag() {
        try {
           JspWriter out = pageContext.getOut();
           Out.print(“Custom tag example “
                   + “(coreservlets.tags.ExmpleTag)”);
        } catch (IOException ioe) {
          System.out.println(“Error in ExampleTag: “ + ioe);
        }
        return(SKIP_BODY);
      }
    }
    
    

    Файл – описатель библиотеки тега (The Tag Library Descriptor File).

    После определения класса – обработчика, вторая задача – отождествить класс с сервером и связать его с определенным именем XML тега. Эта задача выполняется посредством файла – описателя библиотеки тега (в XML формате) подобно тому, как показано в примере 2. Этот файл содержит некоторую фиксированную информацию, произвольное короткое имя для библиотеки, короткое описание и последовательность описаний тега. Невыделенный текст в примере – одинаковый фактически для всех дескрипторов библиотек тегов и может быть скопирован дословно из источника кода http://www.core servlets.com из примеров Tomcat 3.1 (install_dir/webapps/ example/WEB-INF/jsp).

    Формат описаний тега будет объяснен позднее. Элемент tag определяет основное имя тега (реальный индекс тега) и идентифицирует класс, который управляет тегом. Так как класс обработчик тега находится в пакете coreservlets.tags, используется имя класса coreservlets.tags.ExampleTag. Заметим, что это имя класса, а не URL или относительный путь. Класс может быть инсталлирован в любое место на сервере, на котором могут находиться “бины” или классы поддержки. При использовании Tomcat 3.1 ExampleTag будет находиться в install_dir/webapps/ROOT /WEB-INF/classes/corese rvlets/tags. Хорошая идея складывать Ваши сервлет классы в пакеты, но Tomcat 3.1 имеет особенность – обработчики тегов должны находиться в пакетах.

    Пример 2 csajsp-taglib.tld

    <?xml version=”1.0” encoding=”ISO-8859-1” ?>
    <!DOCTYPE taglib
     PUBLIC “-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN”
    http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd>
    
    <!—a tag library descriptor -->
    
    <taglib>
      <!— after this the default space is
    http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd
      -->
    
      <tlibversion>1.0</tlibversion>
      <jspversion>1.1</jspversion>
    <shortname>csajsp</shortname>
      <urn></urn>
    <info>
         a tag library from Core Servlets and JavaServer Pages,
    http://www.coreservlets.com/.
      </info>
    
    <tag>
         <name>example</name>
         <tagclass>coreservlets.tags.ExampleTag</tagclass>
         <info>Simplest example: insert into line of output</info>
         <bodycontent>EMPTY</bodycontent>
      </tag>
      <!—Other tags definrf later ... -->
    
    </taglib>
    
    

    JSP файл

    Имея реализацию обработчика тега и описание библиотеки тега, Вы можете написать JSPфайл, который будет использовать тег. В примере 3 дается пример. Перед использованием тега необходимо использовать директиву taglib. Эта директива имеет следующую форму

    <%@ taglib uri=”...” prefix=”...” %>

    Требуемый атрибут uri может быть абсолютной либо относительной URL ссылкой на файл-описатель библиотеки тега, подобный тому, который приведен в примере 2. Однако Tomcat 3.1 может использовать файл web.xml, который устанавливает соответствие между абсолютным URL для описателя библиотеки тега с локальным файлом. Не рекомендуется использовать этот подход, но следует знать об этом в случае, когда встретитесь с Apache примерами и удивитесь тому, что работает, когда определен несуществующий URL для атрибута uri директивы taglib.

    Атрибут prefix определяет префикс, который будут использоваться перед именем тега, определенного описателем библиотеки тега. Например, если TLD файл определяет имя тега tag1 и атрибут prefix имеет имя test, то действительное имя тега будет test:tag1. Этот тег может быть использован любым из следующих двух способов:

    <test:tag1>
    Arbitrary JSP
    </test:tag1>
    
    

    или

    <test:tag1 />
    
    

    Для иллюстрации: файл-описатель в примере 2 называется csajsp-taglib.tld и постоянно хранится в той же самой директории, что и JSP файл в примере 3. Таким образом, директива taglib в JSP файле использует простой относительный URL, задающий имя файла:

    <%@ taglib uri=”csajsp-taglib.tld” prefix “csajsp” %>
    
    

    Более того, так как атрибут prefix есть csajsp (для Core Servlets и Java Server Page), далее в JSP странице используется csajsp:example для ссылки на тег example, определенный в файле дескрипторе.

    На рисунке 1 показан результат.

    Рисунок 1. Результат SimpleExample.jsp.

    Пример 3. SimpleExample.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
    <TITLE><csajsp:example /></TITLE>
    <LINK REL=STYLESHEET HREF="JSP-Styles.css"
    TYPE="text/css">
    </HEAD>
    <BODY>
    <H1><csajsp:example /></H1>
    <csajsp:example />
    </BODY>
    </HTML>
    
    
  3. Определение элементарного тега.

В этой главе дается детальное определение простых тегов без атрибутов и не содержащих тело; то есть тегов в форме <prefix:tagname />.

Класс обработчик (The Tag Handler Class).

Теги, которые либо не имеют тела, либо имеют пустое тело, должны реализовывать класс TagSupport. Это встроенный класс в javax.servlet.jsp.tagext пакет, который исполняет Tag интерфейс и содержит стандартную функциональность, необходимую для простых тегов. Из-за того, что будет необходимо использовать другие классы, теги должны импортировать javax.servlet.jsp и java.io. Большинство реализаций тегов обычно содержат следующие предложения import после определения пакета:

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;

Рекомендуется скачать пример с http://www.core servlets.com/ и использовать его как начало для собственных реализаций. Для тега без атрибутов или тела необходимо переопределить метод doStartTag, который определяет код, который вызывается во время запроса при обнаружении начального элемента. Для генерации вывода, следует получить JspWriter из поля PageContext с помощью getOut. В дополнение к методу getOut поле pageContext (или тип pageContext) имеет методы для получения других структур данных, связанных с запросом. Наиболее важные: getRequest, getResponse, getServletContext, getSession. Так как метод print JspWtiter вызывает исключения IOException, то предложение print необходимо использовать в блоке try/catch. Для уведомления клиента о других типах ошибок можно определить, что doStartTag вызывает JspException исключение, и затем выбрасывать его, когда произойдет ошибка. Если тег не имеет тела, метод doStartTag должен вернуть константу SKIP_BODY. Эта инструкция системе игнорировать любое содержание между началом и концом тега. Как будет рассказано в главе 5, использование SKIP_BODY иногда полезно даже в том случае, когда существует тело тега: разрабатываемый элементарный тег будет использоваться как автономный тег(<prefix:tagname />) и, таким образом, не имеет содержания тела.

Пример 4 показывает реализацию тега, которая использует этот подход для генерации случайного 50-разрядного простого числа посредством использования класса Prime, разработанного ранее.

Пример 4. SimplePrimeTag.java

package coreservlets.tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import java.math.*;
import coreservlets.*;

public class SimplePrimeTag extends TagSupport
{
  protected int len = 50;
  public int doStartTag()
  {
    try
    {
     JspWriter out = pageContext.getOut();
       BigInteger prime = Primes.nextPrime(Primes.random(len));
     out.print(prime);
    } catch(IOException ioe)
    {
      System.out.println("Error generating prime: " + ioe);
    }
  return(SKIP_BODY);
  }
}

Файл – описатель библиотеки тегов

Общий формат файла-описателя – почти всегда один и тот же: он будет содержать идентификатор версии XML, декларацию DOCTYPE, контейнерный элемент taglib. Для начала можно скачать пример с http://www.core servlets.com/. Важно понять, что находится в элементе taglib: элемент tag. Для тегов без атрибутов, элемент tag должен содержать четыре элемента между <tag> и </tag>:

  1. name, определяет базовое имя тега, к которому будет присоединяться префикс директивы taglib. Пример:
  2. <name>simplePrime</name>

    для связи с базовым тегом simplePrime.

  3. tagclass, полное имя класса – обработчика. Например,
  4. <tagclass>coreservlets.tags.SimplePrimeTag</tagclass>

  5. info, короткое описание. Пример,
  6. <info>Outputs a random 50-digit prime.</info>

  7. bodycontent, должно иметь значение EMPTY для тегов без тела. Теги с нормальным телом, которые должны быть интерпретированы как нормальные JSP, должны иметь значение JSP, и редкие теги, чьи обработчики сами обрабатывают тело, используют значение TAGDEPENDENT. Пример:

<bodycontent>EMPTY</bodycontent>.

Пример 5. Полный TLD файл: csajsp-taglib.tld

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
  "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<!-- a tag library descriptor -->

<taglib>
  <!-- after this the default space is
  "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
  -->
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <shortname>csajsp</shortname>
  <urn></urn>
  <info>
    A tag library from Core Servlets and JavaServer Pages,
    http://www.coreservlets.com/.
  </info>
  <!-- Other tags defined earlier... -->
<tag>
    <name>simplePrime</name>
    <tagclass>coreservlets.tags.SimplePrimeTag</tagclass>
    <info>Outputs a random 50-digit prime.</info>
    <bodycontent>EMPTY</bodycontent>
  </tag>

</taglib>

JSP файл

JSP документы, которые используют пользовательские теги, должны использовать директиву taglib, имеющую атрибут uri, который задает положение файла TLB, и атрибут prefix, определяющий короткую строку, которая будет присоединена (через двоеточие) к основному имени тега. Пример 6 показывает документ, который использует

<%@ taglib uri=”csajsp-taglib.tld” prefix “csajsp” %>

для использования TLD файла, полностью показанного в примере 5, со значением префикса csajsp.

На рисунке 2 показан результат.

Рисунок 2. Результат SimplePrimeExample.jsp.

Пример 6. SimplePrimeExample.jsp.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Some 50-Digit Primes</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>
<BODY>
<H1>Some 50-Digit Primes</H1>
<%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>

<UL>
   <LI><csajsp:simplePrime />
   <LI><csajsp:simplePrime />
   <LI><csajsp:simplePrime />
   <LI><csajsp:simplePrime />
</UL>

</BODY>
</HTML>

  1. Связывание атрибутов с тегами.
  2. Теги, подобные <prefix:name attribute1=”value1” attribute2=”value2” ... /> добавляют значительную гибкость библиотеки тегов. Эта глава объясняет, как добавлять поддержку атрибутов для тегов.

    Класс обработчик (The Tag Handler Class).

    Использование атрибута, называемого attribute1, просто приводит к вызову метода, называемого setAttribute1 в классе, который реализует TagSupport(или, другими словами, реализует Tag интерфейс). Значение атрибута передается в метод как String. Следовательно, добавление поддержки атрибута по имени attribute1 - просто реализация следующего метода:

    Public void setAttribute1(String value1) {
            doSomethingWith(value1)
    }
    
    

    Заметим, что атрибут attributeName(маленькая а) соответствует методу setAttributeName(большая А).

    Одна из наиболее общих вещей, что должен сделать обработчик атрибута – сохранять атрибут для позднего использования в методе doStartTag или подобных методах. Например:

    private String message = “Default message”;
    
    public void setMessage(String message) {
       this.message = message;
    }
    
    

    Если обработчик тега будет доступен из других классов, то хорошая идея – сделать метод getAttributeName в дополнение к методу setAttributeName. Однако требуется только setAttributeName.

    Пример 7 показывает подкласс класса SimplePrimeTag, который добавляет поддержку атрибута length. Когда такой атрибут передается, то это приводит к вызову setLength, который преобразовывает входную переменную String в int и сохраняет в переменную len, которая используется в методе doStartTag родительского класса.

    Пример 7. PrimeTag.java.

    package coreservlets.tags;
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import java.io.*;
    import java.math.*;
    import coreservlets.*;
    
    public class PrimeTag extends SimplePrimeTag {
     public void setLength(String length) {
         try {
               len = Integer.parseInt(length);
         } catch(NumberFormatException nfe) {
               len = 50;
         }
       }
    }
    
    

    Файл – описатель библиотеки тега Атрибуты тега должны быть описаны внутри элемента tag посредством элемента attribute. Элемент attribute имеет три вложенных элемента, которые появляются между <attribute> и <attribute/>.

    1. name, обязательный элемент, который определяет имя атрибута (чувствителен к регистру).
    2. required, обязательный элемент, который определяет всегда ли атрибут должен быть (true) или опционально (false). Если пропустить атрибут, то метод setAttributeName не вызовется, поэтому необходимо предусмотреть значение по умолчанию.
    3. rtexprvalue, необязательный атрибут, который показывает может ли значение атрибута быть подобно JSPрасширению <%= expression %>. Значение по умолчанию false, так что обычно этот элемент пропускается за исключением случаев, когда Вы хотите позволить атрибутам иметь значение, определяемое в момент запроса.

    Пример 8 показывает пример элемента tag внутри tld файла.

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <!DOCTYPE taglib
      PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
      "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
    
    <!-- a tag library descriptor -->
    <taglib>
      <!-- after this the default space is
           "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
    -->
    
      <tlibversion>1.0</tlibversion>
      <jspversion>1.1</jspversion>
      <shortname>csajsp</shortname>
      <urn></urn>
      <info>
       A tag library from Core Servlets and JavaServer Pages,
       http://www.coreservlets.com/.
      </info>
    
      <!-- Other tag defined earlier... -->
    <tag>
        <name>prime</name>
        <tagclass>coreservlets.tags.PrimeTag</tagclass>
        <info>Outputs a random N-digit prime.</info>
        <bodycontent>EMPTY</bodycontent>
        <attribute>
           <name>length</name>
           <required>false</required>
        </attribute>
      </tag>
    
    </taglib>
    
    

    JSP файл

    В примере 9 показан JSPдокумент, который использует директиву taglib для того, чтобы считать tld файл и определить префикс csajsp. Так как тег prime определен для разрешения атрибута length, пример 9 использует <csajsp:prime length="xxx" />

    Необходимо запомнить, что пользовательские теги придерживаются XML синтаксиса, который требует значение атрибута length, заключенное либо в одинарные, либо в двойные кавычки. Так как атрибут length не обязателен, то допускается <csajsp:prime />

    В таком случае обработчик будет использовать значение по умолчанию.

    Рисунок 3 показывает результат действия примера 9.

    Рисунок 3. Результат PrimeExample.jsp.

    Пример 9 primeExample.jsp.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE>Some N-Digit Primes</TITLE>
    <LINK REL=STYLESHEET
          HREF="JSP-Styles.css"
          TYPE="text/css">
    </HEAD>
    
    <BODY>
    <H1>Some N-Digit Primes</H1>
    <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
    
    <UL>
      <LI>20-digit: <csajsp:prime length="20" />
      <LI>40-digit: <csajsp:prime length="40" />
      <LI>80-digit: <csajsp:prime length="80" />
      <LI>Default (50-digit): <csajsp:prime />
    </UL>
    
    </BODY>
    </HTML>
    
    
    1. Включение тела тега.
    2. До текущего момента все пользовательские теги игнорировали тело тега и, таким образом, использовались как автономные теги <prefix:tagname />.

      В этой главе будет показано, как определять теги, которые используют содержание их тела <prefix:tagname>body</prefix:tagname>

      Класс обработчик (The Tag Handler Class).

      В предыдущих примерах обработчики определяли метод doStartTag, который возвращал SKIP_BODY. Для сообщения системе об использовании тела метод doStartTag должен возвращать EVAL_BODY_INCLUDE. Тело может содержать элементы сценария JSP, директивы, действия. JSPконструкции переводятся в сервлет-код во время трансляции страницы и этот код вызывается во время запроса. При использовании тела тега необходимо выполнить определенные действия после тела. Для определения этих действий используйте метод doEndTag. Для продолжения выполнения страницы после окончания тега doEndTag должен возвращать EVAL_PAGE. Если нужно прервать процесс, то необходимо вернуть SKIP_PAGE.

      Пример 10 представляет тег для заголовочного элемента, который является более гибким, чем элементы H1 – H6 в стандартном HTML. Этот новый элемент предоставляет размер шрифта, список имен шрифтов, цвет элемента, цвет фона, рамку и выравнивание. Для элементов HTML доступно только свойство выравнивания. Заголовок реализуется через использование одноячеечной таблицы, включающей в себя элемент SPAN, который имеет встроенные атрибуты диаграммы стилей. Метод doStartTag генерирует начальные теги TABLE и SPAN и возвращает EVAL_BODY_INCLUDE для того, чтобы сказать системе, что нужно включить тело тега. Метод doEndTag генерирует теги </SPAN> и </TABLE>, затем возвращает EVAL_PAGE, чтобы продолжить обработку страницы. Различные методы setAttributeName используются для управления атрибутами, подобными bgColor и fontSize.

      Пример 10 HeadingTag.java

      package coreservlets.tags;
      import javax.servlet.jsp.*;
      import javax.servlet.jsp.tagext.*;
      import java.io.*;
      /** Generates an HTML heading with the specified background
      * color, foreground color, alignment, font, and font size.
      * You can also turn on a border around it, which normally
      * just barely encloses the heading, but which can also
      * stretch wider. All attributes except the background
      * color are optional.
      */
      
      public class HeadingTag extends TagSupport {
         private String bgColor; // The one required attribute
         private String color = null;
         private String align="CENTER";
         private String fontSize="36";
         private String fontList="Arial, Helvetica, sans-serif";
         private String border="0";
         private String width=null;
      
         public void setBgColor(String bgColor)
        {
             this.bgColor = bgColor;
        }
      
        public void setColor(String color)
        {
             this.color = color;
        }
      
        public void setAlign(String align)
        {
            this.align = align;
        }
      
        public void setFontSize(String fontSize)
        {
            this.fontSize = fontSize;
        }
      
       public void setFontList(String fontList)
       {
         this.fontList = fontList;
       }
      
       public void setBorder(String border)
       {
         this.border = border;
       }
      
       public void setWidth(String width)
       {
         this.width = width;
       }
      public int doStartTag()
       {
         try {
           JspWriter out = pageContext.getOut();
           out.print("<TABLE BORDER=" + border +
           " BGCOLOR=\"" + bgColor + "\"" +
           " ALIGN=\"" + align + "\"");
           if (width != null) {
           out.print(" WIDTH=\"" + width + "\"");
         }
         out.print("><TR><TH>");
         out.print("<SPAN STYLE=\"" +
         "font-size: " + fontSize + "px; " +
         "font-family: " + fontList + "; ");
         if (color != null) {
            out.println("color: " + color + ";");
         }
         out.print("\"> "); // End of <SPAN ...>
       } catch(IOException ioe) {
         System.out.println("Error in HeadingTag: " + ioe);
       }
      return(EVAL_BODY_INCLUDE); // Include tag body
      }
      
      public int doEndTag() {
      try {
        JspWriter out = pageContext.getOut();
        out.print("</SPAN></TABLE>");
      } catch(IOException ioe) {
        System.out.println("Error in HeadingTag: " + ioe);
      }
      return(EVAL_PAGE); // Continue with rest of JSP page
      }
      }
      
      

      Файл – описатель библиотеки тега

      Для тегов, которые используют содержание тела, добавляется одна новая характеристика: элемент bodycontenet, который должен содержать значение JSP: <bodycontent>JSP</bodycontent >

      Элементы name, tagclass и attribute используются обычным образом, как описывалось ранее. Пример 11 представляет код.

      Пример 11. csajsp-taglib.tld

      <?xml version="1.0" encoding="ISO-8859-1" ?>
      <!DOCTYPE taglib
      PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
      "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
      <!-- a tag library descriptor -->
      <taglib>
      <!-- after this the default space is
      "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
      -->
      <tlibversion>1.0</tlibversion>
      <jspversion>1.1</jspversion>
      <shortname>csajsp</shortname>
      <urn></urn>
      <info>
      A tag library from Core Servlets and JavaServer Pages,
      http://www.coreservlets.com/.
      </info>
      <!-- Other tags defined earlier... -->
      <tag>
      <name>heading</name>
      <tagclass>coreservlets.tags.HeadingTag</tagclass>
      <info>Outputs a 1-cell table used as a heading.</info>
      <bodycontent>JSP</bodycontent>
      <attribute>
      <name>bgColor</name>
      <required>true</required> <!-- bgColor is required -->
      </attribute>
      <attribute>
      <name>color</name>
      <required>false</required>
      </attribute>
      <attribute>
      <name>align</name>
      <required>false</required>
      </attribute>
      <attribute>
      <name>fontSize</name>
      <required>false</required>
      </attribute>
      <attribute>
      <name>fontList</name>
      <required>false</required>
      </attribute>
      <attribute>
      <name>border</name>
      <required>false</required>
      </attribute>
      <attribute>
      <name>width</name>
      <required>false</required>
      </attribute>
      </tag>
      </taglib>
      
      

      JSP файл

      В примере 12 показан документ, который использует точно определенный заголовочный тег. Так как атрибут bgColor обязателен, то любое использование тега включает его. На рисунке 4 приведен результат.

      Пример 12. HeadingExample.jsp.

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
      <HTML>
      <HEAD>
      <TITLE>Some Tag-Generated Headings</TITLE>
      </HEAD>
      
      <BODY>
      <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
      
      <csajsp:heading bgColor="#C0C0C0">
      Default Heading
      </csajsp:heading>
      
      <P>
      <csajsp:heading bgColor="BLACK" color="WHITE">
      White on Black Heading
      </csajsp:heading>
      <P>
      <csajsp:heading bgColor="#EF8429" fontSize="60" border="5">
      Large Bordered Heading
      </csajsp:heading>
      <P>
      <csajsp:heading bgColor="CYAN" width="100%">
      Heading with Full-Width Background
      </csajsp:heading>
      <P>
      <csajsp:heading bgColor="CYAN" fontSize="60"
                      fontList="Brush Script MT, Times, serif">
      Heading with Non-Standard Font
      </csajsp:heading>
      <P>
      </BODY>
      </HTML>
      
      

      Рисунок 4.

    3. Опциональное включение тела тега.
    4. Большинство тегов либо никогда не используют тело, либо всегда это делают. В этой главе рассказывается о том, как информацию запроса можно использовать для решения будет или нет включаться тело тега.

      Класс обработчик (The Tag Handler Class). Тривиальный пример опционального включения тела тега: возврат EVAL_BODY_INCLUDE или SKIP_BODY в зависимости от значения запроса. Важная вещь, которую необходимо знать, как обнаружить информацию запроса, так как doStartTag не имеет аргументов HttpServletRequest и HttpServletResponse для выполнения service, _jspService, doGet, doPost. Решение этой дилеммы в использовании getRequest для получения HttpServletRequest из автоматически определенного поля pageContext для TagSupport. Строго говоря, возвращаемый тип getRequest – есть ServletRequest, так что этот тип необходимо привести к HttpServletRequest, если необходимо использовать метод, которого нет у ServletRequest. Однако в этом случае можно использовать getParameter, так что не требуется приведение типов. Пример 13 определяет тег, который игнорирует его тело, пока не будет представлен параметр debug в запросе. Такой тег обеспечивает полезную способность, посредством которой Вы можете выводить информацию об отладке прямо в JSP страницу во время разработке, но активизируется она, только когда возникают проблемы.

      Пример 13. sDebugTag.java

      package coreservlets.tags;
      import javax.servlet.jsp.*;
      import javax.servlet.jsp.tagext.*;
      import java.io.*;
      import javax.servlet.*;
      
      /** A tag that includes the body content only if
      * the "debug" request parameter is set.
      */
      
      public class DebugTag extends TagSupport {
          public int doStartTag() {
            ServletRequest request = pageContext.getRequest();
            String debugFlag = request.getParameter("debug");
            if ((debugFlag != null) &&
              (!debugFlag.equalsIgnoreCase("false")))
              {
                return(EVAL_BODY_INCLUDE);
              } else
              {
              return(SKIP_BODY);
              }
          }
      }
      
      

      Файл – описатель библиотеки тега Если тег всегда использует тело, необходимо, чтобы внутри элемента bodycontent было значение JSP. С другой стороны, все элементы внутри элемента tag используются тем же самым способом, как описывалось ранее. Пример 14 показывает содержание, необходимо для DebugTag.

      Пример 14. csajsp-taglib.tld

      <?xml version="1.0" encoding="ISO-8859-1" ?>
      <!DOCTYPE taglib
        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
        "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
      
      <!-- a tag library descriptor -->
      <taglib>
        <!-- after this the default space is
             "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
        -->
      
        <tlibversion>1.0</tlibversion>
        <jspversion>1.1</jspversion>
        <shortname>csajsp</shortname>
        <urn></urn>
        <info>
          A tag library from Core Servlets and JavaServer Pages,
          http://www.coreservlets.com/.
        </info>
      
        <!-- Other tags defined earlier... -->
      <tag>
          <name>debug</name>
          <tagclass>coreservlets.tags.DebugTag</tagclass>
          <info>Includes body only if debug param is set.</info>
          <bodycontent>JSP</bodycontent>
        </tag>
      
      </taglib>
      
      

      JSP файл

      В примере 15 показана страница, которая включает информацию об отладке между <csajsp:debug> и </csajsp:debug>. Рисунки 5 и 6 показывают нормальный результат и результат, когда представлен параметр debug.

      Пример 15. DebugExample.jsp.

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
      <HTML>
      <HEAD>
      <TITLE>Using the Debug Tag</TITLE>
      <LINK REL=STYLESHEET
          HREF="JSP-Styles.css"
          TYPE="text/css">
      </HEAD>
      
      <BODY>
      <H1>Using the Debug Tag</H1>
      <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
      
      Top of regular page. Blah, blah, blah. Yadda, yadda, yadda.
      <P>
      <csajsp:debug>
      <B>Debug:</B>
      <UL>
        <LI>Current time: <%= new java.util.Date() %>
        <LI>Requesting hostname: <%= request.getRemoteHost() %>
        <LI>Session ID: <%= session.getId() %>
      </UL>
      </csajsp:debug>
      
      <P>
      Bottom of regular page. Blah, blah, blah. Yadda, yadda, yadda.
      
      </BODY>
      </HTML>
      
      

      Рисунок 5. Тело элемента csajsp:debug игнорируется.

      Рисунок 6. Тело элемента csajsp:debug включается, когда есть параметр запроса debug.

    5. Манипулирование телом тега.

    Элемент csajsp:prime (глава 3) игнорирует любое содержимое тела, элемент csajsp:heading (глава 4) использует содержимое тела, элемент csajsp:debug (глава 5) игнорирует или использует тело в зависимости от параметра запроса. Общая идея этих элементов – тело тега никогда не модифицируется. В этой главе показано, как обрабатывать тело тега.

    Класс обработчик (The Tag Handler Class).

    До текущего момента все обработчики тега реализовывали класс TagSupport. Хороший стандартный метод – реализовать Tag интерфейс и выполнить ряд операций, как то: запоминание ссылки PageContext в поле pageContext. Однако TagSupport недостаточно мощный для манипулирования содержимым тела тега, и поэтому для этого необходимо использовать BodyTagSupport. BodyTagSupport расширяет TagSupport, поэтому методы doStartTag и doEndTag используются точно также. BodyTagSupport определяет два важных метода:

    1. doAfterBody – метод, который необходимо переопределить для управления манипуляциями телом тега. Этот метод возвращает SKIP_BODY.
    2. getBodyContent – метод, который возвращает объект типа BodyContent, который инкапсулирует информацию о теле тега.

    Класс BodyContent имеет три важных метода:

    1. getEnclosingWriter – возвращает JspWriter, который используется doStartTag и doEndTag
    2. getReader – возвращает Reader, который может читать тело тега
    3. getString – возвращает String, содержащую целостное тело тега

    Пример 16 представляет реализацию тега, который предоставляет функциональность фильтрации для JSP тега.

    Пример 16. FilterTag.java

    package coreservlets.tags;
    
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import java.io.*;
    import coreservlets.*;
    
    /** A tag that replaces <, >, ", and & with their HTML
    * character entities (&lt;, &gt;, &quot;, and &amp;).
    * After filtering, arbitrary strings can be placed
    * in either the page body or in HTML attributes.
    */
    
    public class FilterTag extends BodyTagSupport
    {
       public int doAfterBody()
       {
       BodyContent body = getBodyContent();
         String filteredBody =
           ServletUtilities.filter(body.getString());
         try
         {
           JspWriter out = body.getEnclosingWriter();
           out.print(filteredBody);
         } catch(IOException ioe)
         {
           System.out.println("Error in FilterTag: " + ioe);
         }
    // SKIP_BODY means I'm done. If I wanted to evaluate
    // and handle the body again, I'd return EVAL_BODY_TAG.
       return(SKIP_BODY);
       }
    }
    
    

    Файл – описатель библиотеки тега

    Теги, которые манипулируют содержанием тела, должны использовать элемент bodycontent точно также как и теги, которые просто включают его (тело): необходимо использовать значение JSP. С другой стороны, более в tld файле ничего нового не требуется. Пример в примере 17.

    Пример 17. csajsp-taglib.tld.

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <!DOCTYPE taglib
      PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
      "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
    
    <!-- a tag library descriptor -->
    
    <taglib>
      <!-- after this the default space is
        "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
      -->
    
      <tlibversion>1.0</tlibversion>
      <jspversion>1.1</jspversion>
      <shortname>csajsp</shortname>
      <urn></urn>
      <info>
         A tag library from Core Servlets and JavaServer Pages,
         http://www.coreservlets.com/.
      </info>
    
      <!-- Other tags defined earlier... -->
    <tag>
        <name>filter</name>
        <tagclass>coreservlets.tags.FilterTag</tagclass>
        <info>Replaces HTML-specific characters in body.</info>
        <bodycontent>JSP</bodycontent>
      </tag>
    
    </taglib>
    
    

    JSP файл

    В примере 18 показана страница, которая использует таблицу для того, чтобы показать некоторый образец HTML и его результат. Создание этой таблицы в нормальном HTML будет трудоемким процессом, так как в ячейках таблицы, которые показывают оригинальный HTML, должны быть заменены все символы <and> на &lt; и &gt;. Такие действия особенно затруднительны во время разработки, когда HTML текст часто меняется. Использование тега <csajsp:filter> значительно упрощает процесс, как показано в примере 18. На рисунке 7 показан результат.

    Пример 18. FilterExample.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE>HTML Logical Character Styles</TITLE>
    <LINK REL=STYLESHEET
          HREF="JSP-Styles.css"
          TYPE="text/css">
    </HEAD>
    
    <BODY>
    <H1>HTML Logical Character Styles</H1>
    Physical character styles (B, I, etc.) are rendered consistently
    in different browsers. Logical character styles, however,
    may be rendered differently by different browsers.
    Here's how your browser
    (<%= request.getHeader("User-Agent") %>)
    renders the HTML 4.0 logical character styles:
    <P>
    <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
    
    <TABLE BORDER=1 ALIGN="CENTER">
    <TR CLASS="COLORED"><TH>Example<TH>Result
    <TR>
    
    <TD><PRE><csajsp:filter>
    <EM>Some emphasized text.</EM><BR>
    <STRONG>Some strongly emphasized text.</STRONG><BR>
    <CODE>Some code.</CODE><BR>
    <SAMP>Some sample text.</SAMP><BR>
    <KBD>Some keyboard text.</KBD><BR>
    <DFN>A term being defined.</DFN><BR>
    <VAR>A variable.</VAR><BR>
    <CITE>A citation or reference.</CITE>
    </csajsp:filter></PRE>
    
    <TD>
    <EM>Some emphasized text.</EM><BR>
    <STRONG>Some strongly emphasized text.</STRONG><BR>
    <CODE>Some code.</CODE><BR>
    <SAMP>Some sample text.</SAMP><BR>
    <KBD>Some keyboard text.</KBD><BR>
    <DFN>A term being defined.</DFN><BR>
    <VAR>A variable.</VAR><BR>
    <CITE>A citation or reference.</CITE>
    
    </TABLE>
    </BODY>
    </HTML>
    
    

    Рисунок 7. Элемент csajsp:filter позволяет вставлять текст без заботы о том, содержит ли он специальные HTML символы.

    1. Многократное включение и манипулирование телом тега.
    2. Иногда может потребоваться многократная работа с телом тега. Способность поддерживать многократное включение тела тега позволяет определить ряд (множество) циклических тегов, которые повторяют JSPфрагменты различное число раз до тех пор, пока не выполнится некоторое условие. В этой главе показано, как делать такие теги.

      Класс обработчик (The Tag Handler Class).

      Теги, которые обрабатывают содержание тела несколько раз, должны происходить от BodyTagSupport и реализовывать doStartTag, doEndTag и, что наиболее важно, doAfterBody. Разница заключается в возвращаемой величине doAfterBody. Если этот метод возвращает EVAL_BODY_TAG, то это приводит к новому вызову doAfterBody. Этот процесс продолжается до тех пор, когда doAfterBody не вернет SKIP_BODY.

      Пример 19 определяет тег, который повторяет содержимое тела определенное количество раз, заданное атрибутом reps. Так как тело может содержать JSP, каждый повтор необязательно будет приводить к одному и тому же выводу информации клиенту.

      Пример 19. RepeatTag.java.

      package coreservlets.tags;
      
      import javax.servlet.jsp.*;
      import javax.servlet.jsp.tagext.*;
      import java.io.*;
      
      /** A tag that repeats the body the specified
      * number of times.
      */
      
      public class RepeatTag extends BodyTagSupport {
        private int reps;
      
        public void setReps(String repeats) {
          try {
             reps = Integer.parseInt(repeats);
          } catch(NumberFormatException nfe) {
             reps = 1;
          }
        }
      
        public int doAfterBody() {
          if (reps-- >= 1) {
            BodyContent body = getBodyContent();
            try {
              JspWriter out = body.getEnclosingWriter();
              out.println(body.getString());
              body.clearBody(); // Clear for next evaluation
            } catch(IOException ioe) {
              System.out.println("Error in RepeatTag: " + ioe);
            }
          return(EVAL_BODY_TAG);
          } else {
          return(SKIP_BODY);
          }
        }
      }
      
      

      Файл – описатель библиотеки тега

      В примере 20 показан TLD файл, который присваивает тегу имя <csajsp:repeat>. Для того, чтобы получать значения атрибута reps во время запроса, файл использует элемент rtexprvalue (включающий значение true) внутри элемента attribute.

      Пример 20. csajsp-taglib.tld

      <?xml version="1.0" encoding="ISO-8859-1" ?>
      <!DOCTYPE taglib
       PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
       "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
      
      <!-- a tag library descriptor -->
      
      <taglib>
        <!-- after this the default space is
            "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
        -->
      
        <tlibversion>1.0</tlibversion>
        <jspversion>1.1</jspversion>
        <shortname>csajsp</shortname>
        <urn></urn>
        <info>
          A tag library from Core Servlets and JavaServer Pages,
          http://www.coreservlets.com/.
        </info>
      
        <!-- Other tags defined earlier... -->
      
        <tag>
        <name>repeat</name>
        <tagclass>coreservlets.tags.RepeatTag</tagclass>
        <info>Repeats body the specified number of times.</info>
        <bodycontent>JSP</bodycontent>
        <attribute>
          <name>reps</name>
          <required>true</required>
          <!-- rtexprvalue indicates whether attribute
          can be a JSP expression. -->
        <rtexprvalue>true</rtexprvalue>
        </attribute>
        </tag>
      </taglib>
      
      

      JSP файл

      В примере 21 показан JSPдокумент, который создает нумерованный список простых чисел. Количество чисел в списке берется из параметра запроса repeats. На рисунке 8 показан результат.

      Пример 21. RepeatExample.jsp

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
      <HTML>
      <HEAD>
      <TITLE>Some 40-Digit Primes</TITLE>
      <LINK REL=STYLESHEET
            HREF="JSP-Styles.css"
            TYPE="text/css">
      </HEAD>
      
      <BODY>
      
      <H1>Some 40-Digit Primes</H1>
      Each entry in the following list is the first prime number
      higher than a randomly selected 40-digit number.
      <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
      
      <OL>
      <!-- Repeats N times. A null reps value means repeat once. -->
      <csajsp:repeat reps='<%= request.getParameter("repeats") %>'>
        <LI><csajsp:prime length="40" />
      </csajsp:repeat>
      </OL>
      
      </BODY>
      </HTML>
      
      

      Рисунок 8. Результат RepeatExample.jsp с параметром repeats = 20.

    3. Использование вложенных тегов.
    Несмотря на то, что в примере 21 элемент csajsp:prime помещен внутри элемента csajsp:repeat, эти два элемента друг от друга не зависят. Первый генерирует простое число независимо от того, где используется, а второй повторяет содержание независимо от того, содержится ли элемент csajsp:prime внутри. Однако некоторые теги зависят от вложений. Например, в стандартном HTML, элементы TD и TH могут находиться только внутри TR, который, в свою очередь, может быть только внутри элемента TABLE. Настройки цвета и выравнивания TABLE наследуются от TR, а значения TR влияют на поведение TH и TD. В этом случае вложенные элементы не могут действовать в изоляции. Точно также и tld файл использует ряд элементов: taglib, tag, attribute и required.

    В этой главе показывается, как определять теги, которые зависят от порядка вложенности, и как поведение определенных тегов зависит от значений, создаваемых более ранними тегами.

    Класс обработчик (The Tag Handler Class).

    Определения класса для вложенных тегов могут происходить либо от TagSupport, либо от BodyTagSupport, в зависимости от того, есть ли необходимость манипулировать телом тега или нет. Для вложенных тегов, однако, существуют новые важные характеристики. Во-первых, вложенные теги могут использовать findAncestorWithClass для поиска тега, в который они вложены. Этот метод принимает ссылку на текущий тег (т.е. this), аргументом является объект Class включающего класса (т.е. EnclosingTag.class). Если такого класса нет, то метод во вложенном классе может возбудить исключение JspTagException. Во-вторых, если тег хочет сохранить данные, которые позже будут использоваться, то необходимо поместить эти данные во включающий тег. Определение включающего тега должно обеспечить методы для хранения и доступа к этим данным. Пример 22 показывает такой подход.

    Пример 22. Шаблон вложенных тегов.

    public class OuterTag extends TagSupport
    {
       public void setSomeValue(SomeClass arg)
       { ... }
    
       public SomeClass getSomeValue()
       { ... }
    }
    
    public class FirstInnerTag extends BodyTagSupport
    {
      public int doStartTag() throws JspTagException
      {
        OuterTag parent =
         (OuterTag)findAncestorWithClass(this, OuterTag.class);
        if (parent == null)
        {
          throw new JspTagException("nesting error");
        } else
        {
          parent.setSomeValue(...);
        }
        return(EVAL_BODY_TAG);
      }
    ...
    }
    
    public class SecondInnerTag extends BodyTagSupport
    {
       public int doStartTag() throws JspTagException
       {
         OuterTag parent =
           (OuterTag)findAncestorWithClass(this, OuterTag.class);
         if (parent == null)
         {
            throw new JspTagException("nesting error");
         } else
         {
           SomeClass value = parent.getSomeValue();
           doSomethingWith(value);
         }
         return(EVAL_BODY_TAG);
       }
    ...
    }
    
    

    Теперь предположим, что мы хотим определить набор тегов, которые будут использоваться подобно следующему:

    <csajsp:if>
      <csajsp:condition><%= SomeExpression %></csajsp:condition>
      <csajsp:then>JSP to include if condition is true</csajsp:then>
      <csajsp:else>JSP to include if condition is false</csajsp:else>
    </csajsp:if>
    
    

    Для выполнения этой задачи первый шаг – определить класс IfTag для обработки тега csajsp:if. Этот обработчик будет иметь методы для определения и проверки верно или нет условие (setCondition и getCondition), методы для определения и проверки установлено ли условие явно (setHasCondition и getHasCondition), так как мы необходимо запретить теги csajsp:if, которые не содержат элемента csajsp:condition.

    Второй шаг – определить обработчик тега для csajsp:condition. Этот класс, называемый IfConditionTag, определяет метод doStartTag, который просто определяет, появляется ли тег внутри IfTag. Он возвращает EVAL_BODY_TAG, если появляется и вызывает исключение в противном случае. Метод doAfterBody отыскивает содержание тела (getBodyContent), преобразовывает его в строку (getString) и сравнивает с “true”. Этот подход означает, что определенное значение true может быть подставлено в JSPвыражение, подобное <%= expression %>, если в процессе начальной разработки есть необходимость выполнять часть then. Используя сравнение с “true” также означает, что любая другая величина может быть сравнима с “false”. Результат сравнение сохраняется во включающем теге с помощью метода setCondition IfTag. Код для IfTagCondition показан в примере 24.

    Третий шаг – определить класс для обработки тега csajsp:then. Метод doStartTag этого класса проверяет, что он находится внутри IfTag и, что условие точно установлено (то есть IfConditionTag есть внутри IfTag). Метод doAfterBody проверяет условие в классе IfTag и, если оно истинно, ищет содержание тела и печатает его. В примере 25 показан код.

    Последний шаг в определении обработчиков тега – определить класс для csajsp:else. Этот класс очень похож на обработчик части then тега, за исключением того, что этот обработчик только печатает тело из doAfterBody в случае, если условие из окружающего IfTag - ложно. Код приведен в примере 26.

    Пример 23. IfTag.java

    package coreservlets.tags;
    
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import java.io.*;
    import javax.servlet.*;
    
    /** A tag that acts like an if/then/else.
    */
    
    public class IfTag extends TagSupport
    {
       private boolean condition;
       private boolean hasCondition = false;
       public void setCondition(boolean condition)
       {
         this.condition = condition;
         hasCondition = true;
       }
    
       public boolean getCondition()
       {
          return(condition);
       }
    
       public void setHasCondition(boolean flag)
       {
          this.hasCondition = flag;
       }
    
    /** Has the condition field been explicitly set? */
    
       public boolean hasCondition()
       {
          return(hasCondition);
       }
    
       public int doStartTag()
       {
          return(EVAL_BODY_INCLUDE);
       }
    }
    
    

    Пример 24. IfConditionTag.java

    package coreservlets.tags;
    
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import java.io.*;
    import javax.servlet.*;
    
    /** The condition part of an if tag.
    */
    
    public class IfConditionTag extends BodyTagSupport
    {
       public int doStartTag() throws JspTagException
       {
       IfTag parent =
           (IfTag)findAncestorWithClass(this, IfTag.class);
         if (parent == null)
         {
            throw new JspTagException("condition not inside if");
         }
         return(EVAL_BODY_TAG);
       }
    
       public int doAfterBody()
       {
       IfTag parent =
           (IfTag)findAncestorWithClass(this, IfTag.class);
         String bodyString = getBodyContent().getString();
         if (bodyString.trim().equals("true"))
         {
           parent.setCondition(true);
         } else
         {
           parent.setCondition(false);
         }
         return(SKIP_BODY);
       }
    }
    
    

    Пример 25. IfThenTag.java

    package coreservlets.tags;
    
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import java.io.*;
    import javax.servlet.*;
    
    /** The then part of an if tag.
    */
    
    public class IfThenTag extends BodyTagSupport
    {
       public int doStartTag() throws JspTagException
       {
       IfTag parent =
           (IfTag)findAncestorWithClass(this, IfTag.class);
         if (parent == null)
         {
           throw new JspTagException("then not inside if");
         } else if (!parent.hasCondition())
         {
           String warning =
             "condition tag must come before then tag";
           throw new JspTagException(warning);
         }
         return(EVAL_BODY_TAG);
       }
    
       public int doAfterBody()
       {
       IfTag parent =
           (IfTag)findAncestorWithClass(this, IfTag.class);
         if (parent.getCondition())
         {
            try
            {
               BodyContent body = getBodyContent();
               JspWriter out = body.getEnclosingWriter();
               out.print(body.getString());
            } catch(IOException ioe)
            {
              System.out.println("Error in IfThenTag: " + ioe);
            }
       }
         return(SKIP_BODY);
       }
    }
    
    

    Пример 26. IfElseTag.java

    package coreservlets.tags;
    
    import javax.servlet.jsp.*;
    import javax.servlet.jsp.tagext.*;
    import java.io.*;
    import javax.servlet.*;
    
    /** The else part of an if tag.
    */
    public class IfElseTag extends BodyTagSupport
    {
       public int doStartTag() throws JspTagException
       {
       IfTag parent =
           (IfTag)findAncestorWithClass(this, IfTag.class);
         if (parent == null)
         {
           throw new JspTagException("else not inside if");
         } else if (!parent.hasCondition())
         {
           String warning =
             "condition tag must come before else tag";
           throw new JspTagException(warning);
         }
         return(EVAL_BODY_TAG);
       }
    
       public int doAfterBody()
       {
       IfTag parent =
           (IfTag)findAncestorWithClass(this, IfTag.class);
         if (!parent.getCondition())
         {
            try
            {
              BodyContent body = getBodyContent();
              JspWriter out = body.getEnclosingWriter();
              out.print(body.getString());
            } catch(IOException ioe)
            {
              System.out.println("Error in IfElseTag: " + ioe);
            }
       }
         return(SKIP_BODY);
       }
    }
    
    

    Файл – описатель библиотеки тега

    Однако существует точное определение структуры вложенности для тегов: теги должны быть объявлены отдельно в TLD файле. Это значит, что проверка правильности вложенности определяется только во время запроса, а не во время трансляции. В принципе, можно сконструировать систему для выполнения проверки во время трансляции при использовании класса TagExtraInfo. Этот класс имеет метод VariableInfo, который можно использовать для проверки существования атрибутов. Определив подкласс от TagExtraInfo, можно ассоциировать его в тегом в tld файле с помощью элемента teiclass, который используется точно также, как tagclass. На практике, однако, TagExtraInfo плохо документирован и тяжел в использовании.

    Пример 27. csajsp-taglib.tld

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <!DOCTYPE taglib
     PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
     "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
    
    <!-- a tag library descriptor -->
    
    <taglib>
      <!-- after this the default space is
           "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
      -->
    
      <tlibversion>1.0</tlibversion>
      <jspversion>1.1</jspversion>
      <shortname>csajsp</shortname>
      <urn></urn>
      <info>
         A tag library from Core Servlets and JavaServer Pages,
         http://www.coreservlets.com/.
      </info>
    
      <!-- Other tags defined earlier... -->
    <tag>
        <name>if</name>
        <tagclass>coreservlets.tags.IfTag</tagclass>
        <info>if/condition/then/else tag.</info>
        <bodycontent>JSP</bodycontent>
      </tag>
    
      <tag>
        <name>condition</name>
        <tagclass>coreservlets.tags.IfConditionTag</tagclass>
        <info>condition part of if/condition/then/else tag.</info>
        <bodycontent>JSP</bodycontent>
      </tag>
    
      <tag>
        <name>then</name>
        <tagclass>coreservlets.tags.IfThenTag</tagclass>
        <info>then part of if/condition/then/else tag.</info>
        <bodycontent>JSP</bodycontent>
      </tag>
    
      <tag>
        <name>else</name>
        <tagclass>coreservlets.tags.IfElseTag</tagclass>
        <info>else part of if/condition/then/else tag.</info>
        <bodycontent>JSP</bodycontent>
      </tag>
    
    </taglib>
    
    

    JSP файл

    В примере 28 показана страница, которая использует тег csajsp:if тремя различными способами. Первый: значение true жестко закодировано для условия. Второй: для условия используется параметр от HTTP запроса. Третий: для определения значения условия генерируется случайное число и сравнивается с фиксированным. На рисунке 9 показан результат.

    Пример 28. IfExample.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE>If Tag Example</TITLE>
    <LINK REL=STYLESHEET
          HREF="JSP-Styles.css"
          TYPE="text/css">
    </HEAD>
    
    <BODY>
    <H1>If Tag Example</H1>
    <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
    
    <csajsp:if>
      <csajsp:condition>true</csajsp:condition>
      <csajsp:then>Condition was true</csajsp:then>
      <csajsp:else>Condition was false</csajsp:else>
    </csajsp:if>
    
    <P>
    <csajsp:if>
      <csajsp:condition><%= request.isSecure() %></csajsp:condition>
      <csajsp:then>Request is using SSL (https)</csajsp:then>
      <csajsp:else>Request is not using SSL</csajsp:else>
      </csajsp:if>
    
    <P>
    Some coin tosses:<BR>
    <csajsp:repeat reps="20">
    <csajsp:if>
        <csajsp:condition>
          <%= Math.random() > 0.5 %>
        </csajsp:condition>
      <csajsp:then><B>Heads</B><BR></csajsp:then>
      <csajsp:else><B>Tails</B><BR></csajsp:else>
      </csajsp:if>
    </csajsp:repeat>
    
    </BODY>
    </HTML>
    
    

    Рисунок 9. Результат IfExample.jsp.


    Оригинал статьи: Core Servlets and JavaServer Pages, Chapter 14.
[an error occurred while processing this directive]
[an error occurred while processing this directive]Перевод на русский © Дмитрий Остроушко, 2000
< Вернуться на caйт :: Copyright © 1999 — 2010, IT • archiv.