一、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自定义标签的更多相关文章

  1. 重温JSP学习笔记--JSP动作标签

    上一篇笔记写的是jsp的三个指令九个内置对象,这篇随笔开始写jsp的动作标签,动作标签是由服务器(Tomcat)来解释执行,与java代码一样,都是在服务器端执行的,jsp动作标签有十几多个,这里只写 ...

  2. 学习笔记_Java_day13_JSTL_自定义标签库(9)

    自定义标签 1 自定义标签概述 1.1 自定义标签的步骤 其实我们在JSP页面中使用标签就等于调用某个对象的某个方法一样,例如:<c:if test=””>,这就是在调用对象的方法一样.自 ...

  3. Android学习笔记_41_TabHost自定义标签和TraceView性能测试

    一.tabhost第一种用法,通过在帧布局放入定义好的page页面来实现,这样导致在当前activity下代码量比较大. 1.页面布局: |        |        |        |    ...

  4. JavaWeb学习笔记——JSP标准标签库JSTL

  5. 学习笔记|JSP教程|菜鸟教程

    学习笔记|JSP教程|菜鸟教程 ------------------------------------------------------------------------------------ ...

  6. JSP 自定义标签

    0 标签技术的API继承体系 1 作用 jsp自定义标签用于移除页面中的java代码 2 实现 2.1 标签处理类ViewIPTag.java package com.zsm.util; import ...

  7. 【转】Jsp自定义标签详解

    一.前言 原本是打算研究EXtremeComponents这个jsp标签插件,因为这个是自定义的标签,且自身对jsp的自定义标签并不是非常熟悉,所以就打算继续进行扫盲,开始学习并且整理Jsp自定义标签 ...

  8. 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 ...

  9. JavaWeb学习篇之----自定义标签&&JSTL标签库详解

    今天来看一下自定义标签的内容,自定义标签是JavaWeb的一部分非常重要的核心功能,我们之前就说过,JSP规范说的很清楚,就是Jsp页面中禁止编写一行Java代码,就是最好不要有Java脚本片段,下面 ...

随机推荐

  1. sls文件

    http://www.ituring.com.cn/article/42238 只是数据而已 深入学习之前,明白SLS文件只是结构化的数据而已是很有用的.看懂和编写SLS文件不需要理解这一点,但会让你 ...

  2. 解决“并非来自 Chrome 网上应用店。”

    Chrome谷歌浏览器已停用不支持的扩展程序解决方法 第一种方法:(亲测有效) 1.首先把需要安装的第三方插件,后缀.crx 改成 .rar,然后解压,得到一个文件夹 2.再打开chrome://ex ...

  3. Firefox多国语言多OS离线安装包

    Download Firefox in your language Firefox is made in large part by volunteers around the world. That ...

  4. bootstrap再次回顾认识到的东西

    1,需要使用html5文档类型(Doctype),因此在使用bootstrap项目的开头包含下面的代码段. <!DOCTYPE html> <html> ....... < ...

  5. [USACO07FEB]新牛棚Building A New Barn

    洛谷题目链接:[USACO07FEB]新牛棚Building A New Barn 题目描述 After scrimping and saving for years, Farmer John has ...

  6. java三

    1,深复制与浅复制 浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. 深复制:被复制对象 ...

  7. 【sgu390】数位dp

    这题其实就是不断地合并子树,跟前面例一的思想是一样的. 这个打法我觉得非常优美啊(学别人的),为什么要搞lim1和lim2呢? 是因为在区间lim1~lim2之外的都是没有用的,但是我们f[h][su ...

  8. [NOIP2017]列队 (Splay)

    题目链接 NOIP2017真的是不按常理出牌: 1.数学题不在Day2T1 2.一道水题一道细节极多的模拟题一道不知道怎么形容的题(小凯的疑惑)(因为我太菜了) 3.3道大火题 当时看到列队这题是毫无 ...

  9. [bzoj2152]聪聪可可——点分治

    Brief Descirption 给定一棵带权树,您需要统计路径长度为3的倍数的路径长度 Algorithm Analyse 点分治. 考察经过重心的路径.统计出所有deep,统计即可. Code ...

  10. 利用opencv自带源码,调试摄像头做人脸检测

    本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring 和 http://www.cnblogs.com/xujianqing/ 作者: ...