jsp 自定义标签

jsp 自定义标签.tld 文件说明

jsp 描述性文件.tld

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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>WensTaglib</short-name>
<!-- 定义该标签库的URI -->
<uri>https://oa.wens.com.cn/taglib</uri>
<tag>
<description>first tag</description>
<!-- 定义标签名 -->
<name>showSystemTime</name>
<!-- 定义标签处理类 -->
<tag-class>weaver.interfaces.wens.jdpurchase.test.ShowSystemTime</tag-class>
<!-- 定义标签体为空 -->
<body-content>empty</body-content>
</tag>
</taglib>

注意:将该 tld 描述性文件复制到 Web 应用的 WEB-INF/ 路径,或 WEB-INF 的任意子路径下

1. taglib 下有三个子元素:

  • tlib-version:指定该标签库实现的版本,这是一个作为标识的内部版本号,对程序没有太大的作用。
  • short-name:该标签库的默认短名,该名称通常也没有太大的用处。
  • uri:这个属性非常重要,它指定该标签库的 URI,相当于指定该标签库的唯一标识。JSP 页面中使用标签库时就是根据该 URI 属性来定位标签库的。

2. taglib 元素下可以包含多个 tag 元素,每个 tag 元素定义一个标签,tag 元素下至少应包含如下三个子元素:

  • name:该标签库的名称,这个属性很重要,JSP 页面中就是根据该名称来使用此标签。
  • tag-class:指定标签的处理类,毋庸置疑,这个属性非常重要,指定了标签由哪个 Java 类来处理。
  • body-content:这个属性也很重要,它指定标签体内容。该元素的值可以是如下几个:
    • tagdependent:指定标签处理类自己负责处理标签体。
    • empty:指定该标签只能作用空标签使用。
    • scriptless:指定该标签的标签体可以是静态 HTML 元素,表达式语言,但不允许出现 JSP 脚本。
    • JSP:指定该标签的标签体可以使用 JSP 脚本。

3. 简单标签既没有属性,也没有标签体,用法、功能都比较简单。实际上还有如下两种常用的标签:

  • 带属性的标签。
  • 带标签体的标签。

注意: 带属性标签必须为每个属性提供对应的 setter 和 getter 方法。带标签体的标签,可以在标签内嵌入其他内容(包括静态的 HTML 内容和动态的 JSP 内容),通常用于完成一些逻辑运算,例如判断和循环等。

jsp 自定义标签之 TagSupport,BodyTagSupport(不推荐)

TagSupport,BodyTagSupport 自定义 jsp 标签是 jsp1.0 版本的功能,自定义标签比 jsp2.0 较难理解而且繁琐,推荐使用 jsp2.0 自定义标签。

自定义标签开发步骤

  1. 第一步,编写标签处理类,继承自 TagSupport
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.bin.tag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
* @author Hugo Black
* 自定义标签
*/
public class LoginDateTag extends TagSupport {
@Override
public int doStartTag() throws JspException {
Calendar calendar = Calendar.getInstance();
Date currentTime = calendar.getTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
String time = simpleDateFormat.format(currentTime);
try {
pageContext.getOut().print(time);
} catch (IOException e) {
e.printStackTrace();
}
return super.doStartTag();
}
}
  1. 第二步,定义标签库描述文件,放在 WEB-INF 根目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8" ?>

<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>simple</short-name>
<uri>/my-tag</uri>

<tag>
<name>loginDate</name>
<tag-class>com.bin.tag.LoginDateTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
  1. 第三步,在 jsp 中引入定义声明自定义标签, 使用标签
1
2
<%@ taglib prefix="cxb" uri="/my-tag"%>
<cxb:loginDate/>

控制标签体内容显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.bin.tag;

import javax.servlet.jsp.tagext.TagSupport;

/**
* @author Hugo Black
* 控制标签体内容显示
*/
public class SkipBodyOrEvalBodyIncludeTag extends TagSupport{
@Override
public int doStartTag() {
String name = pageContext.getRequest().getParameter("name");
String hello = "hello";
//name为空不显示标签体内容
if(name==null || hello.equals(name)){
return SKIP_BODY;
}else {
return EVAL_BODY_INCLUDE;
}
}
}

控制是否执行标签结束后的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.bin.tag;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;

/**
* @author Hugo Black
* 控制是否执行标签结束后的内容
*/
public class SkipPageOrEvalPageTag extends TagSupport {
@Override
public int doEndTag(){
HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();
String referer = httpServletRequest.getHeader("referer");
String url = "http://"+ httpServletRequest.getServerName();
if(referer!=null && referer.startsWith(url)){
return EVAL_PAGE;
}else {
try {
pageContext.getOut().print("不能访问");
} catch (IOException e) {
e.printStackTrace();
}
return SKIP_PAGE;
}
}

}

自定义标签的属性

编写标签处理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.bin.tag;

import com.bin.entity.Employee;
import com.bin.util.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

/**
* @author Hugo Black
* 定义标签属性
*/
public class AttributeTag extends TagSupport{
private String sql;

public void setSql(String sql) {
this.sql = sql;
}

@Override
public int doEndTag(){
QueryRunner qr = JdbcUtils.getQueryRuner();
List<Employee> list;
try {
list = qr.query(sql, new BeanListHandler<>(Employee.class));
for(Employee employee: list){
pageContext.getOut().println(employee.toString());
}
return EVAL_PAGE;
} catch (SQLException | IOException e) {
e.printStackTrace();
return SKIP_PAGE;
}
}
}

在 WEB-INF 根目录的标签库描述文件增加以下内容

1
2
3
4
5
6
7
8
9
10
<tag>
<name>ConnectionTag</name>
<tag-class>com.bin.tag.AttributeTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>sql</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>

使用标签

  • 属性值为正常字符串
1
<cxb:ConnectionTag sql="select * from employee"></cxb:ConnectionTag>
  • 属性值为 el 表达式
1
2
3
4
5
6
<%
String sql = "select * from employee";
pageContext.setAttribute("sql", sql);
%>

<cxb:ConnectionTag sql="${sql}"></cxb:ConnectionTag>

修改标签体的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.bin.tag;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.io.IOException;

/**
* @author Hugo Black
* 修改标签体内容
*/
public class BodyTagSupportDemo extends BodyTagSupport {

@Override
public int doEndTag() {
String content = this.bodyContent.getString();
System.out.println(content);

String newStr = "hello world";
JspWriter jspWriter = bodyContent.getEnclosingWriter();
try {
jspWriter.write(newStr);
} catch (IOException e) {
e.printStackTrace();
}
return EVAL_PAGE;
}
}

jsp 自定义标签之 Simple(推荐)

自定义标签开发步骤

  1. 第一步,编写标签处理类,继承自 SimpleTagSupport
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.bin.tag.simple;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
* @author Hugo Black
* 自定义标签
*/
public class LoginDateTag extends SimpleTagSupport {
@Override
public void doTag() throws IOException {
Calendar calendar = Calendar.getInstance();
Date currentTime = calendar.getTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = simpleDateFormat.format(currentTime);

JspWriter jspWriter = this.getJspContext().getOut();
jspWriter.write(time);
}
}
  1. 第二步,定义标签库描述文件,放在 WEB-INF 根目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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">

<description>jsp自定义标签2.0</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>/my-tag2</uri>

<tag>
<name>loginDate</name>
<tag-class>com.bin.tag.simple.LoginDateTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
  1. 第三步,在 jsp 中引入定义声明自定义标签, 使用标签
1
2
<%@ taglib prefix="cxb2" uri="/my-tag2" %>
<cxb2:loginDate/>

显示或者忽略标签体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.bin.tag.simple;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;

/**
* @author Hugo Black
* 显示或者忽略标签体
*/
public class DisplayOrSkipBody extends SimpleTagSupport {
@Override
public void doTag() throws IOException, JspException {
PageContext pageContext = (PageContext) this.getJspContext();
String name = pageContext.getRequest().getParameter("name");
String hello= "hello";
if(name!=null && name.equals(hello)){
this.getJspBody().invoke(null);
}

super.doTag();
}
}

显示或忽略标签体后的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.bin.tag.simple;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;

/**
* @author Hugo Black
* 显示或忽略标签体后的内容
*/
public class SkipOrEvalPage extends SimpleTagSupport{
@Override
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) this.getJspContext();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
String referer = request.getHeader("referer");
if(referer == null){
throw new SkipPageException();
}
super.doTag();
}
}

迭代标签体内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.bin.tag.simple;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;

/**
* @author Hugo Black
* 迭代标签体内容
*/
public class InterationTagBody extends SimpleTagSupport {
private String[] items;
private String var;
private int i = 1;

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

public void setVar(String var) {
this.var = var;
}

public void setI(int i) {
this.i = i;
}

@Override
public void doTag() throws JspException, IOException {
if (items != null && items.length > 0) {
PageContext pageContext = (PageContext) this.getJspContext();
for (int i = 0; i < items.length; i++) {
pageContext.setAttribute("name", items[i]);
getJspBody().invoke(null);
}
}
}
}

修改标签体内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.bin.tag.simple;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.io.StringWriter;

/**
* @author Hugo Black
* 修改标签体内容
*/
public class ModifyTagBodyContent extends SimpleTagSupport{
@Override
public void doTag() throws JspException, IOException {
StringWriter stringWriter = new StringWriter();
JspFragment jspFragment = this.getJspBody();
jspFragment.invoke(stringWriter);
String content = stringWriter.toString();
content = "hello word";
PageContext pageContext = (PageContext)getJspContext();
pageContext.getOut().write(content);
super.doTag();
}
}

总结:自定义标签有以下四个功能:

  1. 控制标签内容是否显示
  2. 控制标签结束后的代码是否执行
  3. 控制标签体内容重复执行
  4. 改变标签体内容再输出

注意:jsp2.0 中的描述性文件.tld中的<body-content>scriptless</body-content>的内容不能为 JSP。

文章目录
  1. 1. jsp 自定义标签.tld 文件说明
    1. 1.1. jsp 描述性文件.tld
  2. 2. jsp 自定义标签之 TagSupport,BodyTagSupport(不推荐)
    1. 2.1. 自定义标签开发步骤
    2. 2.2. 控制标签体内容显示
    3. 2.3. 控制是否执行标签结束后的内容
    4. 2.4. 自定义标签的属性
      1. 2.4.1. 编写标签处理类
      2. 2.4.2. 在 WEB-INF 根目录的标签库描述文件增加以下内容
      3. 2.4.3. 使用标签
    5. 2.5. 修改标签体的内容
  3. 3. jsp 自定义标签之 Simple(推荐)
    1. 3.1. 自定义标签开发步骤
    2. 3.2. 显示或者忽略标签体
    3. 3.3. 显示或忽略标签体后的内容
    4. 3.4. 迭代标签体内容
    5. 3.5. 修改标签体内容
| 45.9k | |