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脚本片段,下面 ...
随机推荐
- 用JSR的@Inject代替@Autowired完成自动装配
从spring3.0开始spring支持JSR-330 的标准注解.主要是javax.inject这个包下的: 下面的例子用@Inject代替@Autowired.完成自动装配: MovieFinde ...
- hive subprocess failed with code X 的错误码对应信息
PipeMapRed.waitOutputThreads(): subprocess failed with code X ,这里code X对应的信息如下:error code 1: Operati ...
- Maven 标准目录结构
Maven 标准目录结构 好的目录结构可以使开发人员更容易理解项目,为以后的维护工作也打下良好的基础.Maven2根据业界公认的最佳目录结构,为开发者提供了缺省的标准目录模板.Maven2的标准目录结 ...
- Drac6-Web界面无法访问
1. ssh idracip, and reset RAC -- will need around 10mins /admin1-> racadm racreset RAC reset oper ...
- 【CF1027F】Session in BSU(dsu,基环树)
题意:给出n场考试,每场考试有2天可以通过(第ai与bi天).每天最多参加一场考试,现在要求所有考试全部通过的最小天数 n<=1e6,1<=a[i]<b[i]<1e9 思路:F ...
- HTML5之FileReader的简易使用
用来把文件读入内存,并且读取文件中的数据.FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据.FileReader接口提供了读取文件的方法 ...
- bzoj 2748 DP
比较裸的背包,w[i][j]代表到第I个操作的时候音量j能不能达到,然后转移就行了. /******************************************************** ...
- mysql五:数据操作
一 介绍 MySQL数据操作: DML ======================================================== 在MySQL管理软件中,可以通过SQL语句中的 ...
- 关于C++编译的程序无法在新一台电脑上运行总结
最近在调用一个SDK调试一个主板的DPIO. 可是编译好的程序在开发电脑上运行没问题,到了新主板建立的电脑系统上就出问题. 总结了下要注意一下几方面. 1:程序本身要没有问题.至少在开发电脑系统环境下 ...
- Navigator与UserAgent笔记
关于Navigator与UserAgent笔记 1.Navigator笔记 Navigator对象主要是包含有关客户端浏览器的一些信息,Navigator对象是由JavaScript runtime ...