1.4(学习笔记)JSP自定义标签
一、JSP自定义标签
JSP自定义标签,可以通过实现Tag接口、继承TagSupport类来设置标签功能。
后续通过配置文件将标签和具体的实现类关联。
二、自定义第一个标签(实现Tag接口)
自定义标签需要先创建一个Java类,然后实现Tge接口或者继承S.....类
我们先来看实现接口这种方法自定义标签:
2.1创建Java类
HelloTag.java
import java.io.IOException; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag; public class HelloTag implements Tag { private PageContext pageContext; @Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
System.out.println("endTag");
return EVAL_PAGE;//继续显示该标签后续内容
} @Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
String msg = "MyTag";
JspWriter out = pageContext.getOut();
try {
out.println(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("startTag");
return EVAL_BODY_INCLUDE;//显示标签体中的内容
} @Override
public Tag getParent() {
// TODO Auto-generated method stub
return null;
} @Override
public void release() {
// TODO Auto-generated method stub
} @Override
public void setPageContext(PageContext pageContext) {
// TODO Auto-generated method stub
//获取JSP页面的pageContext
this.pageContext = pageContext;
System.out.println("pageContext");
} @Override
public void setParent(Tag arg0) {
// TODO Auto-generated method stub
} }
2.2创建好java类后,需要创建配置文件
2.2.1创建my_tag_config.tld文件
在WEB-INF文件夹下新建XML文件。

将.xml改为.tld(结果如下图所示)

点击next,进入如下页面。(结果如下图所示)

点击next(结果如下图所示)

点击next,(效果如下图所示)

点击finish,创建结束。
打开创建好的文件,效果如下图所示。

接着我们就要对其进行配置,将标签和我们创建的类关联。
<?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>1.2</jsp-version>
<short-name>short-name</short-name> <!-- 此处的uri只是一个标识,可任意指定,后续JSP页面中引用时保持一致即可 -->
<uri>http://www.myTag.com</uri> <tag>
<name>hello</name> <!-- 设置标签名 -->
<tag-class>com.myTag.HelloTag</tag-class> <!-- 设置标签名关联类 -->
<body-content>JSP</body-content> <!-- 指定标签体显示格式 -->
</tag>
</taglib>
其中<body-content>中的属性有四种:
tagdependent,empty,JSP,
各个属性的含义可参阅:https://www.cnblogs.com/keyi/p/7127685.html
以上都配置好了后,我们就来使用标签。
tag.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <!-- 指定需要使用标签的URi和前缀 -->
<%@ taglib uri="http://www.myTag.com" prefix = "m" %> <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<m:hello>include body</m:hello>
</body>
</html>

自定义标签的功能是输出“MyTag”,结果正常输出。
我们来看下控制台的输出:

最后我们分析下标签的执行流程
我们看下tag.jsp生存的servlet中的代码:

Servlet中调用了一个方法,我们来看下这个方法

查看代码可以很清楚的看到自定义标签的执行流程。
三、自定义out标签(继承TagSupport类实现)
java类
import java.io.IOException; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport; public class HelloTagEx extends TagSupport {
private String value;
private JspWriter out; public void setValue(String value) {//设置值
this.value = value;
} @Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
//不重写setPageContext方法,也可直接使用pageContext
// 例如: this.out = pageContext.getOut();
try {
out.println(value); //将设置的value输出
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return SKIP_BODY;//不输出标签体中内容
} @Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
return SKIP_PAGE;//不输出界面后续内容
} @Override
public int doAfterBody() throws JspException {
// TODO Auto-generated method stub return super.doAfterBody();
} @Override //此方法也可以不重写,在doStartTag、doEndTag中可以直接使用pageContext
public void setPageContext(PageContext pageContext) {
this.pageContext = pageContext;
this.out = pageContext.getOut();
}
}
标签配置:
<tag>
<name>helloEx</name>
<tag-class>com.myTag.HelloTagEx</tag-class>
<body-content>JSP</body-content> <attribute>
<name>value</name> <!-- 属性名要和类中属性名对应 -->
<required>true</required> <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
<rtexprvalue>true</rtexprvalue> <!-- 能否使用表达式赋值 true表示可以用表达式-->
</attribute>
</tag>
tag.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <!-- 指定需要使用标签的URi和前缀 -->
<%@ taglib uri="http://www.myTag.com" prefix = "m" %> <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<m:helloEx value="123">ss</m:helloEx>
endTag方法返回值是SKIP_PAGE,不输出后续界面,所以这句话不会输出。
</body>
</html>

四、自定义if标签
有了前面两个作为基础,后面的就很简单了。
标签类
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport; public class IF extends TagSupport{
private boolean flag; public void setFlag(boolean flag) {
this.flag = flag;
} @Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
if(flag == true) {//如果为true,标签体中内容执行,反正不执行。
return EVAL_BODY_INCLUDE;
}else {
return SKIP_BODY;
}
} @Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
return EVAL_PAGE;//IF标签结束后,继续执行页面内容
} }
配置:
<tag>
<name>IF</name>
<tag-class>com.myTag.IF</tag-class>
<body-content>JSP</body-content> <attribute>
<name>flag</name> <!-- 属性名要和类中属性名对应 -->
<required>true</required> <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
<rtexprvalue>true</rtexprvalue> <!-- 能否使用表达式赋值 true表示可以用表达式-->
</attribute>
</tag>
tag.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <!-- 指定需要使用标签的URi和前缀 -->
<%@ taglib uri="http://www.myTag.com" prefix = "m" %> <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<m:IF flag="${3>2}">
true
</m:IF>
</body>
</html>

五、自定义foreach标签
标签类:ForEach.java
import java.util.Iterator;
import java.util.List; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport; public class ForEach extends TagSupport { private List<String> list;
private String var; public void setList(List<String> list) {
this.list = list;
} public void setVar(String var) {
this.var = var;
} @Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
if(list == null) {
return SKIP_BODY;
}else {
Iterator<String> items = list.iterator();
pageContext.setAttribute("ite", items);
pageContext.setAttribute("list", list);
//由于doStartTage方法结束后是输出标签体,
//而标签体中有${var}表达式用于输出迭代对象
//所以此处最好先拿出一个对象。
if(items.hasNext()) {//如果迭代器中有元素,设置值,并输出标签体
pageContext.setAttribute(var, items.next());
return EVAL_BODY_INCLUDE;
}else {//反之则不输出标签体
return SKIP_BODY;
} }
} @Override
public int doAfterBody() throws JspException {
// TODO Auto-generated method stub
//获取迭代器
Iterator<String> items = (Iterator<String>)pageContext.getAttribute("ite");
if(items.hasNext()) {//将其中元素取出,并设置。
String value = (String) items.next();
pageContext.setAttribute(var, value);
return EVAL_BODY_AGAIN; //再一次执行标签体
}else {
return SKIP_BODY; //迭代器为空,则停止输出标签体
}
} @Override
public int doEndTag() throws JspException {//结束标签后的内容继续输出
// TODO Auto-generated method stub
return EVAL_PAGE;
}
}
配置:
<tag>
<name>FOREACH</name>
<tag-class>com.myTag.ForEach</tag-class>
<body-content>JSP</body-content> <attribute>
<name>var</name> <!-- 属性名要和类中属性名对应 -->
<required>true</required> <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
<rtexprvalue>false</rtexprvalue> <!-- 能否使用表达式赋值 false表示不可以用表达式-->
</attribute> <attribute>
<name>list</name> <!-- 属性名要和类中属性名对应 -->
<required>true</required> <!-- 该属性是否为必填项 true 代表为必填,不填会报错 -->
<rtexprvalue>true</rtexprvalue> <!-- 能否使用表达式赋值 true表示可以用表达式-->
</attribute> </tag>
tag.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import = "java.util.*" %>
<!-- 指定需要使用标签的URi和前缀 -->
<%@ taglib uri="http://www.myTag.com" prefix = "m" %> <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body> <%
List<String> list = new ArrayList<String>();
for(int i = 0; i < 5 ; i++){
list.add("str" + i);
}
pageContext.setAttribute("list", list);
%>
<m:FOREACH list="${list}" var="s">
${s}
</m:FOREACH>
</body>
</html>

foreach主要通过表达式将list对象传递到ForEach.java中,
在ForEach.java中主要通过doAfterBody()方法,将迭代器中元素
通过pageSetAttribute()设置到page中,然后输出${var},输出的表达式又会自动获取设置的值,
然后往复输出执行doAfterBody()方法,并且输出标签体(表达式${var}),来实现foreach。
直到迭代器元素全部输出,方法才终止。
那个doAfterBody()和return EVAL_BODY_AGAIN配合的流程可能不太好理解,
我们来看下tag.jsp生成的Servlet中的代码就很好理解了。


执行顺序为(不考虑后续输出终止情况):
doStartTag->标签体内容->doAfterBody->doEndTag
<xx> 标签开始(doStartTag)
xxxxxx 标签体
doAfterBody判断是否继续输出标签体(doAfterBody方法也可看作标签体的一部分)
</xx> 标签结束(doEndTag)
参考资料:
https://blog.csdn.net/qq_42246139/article/details/80623607
https://blog.csdn.net/qq_41815326/article/details/81356733
1.4(学习笔记)JSP自定义标签的更多相关文章
- 重温JSP学习笔记--JSP动作标签
上一篇笔记写的是jsp的三个指令九个内置对象,这篇随笔开始写jsp的动作标签,动作标签是由服务器(Tomcat)来解释执行,与java代码一样,都是在服务器端执行的,jsp动作标签有十几多个,这里只写 ...
- 学习笔记_Java_day13_JSTL_自定义标签库(9)
自定义标签 1 自定义标签概述 1.1 自定义标签的步骤 其实我们在JSP页面中使用标签就等于调用某个对象的某个方法一样,例如:<c:if test=””>,这就是在调用对象的方法一样.自 ...
- Android学习笔记_41_TabHost自定义标签和TraceView性能测试
一.tabhost第一种用法,通过在帧布局放入定义好的page页面来实现,这样导致在当前activity下代码量比较大. 1.页面布局: | | | | ...
- JavaWeb学习笔记——JSP标准标签库JSTL
- 学习笔记|JSP教程|菜鸟教程
学习笔记|JSP教程|菜鸟教程 ------------------------------------------------------------------------------------ ...
- JSP 自定义标签
0 标签技术的API继承体系 1 作用 jsp自定义标签用于移除页面中的java代码 2 实现 2.1 标签处理类ViewIPTag.java package com.zsm.util; import ...
- 【转】Jsp自定义标签详解
一.前言 原本是打算研究EXtremeComponents这个jsp标签插件,因为这个是自定义的标签,且自身对jsp的自定义标签并不是非常熟悉,所以就打算继续进行扫盲,开始学习并且整理Jsp自定义标签 ...
- ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则
ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...
- JavaWeb学习篇之----自定义标签&&JSTL标签库详解
今天来看一下自定义标签的内容,自定义标签是JavaWeb的一部分非常重要的核心功能,我们之前就说过,JSP规范说的很清楚,就是Jsp页面中禁止编写一行Java代码,就是最好不要有Java脚本片段,下面 ...
随机推荐
- 1、linux下mysql5.5.20安装过程报错汇总
1.Access denied for user 'root'@'localhost' (using password: YES) 这个提示是因为root帐户默认不开放远程访问权限,所以需要修改一下相 ...
- 【Foreign】染色 [LCT][线段树]
染色 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output Sample Input 13 0 1 0 2 1 11 1 ...
- OOP第三次上机
上机问题 T1 CSet 还是熟悉的CSet,只是多了个构造函数以及收缩空间. T2 SingleTon 单例问题. 用一个指针保存唯一的实例,用户无法在外部直接新建实例,只能使用外部接口(函数),函 ...
- [Leetcode Week7]Jump Game
Jump Game 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/jump-game/description/ Description Given a ...
- HTTP===通用首部字段的各种指令解释
Cache-Control 通过指定首部字段 Cache-Control 的指令,就能操作缓存的工作机制. 指令的参数是可选的,多个指令之间通过“,”分隔.首部字段 Cache-Control 的指令 ...
- CSS边框属性
边框 圆角 border-radius border-top-left-radius border-top-right-radius border-bottom-left-radlius border ...
- 【转】java中的集合和数组
转载自:http://www.cnblogs.com/summers/p/4094260.html 数组Array和集合的区别: (1)数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型 ...
- P1709 [USACO5.5]隐藏口令Hidden Password
P1709 [USACO5.5]隐藏口令Hidden Password 题目描述 有时候程序员有很奇怪的方法来隐藏他们的口令.Binny会选择一个字符串S(由N个小写字母组成,5<=N<= ...
- Scanner类的个人分析
Scanner类读取键盘输入(java中Scanner类nextLine()和next()的区别和使用方法&&java 中的Scanner(非常详细不看后悔)): 2017/3/18 ...
- rest_framework 访问频率(节流)流程
访问频率流程 访问频率流程与认证流程非常相似,只是后续操作稍有不同 当用发出请求时 首先执行dispatch函数,当执行当第二部时: #2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进 ...