自定义标签

开发步骤

1.编写标签处理类

(1)传统方式(JSP1.1):实现javax.servlet.jsp.tagext.Tag接口

  • doSatrtTag():标签处理类的核心方法
    该方法有以下2个返回值:0/1
    int SKIP_BODY=0;标签体不会被执行
    int EVAL_BODY_INCLUDE=1;标签体会被执行

(2)简单方式(JSP2.0):实现javax.servlet.jsp.tagext.SimpleTag接口

  • doTag():标签执行完毕之后的方法。例如可以让标签在执行完毕后,再执行一遍
    int SKIP_PAGE=5;后面的JSP页面内容不被执行
    int EVAL_PAGE=6;后面的JSP页面内容继续执行

如果jsp在编译阶段发现了自定义标签<xx:yyy>,就会交给doStartTag()或doTag()

传统方式的核心是有缓冲区,简单方式没有

2.编写标签描述符

编写建议:可以仿照一个其他标签语言(el,jstl)的tld文件

  • < body-content >的元素值共有4个
  • Tag属性
代码示例:<?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/jsee/web-jsptagLibrary_2_0.xsd"version="2.0"><tlib-version>1.2</tlib-version><uri>标签库的url</uri><short-name>zd</short-name><!--表示标签的前缀名字类似于<jsp:forward>中的jsp-->  <tag><name>dict</name><!--表示标签的名字 类似于<jsp:forward>中的forward-->  <description>标签库描述</description><tag-class>com.zd.control.tag.DitcTag</tag-class>  <!--标签所在类 -->  <body-content>empty</body-content><!--是否存在标签体,简单标签是填scriptclass,传统标签填JSP--><!-- 标签添加参数 --><attribute><name>id</name><!-- 给select定义一个id(必须) --><required>true</required><rtexprvalue>false</rtexprvalue><!-- 说明属性不可以是一个运行时表达式(必须是一个常量String) --></attribute><attribute><name>name</name><!-- name映射(不是必须) --><required>false</required><rtexprvalue>false</rtexprvalue><!-- 说明属性不可以是一个运行时表达式(必须是一个常量String) --></attribute></tag>
</taglib>

3.导入并使用

myTag.tld(即自定义标签文件)只能导入到WEB-INF或子目录下/WEB-INF/xxx(但是不能放在WEB-INF/lib、WEB-INF/classes里)

引用具体要使用的.tld文件:

<% @taglib url=“每个tld文件的唯一标识符” prefix=""使用tld标签时的前缀 %>

具体的使用:1、空标签(没有标签体的标签)(1)<d:foreach></d:foreach>
(2)<d:foreach/>2、带标签体
<d:foreach>xxx</d:foreach>3、带属性
<d:foreach 属性名="属性值">xxx</d:foreach>4、嵌套
<d:foreach><d:foreach>xxx</d:foreach>
</d:foreach>

Tag接口中的所有方法执行顺序:

  当JSP容器(Tomcat、jetty)在将.jsp翻译成.servlet(.java)的时候,如果遇到JSP中有标签,就会依次执行setPageContext()、setParent()、doStartTag()、doEndTag、realease(),用于解析标签的执行逻辑。

javax.servlet.jsp.tagext.IterationTag接口:(Tag的子接口)

  如果有循环:IterationTag
  没有循环:Tag
  IterationTag接口中存在以下方法:
    doAfterBody():当标签体执行完毕之后的操作,通过返回值决定:
      (EVAL_BODY_AGAIN = 2):要么重复执行
      (SKIP_BODY = 0):要么不再执行

使用BodyContent修改标签显示内容

1.BoyTag接口:如果在标签体被显示之前,进行一些其他的“额外”操作

  hello hello hello -> HELLO HELLO HELLO
  int EVAL_ BODY_ BUFFERED = 2,是doStartTag() 的第三个返回值,代表一个缓冲区 (BodyContent)

2.BodyContent是abstract,具体使用时需要使用实现类BodyContentImpl (再引入jasper. jar)

  缓冲区(BodyContent)的使用用途: hello ->HELLO
  如果返回值是EVAL_ BODY _BUFFERED ,则服务器会自动将标签体需要显示的内容放入缓冲区中(BodyContent)。因此,如果要更改最终显示结果,只需要从缓冲区中获取原来的数据进行修改即可。具体就是通过getXxx()获取原来的数据(hello),自己修改(HELLO),输出getEnclosingWriter()。

简单方式

1.SimpleTag最大的简化:
  将传统方式的doStartTag()、doEndTag()、doafterBody()等方法简化成了一个通用的doTag()方法。

2.SimpleTag接口中的方法

3.简单方式没有“缓冲区”,修改内容通过流的方式修改。

  • javax.servlet.jsp.tagext.JspFragment类:代表一块JSP元素(该块不包含scriptlet,因此简单方式的tld文件中< body-content >不能是JSP)

  • JspFragment中有一个invoke(Writer var1)方法,入参是“流”,即如果要修改显示内容,只需要修改此流。每调用一次invoke()方法,会执行一次标签体。


  • SimpleTagSupport的setJspBody()方法可以获取JspFragment对象

  • SimpleTagSupport的setJspContext()方法可以获取jsp的一些内置对象:setJspContext()的返回值是JspContext对象,而该对象是JSP内置对象的入口对象PageContext的父类。

  • 条件选择:当某一个条件满足时再执行某个标签体

    • 传统标签:如果条件不满足,让doStartTag()的返回值为0
    • 简单标签:如果条件不满足,不调用invoke()即可
  • 简单标签获取JSP内置对象:

    • getJspContext() —> JspContext —> 转成子类PageContext —> PageContext就是所有JSP内置对象的入口,即可以获取一切JSP内置对象

使用简单标签实现登陆显示

代码示例: jsp表单接受用户名密码<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<body><form action="LoginServlet">用户名:<input name="username" type="text"><br>密  码:<input name="password" type="password"><br><input name="提交" type="submit"></form>
</body>
</html>
代码示例:
//show.jsp<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri ="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="https://www.xc.com" prefix="xc"%>
<%@page isELIgnored="false" %>
<html>
<head><title>Title</title>
</head>
<body><xc:login>${sessionScope.username},恭喜您登陆成功!
</xc:login>
</body>
</html>
代码示例:
//LoginServlet.javapackage com.xc.servlet;import com.xc.dao.serviceDao;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/LoginServlet")//servlet映射
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");System.out.println(username + password);serviceDao dao = new serviceDao();boolean t = dao.login(username, password);System.out.println(t);if (t) {//登陆成功将当前用户保存到session中req.getSession().setAttribute("username", username);req.getRequestDispatcher("show.jsp").forward(req,resp);} else {//跳转到失败页面System.out.println("登录失败!");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("=====调用doPost()方法=====");}
}
代码示例:
//serviceDao.javapackage com.xc.dao;
import com.xc.Util.DBUtils;import java.sql.*;public class serviceDao {public Connection conn = null;public PreparedStatement pt = null;public boolean login(String username, String password) {ResultSet rs = null;boolean t = false;Connection conn = DBUtils.getConnection();//解决sql注入利用PreparedStatement//PreparedStatement允许在sql语句中使用占位符?//PreparedStatement的优点//1.解决sql注入//2.提高程序的可读性和可维护性//3.执行效率高String sql = "select * from user where username=? and password=?";try {pt = conn.prepareStatement(sql);//执行sql语句之前需要给参数赋值System.out.println(username+password);pt.setString(1,username);pt.setString(2,password);//执行sql语句rs = pt.executeQuery();if(rs.next()) {t = true;}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}if(rs!=null) {try {rs.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(pt!=null) {try {pt.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(conn!=null) {try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return t;}}
代码示例:
//LoginTag.java
(标签处理类)package com.xc.tag;import com.xc.entity.User;import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.util.List;public class LoginTag extends SimpleTagSupport {@Overridepublic void doTag() throws JspException, IOException {//判断是否已经登陆成功,如果成功执行标签体,若失败则不执行.PageContext pageContext = (PageContext) getJspContext();HttpSession session = pageContext.getSession();List<User> user = (List<User>) session.getAttribute("user");if (user != null){//执行一次标签体getJspBody().invoke(null);}}
}
代码示例:
//mySimpleTag.tld<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"version="2.1"><tlib-version>1.2</tlib-version><short-name>mySimpleTag</short-name><uri>https://www.xc.com</uri><tag><name>login</name><!--表示标签的名字 类似于<jsp:forward>中的forward--><tag-class>com.xc.tag.LoginTag</tag-class>  <!--标签所在类 --><body-content>scriptless</body-content></tag>
</taglib>
代码示例:
//show.jsp<%--Created by IntelliJ IDEA.User: asusDate: 2021/11/23Time: 17:40To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri ="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="https://www.xc.com" prefix="xc"%>
<%@page isELIgnored="false" %>
<html>
<head><title>Title</title>
</head>
<body><xc:login>${sessionScope.username},恭喜您登陆成功!
</xc:login>
</body>
</html>

测试截图:


记录问题
低版本的jsp不解析el表达式,使用时须小心。

Servlet2.3或者更早的JSP页面默认是不使用EL表达式的,即不解析EL表达式,所以要不就是使用更高版本的jsp servlet。这样比较麻烦,这里Java提供了一各属性来解决这个问题,使2.3或更早版本能使用El表达式,该属性为<%@page isELIgnored=“false” %>默认是true,表示暂时不解析,此时我们在jsp页面头文件中设置为false,再次运行,此时jsp页面就会解析El表达式

JavaWeb学习笔记(十九)之自定义标签相关推荐

  1. javaweb学习总结(十九):JSP标签

    一.JSP标签介绍 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 二.JSP常用标签 ...

  2. 转载:javaweb学习总结(二十三)——jsp自定义标签开发入门

    javaweb学习总结(二十三)--jsp自定义标签开发入门 转自:http://www.cnblogs.com/xdp-gacl/p/3916734.html 一.自定义标签的作用 自定义标签主要用 ...

  3. Polyworks脚本开发学习笔记(十九)-将数据对象与参考对象对齐的方法

    Polyworks脚本开发学习笔记(十九)-将数据对象与参考对象对齐的方法 把开发手册理了一遍,发现还有几个点没有记录下来,其中一个就是使用点对的粗对齐和使用参考目标的精确对齐.为了把这个学习笔记凑够 ...

  4. Mr.J-- jQuery学习笔记(十九)--自定义动画实现图标特效

    之前有写过自定义动画Mr.J-- jQuery学习笔记(十八)--自定义动画 这次实现一个小demo 图标特效 页面渲染 <!DOCTYPE html> <html lang=&qu ...

  5. javaweb学习总结(二十三)——jsp自定义标签开发入门

    一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 packag ...

  6. angular学习笔记(十九)-自定义指令修改dom

    使用angular指令可以自己扩展html语法,还可以做很多自定义的事情.在后面会专门讲解这一块的知识,这一篇只是起到了解入门的作用. 与控制器,过滤器,服务,一样,可以通过模块实例的directiv ...

  7. javaweb学习总结(十九)——JSP标签

    一.JSP标签介绍 JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护. 二.JSP常用标签 ...

  8. html图片多热点怎么弄,CSS学习笔记(十五) 使用map标签实现单图多热点

    map标签 定义一个客户端图像映射.图像映射(image-map)指带有可点击区域的一幅图像. area元素永远嵌套在map元素内部.area元素可定义图像映射中的区域. img标签中的usemap属 ...

  9. 步步为营 .NET 设计模式学习笔记 十九、Chain of Responsibility(职责链模式)

    概述 在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合. 如何使请求的发送者不需要指定具体的接受者?让请求的 ...

  10. 【theano-windows】学习笔记十九——循环神经网络

    前言 前面已经介绍了RBM和CNN了,就剩最后一个RNN了,抽了一天时间简单看了一下原理,但是没细推RNN的参数更新算法BPTT,全名是Backpropagation Through Time. [注 ...

最新文章

  1. 面向对象编程的乐趣(TextBox.Text=)
  2. python从入门到精通书-清华大学出版社-图书详情-《Python从入门到精通》
  3. 无人机是计算机什么方面的应用,无人机测绘可以应用到哪些方面呢?
  4. QT的QProxyStyle类的使用
  5. 【Linux网络】Linux Socket编程 TCP协议
  6. repo-关于URL编码
  7. jvm ide_通过微调JVM Garbage Collector减少Java IDE滞后
  8. Python3.x中Django-xadmin的添加
  9. 西安python后端招聘_有大佬招 Python 后端初级人员吗?
  10. TV TimeShift和PVR的区别
  11. NLP之:百度SKEP
  12. (六省)蓝桥真题 奇妙的数字
  13. 地铁运营行车组织方式
  14. 《为你打开一扇门》| 赵丽宏
  15. CSP 2017-12
  16. 产品经理02_竞品分析
  17. 内网穿透实现P2P通信
  18. 成人统考《计算机基础》模拟考试题目及答案(access部分,2012年计算机二级Access第五十套上机试题及答案详解...
  19. android获取当前系统语言
  20. Flask实现微博画像采集小工具

热门文章

  1. 布隆过滤器(Bloom Filter)算法
  2. Linux(3) Vim编辑器
  3. PostgreSQL:trunc函数
  4. 虚拟机(虚拟机 +系统镜像)资源
  5. iOS集成环信SDK点击聊天图片无效问题
  6. 【游戏】光棍节程序员闯关秀过关攻略
  7. python三个数输出最小值_从键盘输入三个数,输出其中的最大值和最小值。_学小易找答案...
  8. 传教士与野人问题的C++搜索实现
  9. Python--turtle之幸运星
  10. java如何实现群聊_Java实现通过服务器实现客户端之间的简单群聊