JSP自定义标签【下】

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
应用实时监控服务-用户体验监控,每月100OCU免费额度
简介: JSP自定义标签是指在JSP页面中自定义的标签,其实现原理是基于Servlet中的可重用HTTP方法、过滤器进行封装,以达到在JSP页面中调用的效果。在JSP中自定义标签的好处是可以,使JSP页面看起来了。

一、自定义标签的简单概述

JSP自定义标签是指在JSP页面中自定义的标签,其实现原理是基于Servlet中的可重用HTTP方法、过滤器进行封装,以达到在JSP页面中调用的效果。在JSP中自定义标签的好处是可以将复杂的业务逻辑封装起来,使JSP页面看起来更加简洁明了。

二、foreach标签

foreach标签分析:

  • 两个属性:var、items
  • 分析线路:
    第二条:eval_body_include
    第三条:eval_body_again
  1. 我们编写一个Foreach的助手类ForeachTag,需要继承BodyTagSupport
    里面的属性为varitemsitmes定义为集合
     private String var;
     private List<Object> items = new ArrayList<>();
    
    并且获取它的get、set方法
public String getVar() {
   
   
        return var;
    }

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

    public List<Object> getItems() {
   
   
        return items;
    }

    public void setItems(List<Object> items) {
   
   
        this.items = items;
    }

我们重写刚刚分析的线路doStartTagdoAfterBody

@Override
    public int doStartTag() throws JspException {
   
   
        //利用迭代
        Iterator<Object> it = items.iterator();
        // it.next()是对应的是集合的某一个对象
        pageContext.setAttribute(var, it.next());
        // 为了保留迭代时指针现有的位置
        pageContext.setAttribute("it", it);

        return EVAL_BODY_INCLUDE;
    }

    @SuppressWarnings("unchecked")
    @Override
    public int doAfterBody() throws JspException {
   
   
        //获取到
        Iterator<Object> it = (Iterator<Object>) pageContext.getAttribute("it");
        //判断如果有数据继续循环,没有就停止循环
        if (it.hasNext()) {
   
   
            // 继续
            pageContext.setAttribute(var, it.next());
            // 为了保留迭代时指针现有的位置
            pageContext.setAttribute("it", it);
            return EVAL_BODY_AGAIN;
        } else {
   
   
            return EVAL_PAGE;
        }

    }
  1. tld文件
<?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>JSTL 1.1 core library</description>
    <display-name>JSTL core</display-name>
    <tlib-version>1.1</tlib-version>
    <!-- 一个名字 -->
    <short-name>t</short-name>
    <!-- 路径 -->
    <uri>http://jsp.tgq.cn</uri>
    <tag>
        <name>foreach</name>
        <tag-class>com.tgq.jsp.ForeachTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
        <!-- 名字,和助手类对应 -->
            <name>items</name>
            <!-- 是否是必须的 -->
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>var</name>
            <!-- 是否是必须的 -->
            <required>true</required>
            <!-- 是否可以写入EL表达式 -->
            <rtexprvalue>false</rtexprvalue>
        </attribute>
    </tag>
    </taglib>
  1. JSP页面
<%@page import="com.tgq.jsp.Teacher"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://jsp.tgq.cn" prefix="t"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>
    <%
        List<Teacher> list = new ArrayList<Teacher>();
        list.add(new Teacher("t01", "sb"));
        list.add(new Teacher("t02", "2b"));
        list.add(new Teacher("t03", "nb"));
        request.setAttribute("list", list);
    %>
    <t:foreach items="${list }" var="t">
    ${t.tid }:${t.tname }
    </t:foreach>
    </body>
</html>
  1. 编写一个Java普通类
package com.tgq.jsp;

public class Teacher {
   
   
    private String tid;
    private String tname;

    public String getTid() {
   
   
        return tid;
    }

    public void setTid(String tid) {
   
   
        this.tid = tid;
    }

    public String getTname() {
   
   
        return tname;
    }

    public void setTname(String tname) {
   
   
        this.tname = tname;
    }

    public Teacher(String tid, String tname) {
   
   
        super();
        this.tid = tid;
        this.tname = tname;
    }

    @Override
    public String toString() {
   
   
        return "Teacher [tid=" + tid + ", tname=" + tname + "]";
    }

    public Teacher() {
   
   
        // TODO Auto-generated constructor stub
    }
}

测试结果:

完整助手类代码:

package com.tgq.jsp;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

/**
 * 分析foreach标签
 * 
 * 两个属性:var、items
 * 
 * 分析线路: 第二条:eval_body_include 第三条:eval_body_again
 * 
 * @author tgq
 *
 */

@SuppressWarnings("serial")
public class ForeachTag extends BodyTagSupport {
   
   

    private String var;
    private List<Object> items = new ArrayList<>();

    public String getVar() {
   
   
        return var;
    }

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

    public List<Object> getItems() {
   
   
        return items;
    }

    public void setItems(List<Object> items) {
   
   
        this.items = items;
    }

    @Override
    public int doStartTag() throws JspException {
   
   

        Iterator<Object> it = items.iterator();
        // it.next()是对应的是集合的某一个对象
        pageContext.setAttribute(var, it.next());
        // 为了保留迭代时指针现有的位置
        pageContext.setAttribute("it", it);

        return EVAL_BODY_INCLUDE;
    }

    @SuppressWarnings("unchecked")
    @Override
    public int doAfterBody() throws JspException {
   
   

        Iterator<Object> it = (Iterator<Object>) pageContext.getAttribute("it");

        if (it.hasNext()) {
   
   
            // 继续
            pageContext.setAttribute(var, it.next());
            // 为了保留迭代时指针现有的位置
            pageContext.setAttribute("it", it);
            return EVAL_BODY_AGAIN;
        } else {
   
   
            return EVAL_PAGE;
        }

    }

}

三、dept数据标签

dept数据标签一般用于在JSP页面中展示部门的树形结构,其作用是可以根据传入的参数生成相应的HTML代码,从而在页面上展示类似于树形结构的数据。

分析:
一个属性var、重写doStartTag

  1. 编写DeptTag助手类
    完整代码:
package com.tgq.jsp;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class DeptTag extends BodyTagSupport {
   
   

    private String var;

    public String getVar() {
   
   
        return var;
    }

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

    @Override
    public int doStartTag() throws JspException {
   
   
        // 模拟数据库访问过程
        List<Teacher> list = new ArrayList<Teacher>();
        list.add(new Teacher("t01", "sb"));
        list.add(new Teacher("t02", "2b"));
        list.add(new Teacher("t03", "nb"));
        // 将数据放入 var 中
        pageContext.setAttribute("tl", list);
        return SKIP_BODY;
    }
}
  1. tld文件
<?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>JSTL 1.1 core library</description>
    <display-name>JSTL core</display-name>
    <tlib-version>1.1</tlib-version>
    <!-- 一个名字 -->
    <short-name>t</short-name>
    <!-- 路径 -->
    <uri>http://jsp.tgq.cn</uri>
        <tag>
        <name>dept</name>
        <tag-class>com.tgq.jsp.DeptTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>var</name>
            <!-- 是否是必须的 -->
            <required>true</required>
            <!-- 是否可以写入EL表达式 -->
            <rtexprvalue>false</rtexprvalue>
        </attribute>
    </tag>
    </taglib>
  1. JSP页面
<%@page import="com.tgq.jsp.Teacher"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://jsp.tgq.cn" prefix="t"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>
<hr>
    <p>自定义数据标签dept</p>
    <!-- 作用:当一些数据多个页面,或者多个地方频繁使用时,就可以做成数据 -->
    <t:dept var="tl"></t:dept>
    ${tl }
    <hr>
</body>
</html>

测试结果:

四、select标签

select标签:该标签用于生成HTML的下拉选择控件,一般情况下用于表单提交时的选择

作用

  1. 省略遍历过程
  2. 当做数据回显时,无需增加if判断,无需增加新的代码

分析:

  1. 后台遍历==》数据源===》items
  2. 需要一个对象的属性代表下拉框对应展示的内容==》textVal
  3. 需要一个对象的属性代表下拉框对应展示的value值==》textKey
  4. 默认的头部选项展示内容-->headerTextVal
  5. 默认的头部选项值-->headerTextValKey
  6. 数据中存储的值,为了方便做数据回显-->selectedVal
  7. id name cssStyle....

实践

我们进行一个简易化
一个助手类
重写doStartTag方法 和 getset 方法

    // 下拉框的数据源
    private List<Object> itmes = new ArrayList<>();
    // 下拉框option的value值
    private String optionVal;
    // 下拉框option标签体内容
    private String optionText;
    // 数据库中存储的数据,用于下拉框回显
    private String selectedVal;

我们在助手类里面还需要编写两个方法:用来回显数据和获取某个对象的某个属性值

/**
     * 返回一个标签
     * 一个循环
     * 
     * @return
     * @throws Exception
     */
    private String toHtml() throws Exception {
   
   
        // String 和 StringBuffer的区别
        // String 处理字符串拼接更加消耗服务器内存
        StringBuffer sb = new StringBuffer("<select>");
        for (Object object : itmes) {
   
   
            // 取出某一个对象的某一个属性值
            String val = getObjAttrValue(object, optionVal);
            String text = getObjAttrValue(object, optionText);
            sb.append("<option " + (val.equals(selectedVal) ? "selected" : "") + " value='" + val + "'>" + text
                    + "</option>");
        }
        sb.append("</select>");
        return sb.toString();
    }
/**
     * 
     * 获取某个对象的某个属性值
     * 
     * @param object
     *            dept
     * @param optionVal2
     *            id/name
     * @throws Exception
     */
    private String getObjAttrValue(Object object, String atr) throws Exception {
   
   
        Class cl = object.getClass();
        Field f = cl.getDeclaredField(atr);
        f.setAccessible(true);// 打开权限 f代表id
        return (String) f.get(object).toString();
    }

编写tld文件

<tag>
        <name>select</name>
        <tag-class>com.tgq.jsp.SelectTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>itmes</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <name>optionVal</name>
            <!-- 是否是必须的 -->
            <required>true</required>
            <!-- 是否可以写入EL表达式 -->
            <rtexprvalue>false</rtexprvalue>
        </attribute>
        <attribute>
            <name>optionText</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
        </attribute>
        <attribute>
            <name>selectedVal</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

JSP界面进行一个测试

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://jsp.tgq.cn" prefix="t"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>
    <%
        List<Teacher> list = new ArrayList<Teacher>();
        list.add(new Teacher("t01", "sb"));
        list.add(new Teacher("t02", "2b"));
        list.add(new Teacher("t03", "nb"));
        request.setAttribute("list", list);
    %>
    <t:foreach items="${list }" var="t">
    ${t.tid }:${t.tname }
    </t:foreach>
    <hr>
    <p>自定义数据标签dept</p>
    <!-- 作用:当一些数据多个页面,或者多个地方频繁使用时,就可以做成数据 -->
    <t:dept var="tl"></t:dept>
    ${tl }
    <hr>
    <select id="" name="">
        <option value="1">qwe</option>
        <option value="2">asd</option>
    </select>
    <p>自定义select标签</p>
    <t:select optionVal="tid" itmes="${list }" optionText="tname"></t:select>

    <t:select optionVal="tid" itmes="${list }" optionText="tname"
        selectedVal="t02"></t:select>
    <t:select optionVal="tid" itmes="${list }" optionText="tname"
        selectedVal="t03"></t:select>

    </body>
</html>

全部的测试结果:

编写的有点简陋还请见谅!!!希望对你们有点帮助!!!

相关文章
|
Java
JSP自定义标签【下】
JSP自定义标签【下】
67 0
|
Java
jsp自定义标签
jsp自定义标签
79 1
|
7月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 3
JSP自定义标签允许开发人员创建可重用的组件,简化页面逻辑。在JSP 2.0及以上版本,可通过继承`SimpleTagSupport`并覆写`doTag()`方法来创建自定义标签,如`HelloTag`,它有一个`message`属性。属性值通过setter方法`setMessage()`设置。在TLD文件中定义该属性后,可在JSP页面使用`&lt;ex:Hello message=&quot;This is custom tag&quot;/&gt;`来调用,输出定制的文本。
31 0
|
7月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 4
**JSP自定义标签允许创建用户定义的语言元素。它们转换为Servlet中的tag handler,在执行时由Web容器调用。使用SimpleTagSupport继承并重写doTag()方法可创建简单标签。标签可设置属性,如message,通过setter方法访问。TLD文件定义属性元数据,JSP页面则通过prefix和uri引用。例如,&lt;ex:Hello message=&quot;...&quot;/&gt; 显示定制消息。属性可配置为必需、类型、描述及是否为JspFragment。**
31 0
|
7月前
|
搜索推荐 Java 容器
JSP 教程 之 JSP 自定义标签 2
**JSP自定义标签允许用户创建个性化标签,简化页面逻辑。在JSP 2.0中,通过继承`SimpleTagSupport`并重写`doTag()`可创建简单标签处理器。示例展示了一个名为`Hello`的自定义标签,它接收并显示标签体内容。TLD文件配置了标签元数据,JSP页面引用该标签并展示“这是消息主体”。**
32 0
|
7月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 1
**JSP自定义标签简介**:扩展JSP功能,创建用户定义标签,通过Servlet容器调用Tag Handler。在JSP 2.0中,使用SimpleTagHandlers简化定制。以&quot;Hello&quot;标签为例,创建`HelloTag`类继承`SimpleTagSupport`,重写`doTag()`打印消息。编译后,在`custom.tld`定义标签库,JSP页面引用后即可使用。例如 `&lt;ex:Hello/&gt;` 显示 &quot;Hello Custom Tag!&quot;。
35 0
|
前端开发 Java
通用分页进阶之jsp之自定义标签
通用分页进阶之jsp之自定义标签
40 1
|
8月前
|
Java 数据安全/隐私保护
Jsp自定义标签(foreach,dept,select)
Jsp自定义标签(foreach,dept,select)
50 0
|
8月前
|
XML Java 数据格式
JSP自定义标签
JSP自定义标签
71 0
|
XML Java 计算机视觉
JSP实现自定义标签【上】
-- 标签库名 -->-- 对应的助手类 -->-- 代表JSP标签 -->自定义JSP标签的属性名称该属性是否必填该属性值是否支持表达式