JSP Tags selber erstellen -> Tutorial?

Romsl

Erfahrenes Mitglied
Hi,

gibt es ein Tutorial das zeigt wie JSP Tags erstellt werden können?

Ich bin schon dran, aber mein Problem ist, dass ich keine Object als Attribut mit übergeben kann sondern nur Strings. Weiß jemand wie es funktioniert bzw hat Beispielcode. Es sollte dann so wie bei
Code:
<c:forEach items="${list}"...
(bei dem ich ja über Listen iterieren kann) funktionieren.

Gruß

Danke Romsl
 
Hallo!

Einen eigenen JSP Tag zu erstellen ist eigentlich recht einfach.
Man muss einfach von der Klasse javax.servlet.jsp.tagext.TagSupport bzw. javax.servlet.jsp.tagext.SimpleTagSupport ableiten beispielsweise die doStartTag Methode überschreiben und einen passenden Descriptor (TLD = Tag Library Descriptor erstellen)

Wir erstellen beispielsweise mal einen tag der eine Liste von Zahlen summieren kann. Die Liste bekommt er als Parameter übergeben.

In Java sähe dass dan beispielsweise so aus:
Code:
/*
 * Created on 06.05.2005@16:49:01
 *
 * TODO Add some Licence info
 */
package de.tutorials.jsp.tags;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

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

/**
 * @author Tom
 * 
 * TODO Describe me
 * @jsp.tag body-content = "empty" description = "Computes the Sum of the given
 *          List of Numbers" display-name = "SumTag" name = "sumTag"
 *  
 */
public class SumTag extends TagSupport {

    private List numbers;

    private double sum;

    /*
     * (non-Javadoc)
     * 
     * @see javax.servlet.jsp.tagext.Tag#doStartTag()
     */
    public int doStartTag() throws JspException {
        try {

            for (Iterator iter = numbers.iterator(); iter.hasNext();) {
                Object number = (Object) iter.next();

                if (number instanceof Double) {
                    sum += ((Double) number).doubleValue();
                } else if (number instanceof Float) {
                    sum += ((Float) number).floatValue();
                } else if (number instanceof Integer) {
                    sum += ((Integer) number).intValue();
                } else if (number instanceof Long) {
                    sum += ((Long) number).longValue();
                } else if (number instanceof Short) {
                    sum += ((Short) number).shortValue();
                } else if (number instanceof Double) {
                    sum += ((Byte) number).byteValue();
                }

            }

            super.pageContext.getOut().print(sum);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.doStartTag();
    }

    /**
     * @jsp.attribute required = "true" description = "List of Numbers"
     *                rtexprvalue = "true" type = "java.util.List"
     * @return
     */
    public List getNumbers() {
        return numbers;
    }

    /**
     * @param numbers
     *            The numbers to set.
     */
    public void setNumbers(List numbers) {
        this.numbers = numbers;
    }
}

Der Descriptor sieht so aus:
sumTag.tld:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>

   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>sumTag</short-name>

   <tag>

      <name>sumTag</name>
      <tag-class>de.tutorials.jsp.tags.SumTag</tag-class>
      <body-content>empty</body-content>
      <display-name>SumTag</display-name>
      <description><![CDATA[Computes the Sum of the given List of Numbers]]></description>

      <attribute>
         <name>numbers</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>

           <type>java.util.List</type>
           <description><![CDATA[List of Numbers]]></description>

      </attribute>
   </tag>

</taglib>

Will man den tag dann Verwenden könnte man sowas schreiben:
test.jsp:
Code:
<%@ taglib uri="WEB-INF/tlds/sumTag.tld" prefix="sum"%>

<% 
java.util.List list = new java.util.ArrayList(); 
list.add(Integer.valueOf(10));
list.add(Double.valueOf("105.25"));
list.add(Long.valueOf(255L));
%>

<sum:sumTag numbers="<%= list %>"/>

Das Attribut "numbers" entspricht der Membervariablen numbers in der Klasse SumTag.
Will man andere Attribute haben muss man einfach die entsprechenden Properties zur Java Klasse hinzufügen. Ein Attribut foo im Tag X entspräche dann beispielsweise der Methode getFoo() / setFoo(SomeType foo); und der Membervariablen SomeType foo;

So einfach ist das ;-)

Gruß Tom
 

Anhänge

Danke Thomas,

Super Beispiel, denn der TAG <type> in der tld definition wars.

Gruß

Roman
 
Da ist mir noch was aufgefallen.

Du rufst das Tag mit

Code:
<sum:sumTag numbers="<%= list %>"/>

bei c:forEach kann ich das mit
Code:
<c:forEach items="${list}" ...
rufen.

Würde das auch irgendwie gehen?

Code:
<sum:sumTag numbers="${list}"/>

Danke
 
EL? Muss dazu von einer anderen Tag-Klasse ableiten? Hast du mir evtl. ein Beispiel?

Danke
 
OK ich habs, danke Christian.

Code:
public void setList(String list) {

        List l = null;
        try {
            l = (List) ExpressionEvaluatorManager.evaluate("l", "${customerDto}", List.class, this, pageContext);
        }
        catch (JspException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        if (l != null) System.out.println("LIST: " + l.toString());

        this.list = l;
    }

Gruß

Romsl
 
Musst ich leider nochmal öffnen, ich möchte meine eigenen webTags schreiben.

d.h. mein jsp code vereinfachen, wie z.B.

HTML:
<webos:table list="${anyList}" class="table" ...>
    <webos:tableColumn property="id" class="tableIdCol" .../>
    <webos:tableColumn property="firstname" class="tableCol" .../>
    ....
</webos:table>

soll zu folgender Ausgabe führen.

HTML:
<table class="table" ...>
    <tr>
        <td class="tableIdCol"...>hier wird die property id (getId()) des aus anyList ausgelesenen objectes angezeigt</td>
        <td class="tableIdCol"...>das selbe wie oben nur property getFirstname()</td>
    </tr>
    <tr>
        -> das wird solange fortgeführt solange die liste noch elemente enthält -> iterator
    </tr>
</table>

aber sp wie ich das habe gehts nicht...

Code:
package ebooking.webos.tag;

import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;

import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.JspWriter;
import java.io.IOException;
import java.util.List;
import java.util.Iterator;

/**
 * Created by IntelliJ IDEA.
 * User: Roman Georg Rädle
 * Date: 05.05.2005
 * Time: 18:41:16
 * To change this template use File | Settings | File Templates.
 */
public class WebOSTable extends BodyTagSupport {

    private List list;
    private Iterator iter;

    public int doStartTag() throws JspException {
        System.out.println("doStartTag()");

        if (!iter.hasNext()) {
            System.out.println("SKIP_BODY");
            return SKIP_BODY;
        }

        StringBuffer html = new StringBuffer();

        html.append("<table>\n");

        try {
            JspWriter writer = pageContext.getOut();
            writer.write(html.toString());
        }
        catch (IOException ioe) {
            throw new JspException(ioe.getMessage());
        }

        System.out.println("EVAL_BODY_BUFFERED");
        return EVAL_BODY_BUFFERED;
    }

    public void doInitBody() throws JspException {
        try {
            pageContext.getOut().write("<tr>");
        }
        catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public int doAfterBody() throws JspTagException {
        System.out.println("doEndTag()");

        try {
            pageContext.getOut().write("</tr>");
        }
        catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        if (iter.hasNext()) {
            System.out.println("EVAL_BODY_AGAIN");

            Object o = iter.next();
            System.out.println("ECHO: " + o.toString());

            return EVAL_BODY_BUFFERED;
        }

        System.out.println("EVAL_PAGE");
        return EVAL_PAGE;
    }

    public int doEndTag() throws JspException {
        try {
            StringBuffer html = new StringBuffer();

            html.append("</table>\n");

            JspWriter writer = pageContext.getOut();
            writer.write(html.toString());

            bodyContent.writeOut(bodyContent.getEnclosingWriter());
        }
        catch (IOException ioe) {
            throw new JspTagException(ioe.getMessage());
        }

        return EVAL_PAGE;
    }

    public void setList(String listEL) throws JspException {
        this.list = (List) ExpressionEvaluatorManager.evaluate("list", listEL, List.class, pageContext);
        this.iter = list.iterator();
    }
}

kann mir da jemand weiterhelfen?
 
Zuletzt bearbeitet:
Zurück