JavaWeb学习——自定义标签

自定义标签


一、自定义标签概述

使用标准JSP访问、操作JavaBean,是实现展现(HTML)与业务实现(Java代码)分离的第一步。然而,标准方法功能不够强大,以至于开发者无法仅仅使用它们开发应用,还要在JSP页面中使用Java代码。

介于JavaBean中解决展现与业务实现分离的方法的不完善,就产生了JSP1.1中的自定义标签。自定义标签提供了在JavaBean中所不能实现的便利。其中就包括,自定义标签允许访问JSP隐藏的对象及它们的属性。

尽管自定义标签能编写无脚本的JSP页面,但是JSP1.1和JSP1.2中提供的经典自定义标签非常难用。直到JSP2.0,才增加两个特性,用于改善自定义标签实现。第一个特性是一个接口——SimpleTag。另一个特性是标签文件中定义标签的机制。

自定义标签的实现,叫做标签处理器,而简单标签处理器是指继承SimpleTag实现的标签处理器。

二、简单标签处理器

实现SimpleTag的标签处理器都叫作简单标签处理器;实现Tag、Iteration及BodyTag的标签处理器都叫作经典标签处理器。

简单标签处理器有着简单的生命周期,而且比经典标签处理器更加容易实现。SimpleTag接口中用于标签触发的方法只有一个——doTag,并且此方法只执行一次。业务逻辑、遍历及页面内容操作都在这里实现。简单标签处理器中的页面内容都在JspFragment类的实例中体现。

简单标签的生命周期如下:

  • JSP容器通过简单标签处理器的无参数构造器创建它的实例。
  • JSP容器通过setJspContext的方法,传入JspContext对象。
  • 如果自定义标签被另一个自定义标签所嵌套,JSP容器就会调用setParent的方法。
  • JSP容器调用该标签中所定义的每个属性的set方法。
  • 如果需要处理页面内容,JSP容器还会调用SimpleTag接口的setJspBody方法,把使用JSPFragment封装的页面内容传过来。

javax.servlet.jsp.tagext 包中也包含了一个SimpleTag的基础类:SimpleTagSupport。它提供了SimpleTag所有方法的默认实现。

三、实例

自定义标签需要有两个步骤:编写标签处理器及注册标签。

1. 编写标签处理器

package customtag;

import java.io.IOException;
import java.util.StringTokenizer;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class DataFormatterTag extends SimpleTagSupport {
    private String header;     //标签属性
    private String items;

    public void setHeader(String header) {
        this.header = header;
    }

    public void setItems(String items) {
        this.items = items;
    }

    public void doTag() throws IOException, JspException {   //标签处理函数
        JspContext jspContext = getJspContext();    //返回JspFragment关联的JspContext对象
        JspWriter out = jspContext.getOut();    //通过JspContext实例中的getOut方法获取JspWriter对象

        out.print("<table style=‘border:1px solid green‘>\n" + "<tr><td><span style=‘font-weight:bold‘>" + header +"</span></td></tr>\n");
        StringTokenizer tokenizer = new StringTokenizer(items,",");
        while(tokenizer.hasMoreElements()) {
            String token = tokenizer.nextToken();
            out.print("<tr><td>" + token + "</td></tr>\n");
        }

        out.print("</table>");
    }
}

2. 注册标签

<?xml version="1.0" encoding="UTF-8"?>

<taglib xlmns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun/xml/ns/j2ee web-jsptaglibrary_2_1/xsd"
    version="2.1">

    <description>Simple tag examples</description>     <!-- 标签库描述 -->
    <tlib-version>1.0</tlib-version>
    <jsp-version>1.1</jsp-version>
    <short-name>My First Taglib Example</short-name>
    <uri>/firstTag</uri>  <!-- 为标签库设置URI,jsp通过它引入此标签库 -->
    <tag>
      <name>dataFormatter</name>    <!-- 自定义标签名称 -->
      <tag-class>customtag.DataFormatterTag</tag-class>    <!-- 标签处理器路径 -->
      <body-content>empty</body-content>    <!-- 标签内容处理方式 -->
      <attribute>
        <name>header</name>
        <required>true</required>
      </attribute>
      <attribute>
        <name>items</name>
        <required>true</required>
      </attribute>
    </tag>
</taglib>

3. 在JSP页面中使用自定义标签

 1 <%@ taglib uri="/firstTag" prefix="easy" %>
 2
 3 <html>
 4 <head>
 5     <title>TestingFormatterTag</title>
 6 </head>
 7
 8 <body>
 9 <easy:dataFormatter header="States" items="Alabama,Alaska,Georgia,Florida"/>
10
11 <br/>
12 <easy:dataFormatter header="Countries">
13     <jsp:attribute name="items">
14         US,UK,Canada,Korea
15     </jsp:attribute>
16 </easy:dataFormatter>
17
18 </body>
19 </html>

运行效果:

四.处理属性

实现SimpleTag接口或者扩展SimpleTagSupport的标签处理器都可以有属性。下面的例子展示了名为DateFormatTag的标签处理器可以将逗号分隔内容转换成HTML表格。

①标签处理器

 1 package customtag;
 2
 3 import java.io.IOException;
 4 import java.util.StringTokenizer;
 5
 6 import javax.servlet.jsp.JspContext;
 7 import javax.servlet.jsp.JspException;
 8 import javax.servlet.jsp.JspWriter;
 9 import javax.servlet.jsp.tagext.SimpleTagSupport;
10
11 public class DataFormatterTag extends SimpleTagSupport {
12     private String header;
13     private String items;
14
15     public void setHeader(String header) {
16         this.header = header;
17     }
18
19     public void setItems(String items) {
20         this.items = items;
21     }
22
23     public void doTag() throws IOException, JspException {
24         JspContext jspContext = getJspContext();
25         JspWriter out = jspContext.getOut();
26
27         out.print("<table style=‘border:1px solid green‘>\n" + "<tr><td><span style=‘font-weight:bold‘>" + header +"</span></td></tr>\n");
28         StringTokenizer tokenizer = new StringTokenizer(items,",");
29         while(tokenizer.hasMoreElements()) {
30             String token = tokenizer.nextToken();
31             out.print("<tr><td>" + token + "</td></tr>\n");
32         }
33
34         out.print("</table>");
35     }
36 }

②jsp页面实现

<%@ taglib uri="/WEB-INF/mytags.tld" prefix="easy" %>

<html>
<head>
    <title>TestingFormatterTag</title>
</head>

<body>
<easy:dataFormatter header="States" items="Alabama,Alaska,Georgia,Florida"/>

<br/>
<easy:dataFormatter header="Countries">
    <jsp:attribute name="items">
        US,UK,Canada,Korea
    </jsp:attribute>
</easy:dataFormatter>

</body>
</html>

③效果展示

五.访问标签内容

在SimpleTag中,可以通过JSP容器传入的JspFragment来访问标签内容。JspFragment类提供了多次访问Jsp中这部分代码的能力。JSP片段的定义不能包含脚本或者脚本表达式,他只能是文件模板或者JSP标准结点。

JspFragment类中有两个方法:getJspContext、invoke。定义如下:

public abstract JspContext getJspContext()

public abstract void invoke(java.io.Writer writer)
           throws JspException, java.io.IOException

getJspContext方法返回这个JspFragment关联的JspContext对象。可以通过invoke方法来执行这个片段(标签的内容),然后通过指定的Writer对象把它直接输出。如果把null传入invoke方法中,那么这个Writer将会被JspFragment所关联的JspContext对象中的getOut方法返回的JspWriter所接管。下面看一个示例:

SelectElementTag

package customtag;

import java.io.IOException;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class SelectElementTag extends SimpleTagSupport{
    private String[] countries = {"Australia", "Brazil", "China"};

    public void doTag() throws IOException, JspException {
        JspContext jspContext = getJspContext();
        JspWriter out = jspContext.getOut();
        out.print("<select>\n");
        for(int i=0;i<3;i++){
            getJspContext().setAttribute("value", countries[i]);
            getJspContext().setAttribute("text", countries[i]);
            getJspBody().invoke(null);
        }
        out.print("</select>\n");
    }
}

注册SelectElementTag

<tag>
    <name>select</name>
    <tag-class>customtag.SelectElementTag</tag-class>
    <body-content>scriptless</body-content>
</tag>

selectElementTagTest页面

<%@ taglib uri="/WEB-INF/mytags.tld" prefix="easy" %>

<html>
<head>
    <title>Testing SelectElementFormatterTag</title>
</head>

<body>
<easy:select>
    <option value="${value}">${text}</option>
</easy:select>
</body>
</html>

效果

六、编写EL函数

一般来说,编写EL函数需要以下两个步骤:

(1)创建一个包含静态方法的public类。每个类的静态方法表示一个EL函数。这个类可以不需要实现任何接口或者继承特定的类。可以像发布任何类一样发布这个类。这个类必须放在应用中的/WEB-INF/classes目录或者它的子目录下。

(2)用function节点在标签库描述其中注册这个函数。

  • function节点是taglib节点的下级节点,它有如下子节点:
  • description:可选,标签说明。
  • display-name:在XML工具中显示的缩写名字。
  • icon:可选,在XML工具中使用的icon节点。
  • name:函数的唯一名字。
  • function-class:该函数对应实现的Java类的全名。
  • function-signature:该函数对应实现的Java静态方法。
  • example:可选,使用该函数的示例说明。
  • function-extension:可以是一个或者多个节点,在XML工具中使用,用于提供该函数的更多的细节。

要使用这个函数,必须将taglib指令中的URI属性指向标签库描述,并指明使用的前缀。然后在JSP页面中使用如下语法来访问该函数:

${ prefix:functionName(parameterList) }

具体看以下示例:

StringFunction类中的reverseString方法

package function;

public class StringFunctions {
    public static String reverseString(String s){
        return new StringBuffer(s).reverse().toString();
    }
}

functiontags.tld文件

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://wwww.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_1.xsd"
        version="2.1">
    <description>
        Function tag examples
    </description>
    <tlib-version>1.0</tlib-version>
    <function>
        <description>Reverses a String</description>
        <name>reverseString</name>
        <function-class>function.StringFunctions</function-class>
        <function-signature>
            java.lang.String reverseString(java.lang.String)
        </function-signature>
    </function>
</taglib>

使用EL函数

<%@ taglib uri="/WEB-INF/functiontags.tld" prefix="f" %>
<html>
<head>
    <title>Testing reverseString function</title>
</head>
<body>
${f:reverseString("Hello World") }
</body>
</html>

效果

七、发布自定义标签

可以吧自定义的标签处理器以及标签描述器打包到JAR包里,这样就可以把它发布出来给别人使用了,就像JSTL一样。这种情况下,需要包含其所有的标签处理器及描述它们的TLD文件。此外,还需要在描述其中的URI节点中指定绝对的URI。

为了在应用中使用这个库,需要把这个JAR文件拷贝到应用的WEB-INF/lib目录下。在使用的时候,任何使用自定义标签的JSP页面都要使用和这个标签库描述器中定义的URL。

------ 天若有情天亦老,人间正道是沧桑 ------

原文地址:https://www.cnblogs.com/cardiolith/p/9480683.html

时间: 2024-08-29 05:26:53

JavaWeb学习——自定义标签的相关文章

JavaWeb之自定义标签&amp;JSTL&amp;国际化(九)

自定义标签 简介 自定义标签由于没练习,所以掌握的不是很深,但是对于我而言足够可以应付用户登录注册案例和购物车案例,有时间还是多了解的好 1. 自定义标签简介 1.作用:替换JSP页面中的java脚本(<%%>).(官方推荐:JSP2.0开始) 2. 开发步骤 1. 自定义一个类继承SimpleTagSupport实现doTag方法 2. WEB-INF,建立tld文件,定义标签地址/定义标签内容 3. jsp页面使用taglib指令引入uri地址,prefix定义标签名,直接在页面调用这个标

深入分析JavaWeb Item25 -- 自定义标签开发案例和打包自定义标签库

一.开发标签库案例 1.1.开发防盗链标签 1.编写标签处理器类:RefererTag.java package me.gacl.web.simpletag; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspException; import jav

JavaWeb学习----JSTL标签库

一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Community Process)所指定的标准规格,它主要提供给Java Web开发人员一个标准通用的标签函数库. Web 程序开发人员能够利用JSTL和EL来开发Web程序,取代传统直接在页面上嵌入Java程序(Scripting)的做法,以提高程序可读性.维护性和方便性. 既然是库文件,那我们就要

javaweb框架--自定义标签与freemaker结合

http://blog.csdn.net/myfmyfmyfmyf/article/details/8960299 很有用但是不不知道怎么说,写个例子,总之方便多了,并且容易管理,重复利用强 1.自定一个类,实现 javax.servlet.jsp.tagext.Tag;(PageTag.java) 2.建立一个tld文件(myfTag.tld) 3.建立一个freemaker文件*.ftl(page.ftl) 4.建立jsp页面,导入标签(<%@taglib prefix="myf&qu

javaweb学习总结(二十三)——jsp自定义标签开发入门

一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 package me.gacl.web.tag; 2 3 import java.io.IOException; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.jsp.JspException; 7 import

javaweb学习总结(二十三)——jsp自定义标签开发入门【转】

原文地址:http://www.cnblogs.com/xdp-gacl/p/3916734.html 一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 package me.gacl.web.tag; 2 3 import java.io.IOException; 4 5 import javax.servlet.http.HttpServletReques

Javaweb自定义标签

项目中用到自定义的标签文件,但是却在web.xml中没有看到相关的标签配置,原来如果web应用使用servelet2.4以上的版本就不需要在web.xml中定义了,servelet会自动加载tld文件,有两种方式使用自动加载 1.打成jar包时,将tld文件放在META-INF文件夹下(参考standard,jar) 2.直接将自定义tld文件放在WEB-INF下(也可以放在WEB-INF子目录下). java web开发中,如何查看JSP和Servlet版本? 打开tomcat的lib 目录下

javaweb基础(23)_jsp自定义标签

一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 package me.gacl.web.tag; 2 3 import java.io.IOException; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.jsp.JspException; 7 import

javaweb(二十三)——jsp自定义标签开发入门

一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 package me.gacl.web.tag; 2 3 import java.io.IOException; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.jsp.JspException; 7 import