J2EE基础:jsp标签

本节知识总结



前言

首先介绍一下我们学习本节的目标:

①明确c标签怎么来的;

②如何开发一个自己的标签

③根据实际业务场景开发对应标签


下面我们就来完成这些目标<( ̄︶ ̄)↗[GO!]🧐

一、jsp标签语言的特点

1.组成

①开始标签

②标签体

③结束标签

组成形式:<开始标签 属性="属性值">标签体</结束标签>

2.分类

可分为以下四种:

①空标签: br、hr...

②ui标签:input、table...

③控制标签:if、foreach...

④数据标签:set标签、out标签...

代码如下(示例):

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!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>Insert title here</title>
</head>
<body>
<z:if test=""></z:if>
<z:forEach items=""></z:forEach>
<!-- 标签的构造:开始标签,标签体,结束标签 -->
<a>标签的特点</a>
<!-- 空标签 -->
<br>
<hr>
<!-- UI标签 -->
<table>
<tr></tr>
</table>
<input>
<!-- 控制标签 -->
<c:if test="true"></c:if>
<c:if test="false"></c:if>
<!-- 数据标签 -->
<c:set var="name" value="zs"></c:set>
<c:out value="${name }"></c:out>
</body>
</html>

 二、jsp自定义标签步骤

1.tag助手继承BodyTagSupport

重写doStartTag()

重写doAfterBodyTag

重写doEndTag

代码如下(示例):

package com.xhy.tag;

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

public class Demo1 extends BodyTagSupport{
    
@Override
public int doStartTag() throws JspException {
    System.out.println("进来了");
    // TODO Auto-generated method stub

   // return super.doStartTag();不显示
    return EVAL_BODY_INCLUDE;显示
}
@Override
    public int doAfterBody() throws JspException {
        // TODO Auto-generated method stub
        return super.doAfterBody();
    }
@Override
    public int doEndTag() throws JspException {
        // TODO Auto-generated method stub
        return super.doEndTag();
    }
}

2.新建tld标签库描述文件

在你的web应用目录下,找到WEB-INF文件夹,在里面新建一个tld类型的文件(注:一定要是tld文件)

这里可以参考jstl里的tld文件进行编写!!

导入jstl包和standard包:https://mvnrepository.com/  去里面搜索jra包吧学会自己下载哦🐷

代码如下(示例):

<?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>zking 1.1 core library</description>
  <display-name>zking core</display-name>
  <tlib-version>1.1</tlib-version><!-- 代表标签库的版本号 -->
  <short-name>zking</short-name><!-- 你的标签库的简称 -->
  <uri>http://jsp.veryedu.cn</uri><!-- 你标签库的引用uri -->


<tag>   
    <name>demo1</name><!-- 你定义的标签的名称 -->
    <tag-class>com.zking.tag.Demo1</tag-class><!-- 对应的标签处理程序:包名+类名,全包名 -->
    <body-content>JSP</body-content><!-- 标签体内容的格式 -->
  </tag>


</taglib>
 

3.使用自定义标签 

你要在使用你定义的标签的jsp页面导入你的标签库就像导入类包一样(也称为:调用自己所写的标签)使用标签

代码如下(示例):

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib uri="http://jsp.veryedu.cn" prefix="z"%>
    
<!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>Insert title here</title>
</head>
<body>
<z:demo1>随便来点</z:demo1>
</body>
</html>


 三、jsp标签生命周期

 

 首先介绍他的开发场景:

①doStartTag——SKIP_BODY——doEndTag

②doStartTag——EVAL_BODY_INCLUDE——doAfterBody——EVAL_PAGE——doEndTag

③doStartTag——EVAL_BODY_INCLUDE——doAfterBody——EVAL_BODY_AGAIN(N次)——doEndTag

然后是返回值:

SKIP_BODY:跳过主体
EVAL_BODY_INCLUDE:计算标签主体内容并输出
EVAL_BODY_AGAIN:再计算主体一次
EVAL_PAGE:计算页面的后续部分
SKIP_PAGE:跳过页面的后续部分

测试:

代码如下(示例):

package com.xhy.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
/**
 * 三种路线
 *①doStartTag——SKIP_BODY——doEndTag
 * ②doStartTag——EVAL_BODY_INCLUDE——doAfterBody——EVAL_PAGE——doEndTag
 * ③doStartTag——EVAL_BODY_INCLUDE——doAfterBody——EVAL_BODY_AGAIN(N次)——doEndTag
 */
public class Test01 extends BodyTagSupport{
    
    //第一个例子:根据代码论证这三条路线的执行顺序(涉及三个类:Test01.java,Test02.java,Test03.java)
    @Override
    public int doStartTag() throws JspException {
        System.out.println("Test01_doStartTag");
        //return super.doStartTag();
        return SKIP_BODY;
    }
    @Override
    public int doEndTag() throws JspException {
        System.out.println("Test01_doEndTag");
        // TODO Auto-generated method stub
        return super.doEndTag();
    }
}
 
 
public class Test02 extends BodyTagSupport{
    //第一个例子:根据代码论证这三条路线的执行顺序(涉及三个类:Test01.java,Test02.java,Test03.java)
    @Override
    public int doStartTag() throws JspException {
        System.out.println("Test02_doStartTag");
        //return super.doStartTag();
        return EVAL_BODY_INCLUDE;
    }
    @Override
    public int doAfterBody() throws JspException {
        System.out.println("Test02_doAfterBody");
        // TODO Auto-generated method stub
        return EVAL_PAGE;
    }
    @Override
    public int doEndTag() throws JspException {
        System.out.println("Test02_doEndTag");
        // TODO Auto-generated method stub
        return super.doEndTag();
    }
}
 
 
public class Test03 extends BodyTagSupport{
    //第一个例子:根据代码论证这三条路线的执行顺序(涉及三个类:Test01.java,Test02.java,Test03.java)
    @Override
    public int doStartTag() throws JspException {
        System.out.println("Test03_doStartTag");
        //return super.doStartTag();
        return EVAL_BODY_INCLUDE;
    }
    @Override
    public int doAfterBody() throws JspException {
        System.out.println("Test03_doAfterBody");
        // TODO Auto-generated method stub
        return EVAL_BODY_AGAIN;
    }
    
    @Override
    public int doEndTag() throws JspException {
        System.out.println("Test03_doEndTag");
        // TODO Auto-generated method stub
        return super.doEndTag();
    }
}


四、建立常见的jsp标签 

1.z:if标签:

1.tag助手继承BodyTagSupport

return this.test ?EVAL_BODY_INCLUDE:SKIP_BODY;

package com.xhy.tag;

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

public class If extends BodyTagSupport{
    private boolean test;

    public boolean isTest() {
        return test;
    }

    public void setTest(boolean test) {
        this.test = test;
    }
    @Override
    public int doStartTag() throws JspException {
        return this.test ? EVAL_BODY_INCLUDE:SKIP_BODY;
    }
    @Override
    public int doEndTag() throws JspException {
        // TODO Auto-generated method stub
        return super.doEndTag();
    }
}
 

 2.创建tld文件,开发if标签

<tag>
  <name>if</name>
  <tag-class>com.xhy.tag.If</tag-class>
  <body-content>JSP</body-content>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>test</name>
  <!-- 该成员变量是否必传-->
  <required>true</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  </tag>

3.使用

 <z:if test="true">输出</z:if>

<zking:if test="false">不输出</zking:if>

2.z:set与z:out标签:

pageContext:setAttribute(var,value)
JspWrite out=pageContext.getOut();
out.print(value);

①set

1.tag助手继承BodyTagSupport

package com.xhy.tag;

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

public class Set extends BodyTagSupport{
    private String var;
    private Object value;
    public String getVar() {
        return var;
    }
    public void setVar(String var) {
        this.var = var;
    }
    public Object getValue() {
        return value;
    }
    public void setValue(Object value) {
        this.value = value;
    }
    @Override
    public String toString() {
        return "SetTag [var=" + var + ", value=" + value + "]";
    }
public Set() {
    // TODO Auto-generated constructor stub
}

@Override
public int doStartTag() throws JspException {
    pageContext.setAttribute(var, value);
    return super.doStartTag();
}
}

2. 创建tld文件,开发set标签

<tag>
  <name>set</name>
  <tag-class>com.xhy.tag.Set</tag-class>
  <body-content>JSP</body-content>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>var</name>
  <!-- 该成员变量是否必传-->
  <required>true</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>value</name>
  <!-- 该成员变量是否必传-->
  <required>true</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>true</rtexprvalue>
  </attribute>
  </tag>

3.使用:

 <z:set var="name" value="xhy"></z:set>

②out

1.tag助手继承BodyTagSupport

package com.xhy.tag;

import java.io.IOException;

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

public class Out extends BodyTagSupport{
private Object value;
    
    public Object getValue() {
        return value;
    }
    public void setValue(Object value) {
        this.value = value;
    }
    @Override
    public int doStartTag() throws JspException {
        JspWriter out = pageContext.getOut();
        try {
            out.print(value);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return super.doStartTag();
    }

    @Override
    public int doEndTag() throws JspException {
        // TODO Auto-generated method stub
        return super.doEndTag();
    }
}
 

 2. 创建tld文件,开发Out标签

<tag>
  <name>out</name>
  <tag-class>com.xhy.tag.Out</tag-class>
  <body-content>JSP</body-content>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>value</name>
  <!-- 该成员变量是否必传-->
  <required>true</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>true</rtexprvalue>
  </attribute>
  </tag>

3.使用

<z:out value="${name} "></z:out>

3.z:foreach标签:

分析:

1.属性值有:var items

2.start:Iterator<Object> it=items.iterator();
        pageContext.setAttribute("it", it);

3.after: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.tag助手继承BodyTagSupport

 package com.xhy.tag;

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

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

public class foreach extends BodyTagSupport{

    private String var;
    private List<Object> items;
    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();
        pageContext.setAttribute("it", it);
        return EVAL_BODY_INCLUDE;

    }
    @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;
        }

    }
    
}

 2. 创建tld文件,开发foreach标签

<tag>
        <!-- 标签名 -->
        <name>foreach</name>
        <!-- 标签工具类 -->
        <tag-class>com.xhy.tag.foreach</tag-class>
        <!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
        <body-content>jsp</body-content>
        <!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
         <attribute>
            <!-- 自定义标签的属性名称 -->
            <name>var</name>
            <!-- true表示必填 -->
            <required>true</required>
            <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
            <rtexprvalue>false</rtexprvalue>
        </attribute> 
        <attribute>
            <!-- 自定义标签的属性名称 -->
            <name>items</name>
            <!-- true表示必填 -->
            <required>true</required>
            <!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute> 
    </tag>

3.测试

<%
List user=new ArrayList<>();
user.add(new User(1,"a"));
user.add(new User(2,"b"));
user.add(new User(3,"c"));
request.setAttribute("user", user);
%>

<z:foreach items="${ user }" var="i">
${ i.id }:${ i.name }
</z:foreach>

4.z:select标签:

将所学的自定义标签的知识点,用于实际项目开发
 不管if/set/out/foreach...,那都是C标签已经具备的功能,直接用别人的就好
 学习自定义标签理解其底层的目的,就是弥补现成C标签没有的功能

查询下拉框
 修改回显,在这里有大量的c:foreach/c:if判断
 不足之处,代码量过大,以及凡是涉及到下拉框以及复选框,相类似代码量过多
 目前:
 <z:select></z:select>通过该标签实现上述代码的相同功能
  分析属性:
 1、需要遍历展示,需要数据源属性items,用于遍历展示     users->List<User>->id=option>value;name=option>test
  2、对象Key属性textKey,用于对应option>value
 3、对象value属性textVal,用于对应option>text
 4、对象默认Key属性headerTextKey,用于对应默认option>value
 5、对象默认value属性headerTextVal,用于对应默认option>text
 6、对象回显属性selectedVal,用于判断数据回显选择 

1.tag助手继承BodyTagSupport

 package com.xhy.tag;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.commons.beanutils.PropertyUtils;

public class SelectTag extends BodyTagSupport {
    private List<Object> items=new ArrayList<Object>();//用于遍历展示
    private String textKey;//用于对应option>value
    private String textVal;//用于对应option>text
    private String headerTextKey;//用于对应默认option>value
    private String headerTextVal;//用于对应默认option>text
    private String selectedVal;//用于判断数据回显选择
    //定义属性美化。拓展/操作标签
    private String cssStyle;//美化
    private String id;//绑定事件...操作标签
    private String className;//美化
    //没有标签体,有需要往页面输出内容  JspWriter
    @Override
    public int doStartTag() throws JspException {
        JspWriter out = pageContext.getOut();
        try {
            out.print(doHTML());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.doStartTag();
    }
    //<select>
    //<option value="">--请选择--</option>
    //<option value="1">晓哥</option>
    // <option value="2">胡哥</option>
    // </select>
    private String doHTML() throws Exception, Exception {
        StringBuffer sb=new StringBuffer();
        sb.append("<select id='"+id+"' class='"+className+"' style='"+cssStyle+"'>");
        //拼接默认显示标签
        if(headerTextVal!=null&&!"".equals(headerTextVal)) {
            sb.append("<option value='"+headerTextKey+"'>"+headerTextVal+"</option>");
        }
        //循环显示数据
        if(items.size()>0) {
            for (Object obj : items) {
                //obj对应user,希望拿到当前user的id放入option-value,name放入option-text
                //通过反射获取到id对应的属性对象
                Field textKeyField = obj.getClass().getDeclaredField(textKey);
                textKeyField.setAccessible(true);//打开权限
                //textKeyField.get(obj);//获取id对应的值
                //以下方法等价于上面三行代码
                //PropertyUtils.getProperty(obj, textVal);
                String value = textKeyField.get(obj).toString();
                //System.out.println(value+"--------");
                sb.append("<option value='"+value+"'>"+PropertyUtils.getProperty(obj, textVal)+"</option>");
                //修改页面下拉框回显选中
                //当下拉框的Value值等于selectedVal,那么就要默认下拉框选中;
                if(value.equals(selectedVal)) {
                    sb.append("<option selected value='"+value+"'>"+PropertyUtils.getProperty(obj, textVal)+"</option>");
                }else {
                    sb.append("<option value='"+value+"'>"+PropertyUtils.getProperty(obj, textVal)+"</option>");
                }
            }
        }
        
        sb.append("</select>");
        return sb.toString();
    }
 
//   get/set方法
    public List<Object> getItems() {
        return items;
    }
    public void setItems(List<Object> items) {
        this.items = items;
    }
    public String getTextKey() {
        return textKey;
    }
    public void setTextKey(String textKey) {
        this.textKey = textKey;
    }
    public String getTextVal() {
        return textVal;
    }
    public void setTextVal(String textVal) {
        this.textVal = textVal;
    }
    public String getHeaderTextKey() {
        return headerTextKey;
    }
    public void setHeaderTextKey(String headerTextKey) {
        this.headerTextKey = headerTextKey;
    }
    public String getHeaderTextVal() {
        return headerTextVal;
    }
    public void setHeaderTextVal(String headerTextVal) {
        this.headerTextVal = headerTextVal;
    }
    public String getSelectedVal() {
        return selectedVal;
    }
    public void setSelectedVal(String selectedVal) {
        this.selectedVal = selectedVal;
    }
    public String getCssStyle() {
        return cssStyle;
    }
    public void setCssStyle(String cssStyle) {
        this.cssStyle = cssStyle;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
}

  2. 创建tld文件,开发select标签

<tag>
  <name>select</name>
  <tag-class>com.xhy.tag.select</tag-class>
  <body-content>JSP</body-content>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>id</name>
  <!-- 该成员变量是否必传-->
  <required>false</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>cssStyle</name>
  <!-- 该成员变量是否必传-->
  <required>false</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>className</name>
  <!-- 该成员变量是否必传-->
  <required>false</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>items</name>
  <!-- 该成员变量是否必传-->
  <required>true</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>textKey</name>
  <!-- 该成员变量是否必传-->
  <required>true</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>textVal</name>
  <!-- 该成员变量是否必传-->
  <required>true</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>headerTextKey</name>
  <!-- 该成员变量是否必传-->
  <required>false</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>headerTextVal</name>
  <!-- 该成员变量是否必传-->
  <required>false</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  <attribute>
  <!--  自定义标签的成员变量名称-->
  <name>selectedVal</name>
  <!-- 该成员变量是否必传-->
  <required>false</required>
  <!--  是否支持EL表达式-->
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  </tag>

3.测试 

<%
List user=new ArrayList<>();
user.add(new User(1,"a"));
user.add(new User(2,"b"));
user.add(new User(3,"c"));
request.setAttribute("user", user);
%>

<!-- 模拟的是新增场景 -->
<zking:select cssStyle="color:blue" textVal="name" items="${users}" textKey="id"></zking:select>
<!-- 模拟修改场景 -->
<zking:select selectedVal="u" textVal="name" items="${users}" textKey="id"></zking:select>
<!-- 模拟查询 所有 -->
<zking:select headerTextKey="" headerTextVal="--请选择--" textVal="name"  items="${users}" textKey="id"></zking:select>


总结

自己开发jsp标签使代码更灵活了,熟悉了tld文件

今天的内容就到这了!我们下期再见!希望以上内容能对你有帮助,当然有什么错误之处还望大佬指正!谢谢😘

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值