JavaServer Pages – užívateľské značky a knižnice 3.

17. prosince 2002

V predchádzajúcej časti sme preberali význam a obsah súborov TLD (Tag Library Descriptor). V súbore TLD je element s názvom „tagclass“. Tento element je povinný a musí obsahovať kompletné meno triedy (package.Class) zodpovednej za spracovanie konkrétnej značky. V dnešnej časti si povieme niečo málo práve o týchto triedach, ktoré sa označujú ako Tag Handlers.

Triedy zodpovedné za spracovanie konkrétnej značky, sú v podstate Java Beany. Preto pre ne platia podobné pravidlá (viz JavaServer Pages – akčné značky). Na rozdiel od beanov však tag handlery majú určité vlastnosti navyše. Tag handler musí implementovať rozhranie javax.servlet.jsp.tagext.Tag prípadne javax.servlet.jsp.tagext.BodyTag alebo (častejší prípad) musí vzniknúť dedením z triedy javax.servlet.jsp.tagext.TagSupport prípadne javax.servlet.jsp.tagext.BodyTagSupport. Handler má prístup k väčšiemu množstvu informácií o obsahu JSP stránky ako JavaBean. Je to vďaka tomu, že môže čítať a zapisovať do objektu triedy javax.servlet.jsp.PageContext, ktorý je držiteľom informácií o práve spracovávanej stránke, vrátane request a response objektov, prípadne iných objektov, ktoré sú asociované so stránkou. Triedy TagSupport a BodyTagSupport nie sú abstraktné triedy a teda obsahujú úplnú implementáciu vyššie uvedených rozhraní Tag a BodyTag. Aby ste si urobili predstavu, v akom vzťahu sú tieto triedy a rozhrania a aké metódy poskytujú, prezrite si nasledujúci class diagram:

V prípade, že chcete zapisovať priamo do stránky JSP, budete potrebovať do tag handlera naimportovať triedu java.io.*.

Jednoduché značky (bez parametrov a tela)

Najlepšie na príklade si vysvetlíme vytvorenie tag handlera pre najjednoduchší typ užívateľskej značky. Samozrejme potrebujeme minimálne tri veci: stránku JSP, súbor TLD a Tag Handler.

hello.jsp

<html>
 <head>
  <%@ taglib uri=“WEB-INF/hello.tld“ prefix=“interval“ %>
  <%@ page contentType=“text/html;charset=windows-1250″%>
  <META HTTP-EQUIV=“Content-Type“ CONTENT=“text/html;charset=windows-1250″>
  <title>Hello Tag</title>
 </head>
<body>
<strong>Vitajte na našich stránkach venovaných užívateľským značkám.</strong><p/>
<i><interval:hello></interval:hello></i>
<strong>Dúfame, že prídete znova.</strong>
</body>
</html>

hello.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“>
<taglib>
 <tlibversion>1.0</tlibversion>
 <jspversion>1.1</jspversion>
 <shortname>interval</shortname>
 <info>Simple welcome library.</info>
 <tag>
  <name>hello</name>
  <tagclass>interval.tags.Hello</tagclass>
  <bodycontent>JSP</bodycontent>
 </tag>
</taglib>

interval.tags.Hello

package interval.tags;
 
import java.io.*;
import java.util.Date;
import java.text.DateFormat;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
 
public class Hello extends TagSupport {
 public int doStartTag() throws JspTagException {
  return EVAL_BODY_INCLUDE;
 }
 public int doEndTag() throws JspTagException {
  DateFormat df = DateFormat.getDateInstance();
  String date = df.format(new Date());
  try {
   JspWriter out = pageContext.getOut();
   out.print(„Moje meno je “ + getClass().getName() +
     “ a dnes máme “ + date + „<p/>“);
  } catch (IOException ex) {
     throw new JspTagException
     („Error: Hello tag nemôže zapisovať do JSP“);
  }
  return EVAL_PAGE;
 }
}

Všimnite si, že trieda Hello obsahuje len dve metódy doStartTag() a doEndTag(). Prvá z nich je volaná v okamihu, keď server narazí na otvárajúcu časť značky (<interval:hello>). V našom príklade táto metóda nič iné nevykoná, len vráti konštantu EVAL_BODY_INCLUDE. To znamená toľko, aby server načítal obsah tela značky. Keďže žiadne nemá, žiadne nenačíta. Ak by ste explicitne chceli aby obsah tela ignoroval, musíte návratovú hodnotu metódy zmeniť na SKIP_BODY. Podobne to funguje aj s metódou doEndTag(). Je volaná vtedy, keď sa spracováva ukončovacia časť značky (</interval:hello>). Aj táto metóda má dve rôzne návratové hodnoty: EVAL_PAGE a SKIP_PAGE. Prvá zabezpečí, že server po ukončení značky pokračuje v spracovávaní zvyšku stránky JSP. Druhá konštanta spôsobí prerušenie a ukončenie spracovávania zvyšku stránky JSP. Samozrejme je možné namiesto otváracej a ukončovacej časti značky použiť skrátený tvar. Teda ak nemám v úmysle spracovávať telo značky, zapíšem len <interval:hello/>.

Značky s parametrami (bez tela)

Rozdiel medzi jednoduchými značkami a značkami s parametrami je v tom, že tag handler druhého typu musí obsahovať metódy typu setXxx(). Pričom pravidlo je také, že keď nejaký parameter značky sa volá napríklad zakaznikId potom príslušná metóda sa musí volať setZakaznikId(). Táto charakteristika je prebraná od JavaBeans. Ďalšia zmena nastáva v súbore TLD, kde je nutné definovať element <attribute> vrátane príslušných subelementov. Opäť si nasadenie ukážme na jednoduchom príklade.

enter.html

<html>
 <head>
  <META HTTP-EQUIV=“Content-Type“ CONTENT=“text/html;charset=windows-1250″>
  <title>Vstup na stránky</title>
 </head>
<body>
Vitajte a príhláste sa prosím: <br>
<form action=“helloName.jsp“ method=“post“>
 <input type=“text“ name=“meno“><input type=“submit“ name=“submit“ value=“OK“>
</form>
</body>
</html>

helloName.jsp

<%@ page contentType=“text/html;charset=windows-1250″%>
<%@ taglib prefix=“interval“ uri=“WEB-INF/hello.tld“ %>
<%@ taglib prefix=“fmt“ uri=“WEB-INF/fmt.tld“ %>
<html>
 <head><title>Hello Name Tag</title></head>
<body>
 <fmt:requestEncoding value=“windows-1250″/>
 <strong>Vitajte na našich stránkach venovaných užívateľským značkám.</strong><p>
 <i><interval:helloName meno='<%= request.getParameter(„meno“) %>’/></i><p>
 <strong>Dúfame, že prídete znova.</strong>
</body>
</html>

hello.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“>
<taglib>
 <tlibversion>1.0</tlibversion>
 <jspversion>1.1</jspversion>
 <shortname>interval</shortname>
 <info>Simple welcome library.</info>
<tag>
 <name>hello</name>
 <tagclass>interval.tags.Hello</tagclass>
 <bodycontent>JSP</bodycontent>
</tag>
<tag>
 <name>helloName</name>
 <tagclass>interval.tags.HelloName</tagclass>
 <bodycontent>JSP</bodycontent>
 <attribute>
  <name>meno</name>
  <required>true</required>
  <rtexprvalue>true</rtexprvalue>
 </attribute >
</tag>
</taglib>

interval.tags.HelloName

package interval.tags;
 
import java.io.*;
import java.util.Date;
import java.text.DateFormat;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
 
public class HelloName extends TagSupport {
 private String name = „nobody“;
 
 public void setMeno(String name) {
  if ( !name.equals(„“) ) {
   this.name = name;
  }
 }
 
 public int doStartTag() throws JspTagException {
  return EVAL_BODY_INCLUDE;
 }
 public int doEndTag() throws JspTagException {
  DateFormat df = DateFormat.getDateInstance();
  String date = df.format(new Date());
  try {
   JspWriter out = pageContext.getOut();
   out.print(„Ahoj, “ +name+ „<br>“);
   out.print(„Moje meno je “ + getClass().getName() +
   “ a dnes máme “ + date + „<p/>“);
  } catch (IOException ex) {
   throw new JspTagException
    („Error: Hello tag nemôže zapisovať do JSP“);
  }
 return EVAL_PAGE;
 }
}

Značky s telom

Značky s telom s ním môžu manipulovať, môžu ho začleniť a použiť voliteľne (na základe nejakej podmienky), môžu ho ponechať bez zmeny a nakoniec môžu ho ignorovať, teda vôbec nepoužiť. Aby značka mohla so svojím telom niečo vykonať (spracovať ho), musí jej obslužný tag handler vzniknúť dedením z triedy BodyTagSupport. Táto trieda mu dáva k dispozícii známe metódy doStartTag() a doEndTag() ale aj ďalšie, potrebné na manipuláciu s telom:

  • doAfterBody()
    Táto metóda sa volá vždy, keď je telo značky už načítané. Návratovou hodnotou je konštanta EVAL_BODY_TAG, ktorá spôsobí, že obsah tela bude znova načítaný, alebo konštanta SKIP_BODY, ktorá spôsobí, že obsah tela nebude už viac načítavaný.
  • doInitBody()
    Metóda sa volá vtedy, keď je značka načítaná a zavolaná metóda doStartTag(). Má rovnaké návratové hodnoty ako doAfterBody(), s tým rozdielom, že SKIP_BODY nedovolí načítať telo značky.

V obslužnej triede odvodenej od BodyTagSupport máte k dispozícii objekt triedy BodyContent, ktorý získate nasledovne: BodyContent body = getBodyContent();. Trieda BodyContent, odvodená od triedy JspWriter, môže byť použitá na manipuláciu s obsahom tela značky a ukladať tento obsah pre neskoršie použitie. Trieda BodyContent obsahuje tri dôležité motódy:

  • getEnclosingWriter()
    Vracia objekt javax.servlet.jsp.JspWriter používaný v metódach doStartTag() a doEndTag(). Väčšinou sa táto metóda používa na získanie writera pre stránku JSP, pomocou ktorého môžeme zapísať obsah objektu BodyContent do stránky potom, čo sme vykonali manipuláciu (transformáciu) tela značky.
  • getReader()
    Vracia objekt triedy java.io.Reader, ktorý má prístup k telu značky.
  • getString()
    Vracia objekt triedy java.lang.String. Tento objekt sprístupní obsah tela značky. Používa sa vtedy, keď potrebujeme zistiť, čo bolo pridané do tela značky.
  • clearBody()
    Vymaže obsah objektu triedy BodyContent.

Ukážme si teda niečo na príklade.

enterbody.htm

<!DOCTYPE HTML PUBLIC „-//W3C//DTD HTML 4.01 Transitional//EN“>
<html>
<head>
 <title>Hello Body Tag</title>
 <META HTTP-EQUIV=“Content-Type“ CONTENT=“text/html;charset=windows-1250″>
</head>
<body>
<form action=“helloBody.jsp“ method=“post“>
 <textarea cols=“30″ rows=“6″ name=“text“>Napíšte sem prosím nejaký text …</textarea><p>
<input type=“submit“ name=“submit“ value=“OK“>
</form>
</body>
</html>

helloBody.jsp

<%@ taglib prefix=“interval“ uri=“WEB-INF/hello.tld“%>
<%@ taglib prefix=“fmt“ uri=“WEB-INF/fmt.tld“ %>
<%@ page contentType=“text/html;charset=windows-1250″ %>
<html>
 <head><title>Hello Body Tag</title>
</head>
<body>
 <fmt:requestEncoding value=“windows-1250″/>
 <strong>Tento tag prevzal text zadaný v textfielde a vypíše ho velkými písmenami:</strong><br>
<P>
 <interval:hellobody>
  <%= request.getParameter(„text“) %>
 </interval:hellobody>
<P>
<strong>Pôvodný text:</strong>
<P>
 <%= request.getParameter(„text“) %>
</body>
</html>

hello.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“>
<taglib>
 <tlibversion>1.0</tlibversion>
 <jspversion>1.1</jspversion>
 <shortname>interval</shortname>
 <info>Simple welcome library.</info>
<tag>
 <name>hello</name>
 <tagclass>interval.tags.Hello</tagclass>
 <bodycontent>JSP</bodycontent>
</tag>
<tag>
 <name>helloName</name>
 <tagclass>interval.tags.HelloName</tagclass>
 <bodycontent>JSP</bodycontent>
 <attribute>
  <name>meno</name>
  <required>true</required>
  <rtexprvalue>true</rtexprvalue>
 </attribute >
</tag>
<tag>
 <name>hellobody</name>
 <tagclass>interval.tags.HelloBody</tagclass>
 <bodycontent>JSP</bodycontent>
</tag>
</taglib>

interval.tags.HelloBody.java

package interval.tags;
 
import java.io.*;
import java.util.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
 
public class HelloBody extends BodyTagSupport{
 public int doAfterBody() {
  BodyContent body = getBodyContent();
  String sbody = body.getString();
  sbody = sbody.toUpperCase();
  try {
   JspWriter out = body.getEnclosingWriter();
   out.println(sbody);
  }
  catch (IOException ex) {
   System.out.println(„Error writing body.“);
  }
  return SKIP_BODY;
 }
}

Týmto dielom sme ukončili základy technológie tvorby stránok JSP. Avšak tak celkom nekončíme, pretože existuje ešte veľa podporných technológií okolo programovacieho jazyka Java. Ak sa pozriete dôkladne na posledný príklad (značky s telom), objavíte, že som na stránke helloBody.jsp použil nejakú neznámu značku fmt:requestEncoding. Táto značka nastaví spôsob kódovania reťazcov v objekte request. Samotná značka je z rodiny tzv. JSTL (Java Standard Tag Library), čo je kolekcia značiek od firmy SUN.

Na úplný záver ponúkam uvedené funkčné príklady:

hello | helloName | helloBody

A tu sú príklady na stiahnutie v dvoch formách – ako *.zip archív a ako *.war webovská aplikácia.

hello.zip | helloName.zip | helloBody.zip

hello.zip | helloName.war | helloBody.war

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Předchozí článek brdy.info
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *