JSP2 的自定义标签
在 JSP 中开发标签库只需如下几个步骤
1、开发自定义标签处理类
2、建立一个 *.tld 文件,每个 *.tld 文件对应一个标签库,每个标签库可包含多个标签
3、在 JSP 文件中使用自定义标签
开发自定义标签类
在 JSP 页面使用一个简单的标签时,底层实际上由标签处理类提供支持,从而可以通过简单的标签来封装复杂的功能。
自定义标签类应该继承一个父类:javax.servlet.jsp.tagext.SimpleTagSupport,除此之外,JSP 自定义标签还有如下要求:
1、如果标签类包含属性,每个属性都有对应的 getter 和 setter 方法
2、重写 doTag() 方法,这个方法负责生成页面内容
下面开发一个最简单的自定义标签:
HelloWorldTag.java
package com.baiguiren; import java.io.IOException;
import java.util.Date; import javax.servlet.*; public class HelloWorldTag extends SimpleTagSupport
{
// 重写 doTag() 方法,该方法为标签生成页面内容
public void doTag() throws JspException, IOException {
// 获取页面输出流,并输出字符串
getJspContext().getOut().write("Hello World! " + new Date());
}
}
建立 TLD 文件
TLD 是 Tag Library Definition 的缩写,即标签库定义,文件的后缀是 tld,每个 TLD 文件对应一个标签库,一个标签库中可包含多个标签。TLD 文件也称为标签库定义文件。
标签库定义文件的根元素是 tablib,他可以包含多个 tag 子元素,每个 tag 子元素都定义一个标签。通常可以到 web 容器下复制一个标签库定义文件,并在此基础上修改即可。
<?xml version="1.0" encoding="UTF-8"?> <taglib 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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0"> <tlib-version>1.0</tlib-version>
<short-name>mytaglib</short-name>
<uri>http://localhost:8080/jsp/mytaglib</uri> <!-- 定义第一个标签 -->
<tag>
<description>输出 Hello, World</description>
<!-- 定义标签名 -->
<name>helloWorld</name>
<!-- 定义标签处理类 -->
<tag-class>com.baiguiren.HelloWorldTag</tag-class>
<!-- 定义标签体为空 -->
<body-content>empty</body-content>
</tag> </taglib>
上面的标签库定义文件也是一个标准的 XML 文件,该 XML 文件的根元素是 taglib 元素,因此每次编写标签库定义文件时都直接添加该元素即可。
taglib 下有如下三个子元素:
1、tlib-version:指定该标签库实现的版本,这是一个作为标识的内部版本号,对程序没有太大的作用。
2、short-name:该标签库的默认短名,该名称通常也没有太大的用处。
3、uri:这个属性非常重要,它指定该标签库的 URI,相当于指定该标签库的唯一标识。JSP 页面中使用该标签库时就是根据该 URI 属性来定位标签库的。
除此之外,taglib 元素下可以包含多个 tag 元素,每个 tag 元素定义一个标签,tag 元素下允许出现如下常用子元素。
name:该标签的名称,这个子元素很重要,JSP 页面中就是根据该名称来使用此标签的。
tag-class:指定标签的处理类,它指定了标签由哪个标签处理类来处理。
body-content:这个子元素指定标签体内容,该子元素可以是以下几个:
1、tagdependent:指定标签处理类自己负责处理标签体
2、empty:指定该标签只能作为空标签使用
3、scriptless:指定该标签的标签体可以是静态 HTML 元素、表达式语言,但不允许出现 JSP 脚本。
4、JSP:指定该标签的标签体可以使用 JSP 脚本(JSP2 规范不再推荐使用 JSP)
dynamic-attributes:指定该标签是否支持动态属性。只有当定义动态属性标签时才需要该子元素。
定义了上面的标签库定义文件后,将标签库文件放在 Web 应用的 WEB-INF 路径或任意子路径下,Java Web 规范会自动加载该文件,则该文件定义的标签库也将生效。
使用标签库
在 JSP 页面中确定指定的标签需要两点:
1、标签库 URI:确定使用哪个标签库
2、标签名:确定使用哪个标签
使用标签库分成以下两个步骤:
1、导入标签库:使用 taglib 编译指令导入标签库,就是将该标签库和指定前缀关联起来。
2、使用标签:在 JSP 页面中使用自定义标签。
taglib 的语法格式如下:
<%@ taglib uri="tagliburi" prefix="tagPrefix" %>
其中 uri 属性指定标签库的 URI,这个 URI 可以确定一个标签库。而 prefix 属性指定标签库前缀,即所有使用该前缀的标签将由此标签库处理。
使用标签的语法格式如下:
<tagPrefix:tagName tagAttribute="tagValue" ...>
<tagBody />
</tagPrefix:tagName>
如果该标签没有标签体,则可以使用如下的语法格式:
<tagPrefix:tagName tagAttribute="tagValue" .../>
上面使用标签的语法里都包含了设置属性值,前面介绍的 HelloWorldTag 标签没有任何属性,所以使用该标签只需用 <myTag:helloWorld/> 即可。其中 mytag 是 taglib 指令为标签库指定的前缀,而 helloWorld 是标签名。
mytaglib.tld
<?xml version="1.0" encoding="UTF-8"?> <taglib 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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0"> <tlib-version>1.0</tlib-version>
<short-name>mytaglib</short-name>
<uri>/mytaglib</uri> <!-- 定义第一个标签 -->
<tag>
<description>输出 Hello, World</description>
<!-- 定义标签名 -->
<name>helloWorld</name>
<!-- 定义标签处理类 -->
<tag-class>com.baiguiren.HelloWorldTag</tag-class>
<!-- 定义标签体为空 -->
<body-content>empty</body-content>
</tag> </taglib>
hello-world-tag.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %> <html>
<head>
<title>hello world tag</title>
</head>
<body>
<!-- 使用标签,其中 mytag 是标签前缀,根据 taglib 的编译指令,mytag 前缀将由 URI 为 http://localhost:8080/jsp/mytaglib 的标签库处理 -->
<mytag:helloWorld/><br/>
</body>
</html>
带属性的标签
带属性的标签必须为每个属性提供对应的 setter 和 getter 方法。
定义标签
<!-- 带属性标签 -->
<tag>
<name>query</name>
<tag-class>com.baiguiren.QueryTag</tag-class>
<body-content>empty</body-content> <!-- 配置属性: driver -->
<attribute>
<name>driver</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置属性:url -->
<attribute>
<name>url</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置属性:user -->
<attribute>
<name>user</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置属性:pass -->
<attribute>
<name>pass</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置属性:sql -->
<attribute>
<name>sql</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
</tag>
标签处理类 QueryTag.java
package com.baiguiren; import java.io.IOException;
import java.io.Writer;
import java.util.Date;
import java.sql.*; import javax.servlet.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*; public class QueryTag extends SimpleTagSupport
{
// 定义成员变量来代表标签的属性
private String driver;
private String url;
private String user;
private String pass;
private String sql; // 执行数据库访问的对象
private Connection connection = null;
private Statement statement = null;
private ResultSet resultSet = null;
private ResultSetMetaData resultSetMetaData = null; // 下面是各成员属性的 setter 和 getter 方法
public void setDriver(String driver) {
this.driver = driver;
} public String getDriver() {
return this.driver;
} public void setUrl(String url) {
this.url = url;
} public String getUrl() {
return this.url;
} public void setUser(String user) {
this.user = user;
} public String getUser() {
return this.user;
} public void setPass(String pass) {
this.pass = pass;
} public String getPass() {
return this.pass;
} public void setSql(String sql) {
this.sql = sql;
} public String getSql() {
return this.sql;
} // 重写 doTag() 方法,该方法为标签生成页面内容
public void doTag() throws JspException, IOException
{
try {
// 注册驱动
Class.forName(driver);
// 获取数据库连接
connection = DriverManager.getConnection(url, user, pass);
// 创建 Statement 对象
statement = connection.createStatement();
// 执行查询
resultSet = statement.executeQuery(sql);
resultSetMetaData = resultSet.getMetaData();
// 获取列数目
int columnCount = resultSetMetaData.getColumnCount();
// 获取页面输出流
Writer out = getJspContext().getOut();
// 在页面输出表格
out.write("<table border='1' width='400'>");
// 遍历结果集
while (resultSet.next()) {
out.write("<br>");
// 逐列输出查询到的数据
for (int i = 1; i <= columnCount; i ++) {
out.write("<td>");
out.write(resultSet.getString(i));
out.write("</td>");
}
out.write("</tr>");
}
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
throw new JspException("自定义标签错误" + classNotFoundException.getMessage());
} catch (SQLException sqlException) {
sqlException.printStackTrace();
throw new JspException("SQL错误" + sqlException.getMessage());
} finally {
// 关闭结果集
try {
if (resultSet != null)
resultSet.close();
if (statement != null)
statement.close();
if (connection != null)
connection.close();
} catch (SQLException sqlException2) {
sqlException2.printStackTrace();
}
}
}
}
使用标签 query-tag.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %> <html>
<head>
<title>query tag</title>
</head>
<body> <mytag:query
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jsp"
user="root"
pass="root"
sql="select * from person"
/><br/> </body>
</html>
该标签的输出内容依然由 doTag 方法决定,该方法会根据属性值进行查询,并将查询结果集输出到当前页面。
对于有属性的标签,需要为 <tag.../> 元素增加 <attribute.../> 子元素,每个 attribute 子元素定义一个标签属性。
<attribute.../> 子元素通常还需要指定如下几个子元素:
1、name:设置属性名,子元素的值是字符串内容
2、required:设置该属性是否为必需属性,该子元素的值是 true 或 false
3、fragment:设置该属性是否支持 JSP 脚、表达式等动态内容,子元素的值为 true 或 false。
带标签体的标签
带标签体的标签,可以在标签内嵌入其他内容(包括静态的 HTML 和 动态的 JSP 内容),通常用于完成一些逻辑运算。
标签配置
<!-- 迭代标签 -->
<tag>
<name>iterator</name>
<tag-class>com.baiguiren.IteratorTag</tag-class>
<!-- 定义标签体不允许出现 JSP 脚本 -->
<body-content>scriptless</body-content> <!-- 配置标签属性:collection -->
<attribute>
<name>collection</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置标签属性:item -->
<attribute>
<name>item</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
</tag>
iterator-tag.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %> <html>
<head>
<title>iterator tag</title>
</head>
<body>
<%
// 创建一个 List 对象
List<String> a = new ArrayList<String>();
a.add("string 1");
a.add("string 2");
a.add("string 3");
// 将 List 对象放入 page 范围内
pageContext.setAttribute("a", a);
%>
<table border='1' width='400'>
<!-- 使用迭代器标签,对 a 集合进行迭代 -->
<mytag:iterator collection="a" item="item">
<tr>
<td>${pageScope.item}</td>
</tr>
</mytag:iterator>
</table>
</body>
</html>
IteratorTag.java
package com.baiguiren; import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Date;
import java.sql.*; import javax.servlet.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*; public class IteratorTag extends SimpleTagSupport
{
// 标签属性,用于指定需要被迭代的集合
private String collection;
// 标签属性,指定迭代集合元素,为集合元素指定的名称
private String item; public void setCollection(String collection) {
this.collection = collection;
} public String getCollection() {
return this.collection;
} public void setItem(String item) {
this.item = item;
} public String getItem() {
return this.item;
} // 标签的处理方法,在标签处理类只需要重写 doTag() 方法
public void doTag() throws JspException, IOException
{
// 从 page scope 中取出名为 collection 的集合
Collection itemList = (Collection)getJspContext().getAttribute(collection);
// 遍历集合
for (Object s : itemList) {
// 将集合的元素设置到 page 范围内
getJspContext().setAttribute(item, s);
// 输出标签体(body-content)
getJspBody().invoke(null);
}
}
}
上面的标签处理类先从 page 范围内取出指定名称的 Collection 对象,然后遍历 Collection 对象的元素,每次遍历都调用了 getJspBody() 方法,该方法返回该标签所包含的标签体:JspFragment 对象,执行该对象的 invoke() 方法,即可输出该标签的标签体内容。该标签的作用是:遍历指定集合,每遍历一个集合元素,即输出标签体一次。
因为该标签的标签体不为空,配置该标签时指定 body-content 为 scriptless。
实际上 JSTL 标签库提供了一套功能非常强大的标签,例如普通的输出标签,还有用于分支判断的标签等,JSTL 都有非常完善的实现。
以页面片段作为属性的标签
JSP2 规范的自定义标签还允许直接将一段 "页面片段" 作为属性,这种方式给自定义标签提供了更大的灵活性。
以 "页面片段" 为属性的标签与普通标签区别不大,只有两个简单的改变。
1、标签处理类中定义类型为 JspFragment 的属性,该属性代表了 "页面片段"
2、使用标签库时,通过 <jsp:attribute .../> 动作指令为标签的属性指定值。
<!-- 以页面片段作为属性的标签 -->
<tag>
<!-- 定义标签名 -->
<name>fragment</name>
<!-- 定义标签处理类 -->
<tag-class>com.baiguiren.FragmentTag</tag-class>
<!-- 指定该标签不支持标签体 -->
<body-content>empty</body-content>
<!-- 定义标签属性:fragment -->
<attribute>
<name>jspFragment</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
</tag>
fragment.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %> <html>
<head>
<title>fragment tag</title>
</head>
<body>
<h2>下面显示的是自定义标签中的内容</h2>
<mytag:fragment>
<jsp:attribute name="jspFragment">
<%-- 使用 jsp:attribute 标签传入 fragment 参数 --%>
<!-- 下面是动态的 JSP 页面内容 -->
<mytag:helloWorld/>
</jsp:attribute>
</mytag:fragment>
<br/>
<mytag:fragment>
<jsp:attribute name="jspFragment">
<!-- 下面是动态的 JSP 页面片段 -->
${pageContext.request.remoteAddr}
</jsp:attribute>
</mytag:fragment>
</body>
</html>
FragmentTag.java
package com.baiguiren; import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Date;
import java.sql.*; import javax.servlet.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*; public class FragmentTag extends SimpleTagSupport
{
private JspFragment jspFragment; public void setJspFragment(JspFragment jspFragment) {
this.jspFragment = jspFragment;
} public JspFragment getJspFragment() {
return this.jspFragment;
} public void doTag() throws JspException, IOException {
JspWriter out = getJspContext().getOut();
out.println("<div style='padding: 10px; border: 1px solid black; border-radius: 20px;'>");
out.println("<h3>下面是动态传入的 JSP 片段</h3>");
// 调用、输出 "页面片段"
jspFragment.invoke(null);
out.println("</div>");
}
}
注意:taglib 里面配置的 attribute 一定要和 jsp 里面 jsp:attribute 的 名字一样,例如上面都是 jspFragment,否则会导致莫名其妙的错误。
动态属性的标签
动态属性比普通标签多了如下两个额外要求。
1、标签处理类还需要实现 DynamicAttributes 接口
2、配置标签时通过 <dynamic-attributes .../> 子元素指定该标签支持动态属性。
配置:
<!-- 定义接受动态属性的标签 -->
<tag>
<name>dynaAttr</name>
<tag-class>com.baiguiren.DynamicAttributesTag</tag-class>
<body-content>empty</body-content>
<dynamic-attributes>true</dynamic-attributes>
</tag>
dynamic-attributes.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %> <html>
<head>
<title>支持动态属性的自定义标签</title>
</head>
<body>
<h2>下面显示的是自定义标签中的内容</h2> <h4>指定两个属性</h4>
<mytag:dynaAttr name="name" age="24" /><br/> <h4>指定四个属性</h4>
<mytag:dynaAttr name="jsp" age="12" job="developer" experience="5" />
</body>
</html>
DynamicAttributesTag.japackage com.baiguiren;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.sql.*; import javax.servlet.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*; public class DynamicAttributesTag extends SimpleTagSupport
implements DynamicAttributes
{
// 保存每个属性名的集合
private ArrayList<String> keys = new ArrayList<String>();
// 保存每个属性值的集合
private ArrayList<Object> values = new ArrayList<Object>(); public void doTag() throws JspException, IOException
{
JspWriter out = getJspContext().getOut();
// 此处只是简单地输出每个属性
out.println("<ol>");
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
Object value = values.get(i);
out.println("<li>" + key + "=" + value + "</li>");
}
out.println("</ol>");
} @Override
public void setDynamicAttribute(String uri, String localName, Object value)
throws JspException
{
// 添加属性名
keys.add(localName);
// 添加属性值
values.add(value);
}
}
JSP2 的自定义标签的更多相关文章
- JSP2的自定义标签和方法
Jsp2的自定义标签 Jsp2 开发标签库的几个步骤: 开发自定义标签处理类. 建立一个*.tld文件,每个tld文件对应一个标签库,每个标签库可对应多个标签. 在jsp文件中使用自定义标签 空标签 ...
- Jsp2.0自定义标签(第一天)——一个简单的例子
今天是学习自定义标签的第一天 Jsp2.0以来,自定义标签的实现比传统标签的实现容易了很多,一般只要extends类SimpleSupport重写doTag()方法即可. 先看最简单的例子,输出一个H ...
- JSP2.2自定义标签、EL函数
简介 JSTL是一个JSP标准标签库,可以解决大部分问题,但是如果我们需要一些更特殊的功能,就需要自定义类似JSTL中标签的标签.如果EL表达式无法满足我们的需求,我们也可以自定义EL函数. tld后 ...
- Jsp2.0自定义标签(第二天)——自定义循环标签
今天是学习自定义标签的第二天,主要是写一个自定义的循环标签. 先看效果图: 前台页面Jsp代码 <%@ page language="java" contentType=&q ...
- Jsp2.0自定义标签(第三天)——EL表达式的使用
1.提出问题: 我们经常会看到这样的jsp页面代码: 浏览器显示: 为什么会在页面输出:Hello World ,${per}究竟是如何找到“Hello World”的呢? 2.分析问题: 要想解决 ...
- JSP2.0自定义标签
JSP1.0中可以通过继承TagSupport或者BodyTagSupport来实现自定义的tag处理方法. JSP2.0中也支持另外一种更为简单的自定tag的方法,那就是直接讲JSP代码保存成*.t ...
- JSP2 自定义标签
实现步骤 实现自定义标签的处理类继承javax.servlet.jsp.tagext.SimpleTagSupport,并重写doTag方法 建立标签库配置文件 在jsp中使用自定义标签 一个简单的标 ...
- jsp2自定义标签+属性
前面说过jsp2自定义标签如果要加入属性需要设置属性的getter和setter方法.代码如下: public class GetParam extends SimpleTagSupport { pr ...
- jsp2自定义标签开篇
在JSP2中开发标签库需要以下几个步骤: 1.开发自定义标签处理类: 2.建立一个*.tld文件,每个*.tld文件对应一个标签库,每个标签库可包含多个标签: 3.在JSP文件中使用自定义标签. 第一 ...
随机推荐
- CentOS7.x安装Docker1.11.1
原文发表于cu:2016-05-30 本文属于重发,当前Docker已经分为EE与CE版本,CE版本是17.06.0-ce,最新的CE版本安装方式已略有不同:但可以指定安装版本,如1.11.1,1.1 ...
- leetcode13_C++罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并 ...
- netty初认识
Netty是什么? 本质:JBoss做的一个Jar包 目的:快速开发高性能.高可靠性的网络服务器和客户端程序 优点:提供异步的.事件驱动的网络应用程序框架和工具 通俗的说:一个好使的处理Socket的 ...
- ES6的新特性(17)——Generator 函数的异步应用
Generator 函数的异步应用 异步编程对 JavaScript 语言太重要.Javascript 语言的执行环境是“单线程”的,如果没有异步编程,根本没法用,非卡死不可.本章主要介绍 Gener ...
- 作业 20181016-1 Alpha阶段贡献分配规则
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2244 条件:八位同学,总共80分贡献分(贡献分总数以实际为准),投票方式 ...
- tensorflow之曲线拟合
视频链接:https://morvanzhou.github.io/tutorials/machine-learning/ML-intro/ 1.定义层 定义 add_layer() from __f ...
- [CF] Sasha and One More Name
题目大意 就是给一个回文串,然后进行k次分割,产生k+1个字符子串,通过重新组合这k+1个字符字串,是否会出现新的不同的回文串,且最少需要分割几段.无法产生新的回文串则输出"Impossib ...
- 如何防止app接口被别人调用
app开发的时候,如何保护app的接口呢? 用https是我想到的办法,但是不知道怎么实现,所以就考虑用token,虽然不是绝对有效,但是能防止一般的用户来攻击,高手非要攻击,只能报警了吧. toke ...
- 奇异值分解(SVD) --- 几何意义 (转载)
PS:一直以来对SVD分解似懂非懂,此文为译文,原文以细致的分析+大量的可视化图形演示了SVD的几何意义.能在有限的篇幅把 这个问题讲解的如此清晰,实属不易.原文举了一个简单的图像处理问题,简单形象, ...
- PHP中访问控制修饰符
访问控制修饰符 形式: class 类名{ 访问控制修饰符 属性或方法定义: } 有3个访问修饰符: public公共的:在所有位置都可访问(使用). protected受保护的:只能再该类内部和 ...