JSP自定义标签(进阶)

今天我们继续学习JSP自定义

 

一.面试题:String、StringBuffer和StringBuilder的异同?

相同点底层都是通过char数组实现的

不同点

1.String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的;

2.StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低。

3.而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高

4.总结:如果我们在实际开发过程中需要对字符串进行频繁的修改。不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。

二.自定义foreach标签

我们在写jsp页面时会经常使用c标签的foreach标签。那么我们可不可以自己制定一个foreach标签提供自己使用呢?

下面我们来制定一个自定义foreach标签。

我们根据步骤来:

2.1 创建一个标签助手类(继承BodyTagSupport) 标签属性必须与助手类的属性对应、且要提供对应get/set方法

2.2 创建标签库描述文件(tld),添加自定义标签的配置 注:tld文件必须保存到WEB-INF目录或其子目录 jstl标签库

2.3 在JSP通过taglib指令导入标签库,并通过指定后缀访问自定义标签

运行效果:

 

2.1 创建一个标签助手类 ①(继承BodyTagSupport) ,且要②提供对应get/set方法,③重写doStartTag,doAfterBody,doEndTag方法

分析:定义两个私有的属性:   

     items;------ 用来遍历的

     var;--------用来保存添加的内容

代码如下:

package com.lya.tag;

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

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

/**
 * @author :JAVA-李永安
 * @date :2023年6月26日 下午6:44:00
 */
public class Foreachtag extends BodyTagSupport {
	
	private List items;// 用来遍历的

	private String var;// 用来保存添加的内容
	
	//提供对应get/set方法
	public List getItems() {
		return items;
	}

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

	public String getVar() {
		return var;
	}

	public void setVar(String var) {
		this.var = var;
	}
	
	@Override
	public int doStartTag() throws JspException {
		if (items == null) {// 对集合判空
			return SKIP_BODY;// 为空就跳过
		} else {
			@SuppressWarnings("rawtypes")
			Iterator iterator = items.iterator();// 迭代遍历
			Object next = iterator.next();// 获取遍历内容
			pageContext.setAttribute(var, next);// 通过var保存遍历内容
			pageContext.setAttribute("iterator", iterator);// 保存未遍历的内容
			return EVAL_BODY_INCLUDE;
		}
	}

	@Override
	public int doAfterBody() throws JspException {
		// 将未遍历的内容继续遍历出来
		@SuppressWarnings("rawtypes")
		Iterator iterator = (Iterator) pageContext.getAttribute("iterator");// 获取未遍历的内容

		if (iterator.hasNext()) {// 对集合判空
			Object itp = iterator.next();// 获取遍历内容
			pageContext.setAttribute(var, itp);// 通过var保存遍历内容
			pageContext.setAttribute("iterator", iterator);// 保存未遍历的内容
			return EVAL_BODY_AGAIN;
		}
		return SKIP_BODY;
	}

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

}

2.2 创建标签库描述文件(tld)

<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<!-- 标签库描述符 -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
	<!-- 代表标签库的版本号 -->
	<tlib-version>1.0</tlib-version>
	<!-- 代表jsp的版本 -->
	<jsp-version>1.2</jsp-version>
	<!-- 你的标签库的简称 -->
	<short-name>test</short-name>
	<!-- 你标签库的引用uri -->
	<uri>/zking</uri><!-- 在jsp页面调用tld的路径 -->

	<tag>
		<!-- 标签名 -->
		<name>out</name>
		<!-- 标签工具类 -->
		<tag-class>com.lya.tag.outtag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>jsp</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->

		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>aa</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
			<description>out标签aa属性,输出aa</description>
		</attribute>

		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>bb</name>
			<!-- true表示必填 -->
			<required>false</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
			<description>默认输出</description>
		</attribute>
	</tag>

	<tag>
		<!-- 标签名 -->
		<name>if</name>
		<!-- 标签工具类 -->
		<tag-class>com.lya.tag.iftag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>jsp</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->

		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>cc</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
			<description>if标签cc属性,输出cc</description>
		</attribute>
	</tag>

	<tag>
		<!-- 标签名 -->
		<name>foreach</name>
		<!-- 标签工具类 -->
		<tag-class>com.lya.tag.Foreachtag</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><!-- var是string类型 -->
			<description>foreach标签cc属性,输出cc</description>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>items</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
			<description>foreach标签cc属性,输出cc</description>
		</attribute>
	</tag>
</taglib>

2.3 在JSP通过taglib指令导入标签库,使用自定义标签

<%@page import="java.util.Arrays"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>

	<%
		request.setAttribute("name", "zs");

		List list = new ArrayList<>();
		list.add(0, "zs");
		list.add(1, "ls");
		list.add(2, "ww");

		List list2 = Arrays.asList(new String[] { "zs", "ls", "ww" });
		
		request.setAttribute("list", list);//通过request作用域保存list
	%>

	<pre>
	使用c标签的foreach标签遍历。
	</pre>
	<c:forEach items="${list }" var="a">
		${a }<hr>
	</c:forEach>
	
	<pre>
	使用自定义foreach标签遍历。
	</pre>
	
	<z:foreach items="${list }" var="a">
		${a }<hr>
	</z:foreach>
</body>
</html>

三.自定义select标签

3.1为啥我们需要自定义select标签?

 

1.以前我们使用jsp显示内容是使用servlet传递参数(步骤比较繁琐),只要写两行代码。

以前写的:

 使用自定义select标签后写的:

 显示的效果:

 

2.那么我们用一种简洁的代码来完成。

3.提升我们代码的可维护能力。

3.2创建自定义select标签步骤:

3.2.1 创建一个标签助手类 ①(继承BodyTagSupport) ,且要②提供对应get/set方法,③重写doStartTag,doAfterBody,doEndTag方法

分析:1.定义两个私有的属性:   

    items;---- 用来遍历的
    
    textval;----用来显示下拉的内容

    textvalue;----- 传递下拉对应的value

    seleteval;------- 传递值,使页面显示对应的内容

         2.提供无参构造(因为这个select标签要被作为公共的标签,可是对应的对象我们又不知道,这时候我们得用到反射来实现)

         3.重写doStartTag方法

         4.使用stringbuffer拼接

代码如下:

package com.lya.tag;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;

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

import com.lya.entity.Dpat;

/**
 * 下拉框的标签助手类
 * 
 * @author :JAVA-李永安
 * @date :2023年6月26日 下午7:52:46
 */
public class SeleteTag extends BodyTagSupport{
	private List items;// 用来遍历的

	private String textval;// 用来显示下拉的内容

	private String textvalue;// 传递下拉对应的value

	private String seleteval;// 传递值,使页面显示对应的内容
	
	//提供无参构造(因为这个select标签要被作为公共的标签,可是对应的对象我们又不知道,这时候我们得用到反射来实现)

	//提供对应get/set方法
	public List getItems() {
		return items;
	}
	
	
	public void setItems(List items) {
		this.items = items;
	}

	public String getTextval() {
		return textval;
	}

	public void setTextval(String textval) {
		this.textval = textval;
	}

	public String getTextvalue() {
		return textvalue;
	}

	public void setTextvalue(String textvalue) {
		this.textvalue = textvalue;
	}

	public String getSeleteval() {
		return seleteval;
	}

	public void setSeleteval(String seleteval) {
		this.seleteval = seleteval;
	}
	
	@Override
	public int doStartTag() throws JspException {
		//1.使用页面输出流
		JspWriter out = pageContext.getOut();
		//2.定义一个空变量,通过字符串的方式保存向页面显示的内容
		try {
			out.print(html());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			return EVAL_BODY_INCLUDE;
		}
	private String html() throws Exception {
		//1.实例stringbuffer,用于去拼接字符串。
		StringBuffer sb = new StringBuffer();
		sb.append("<select>");
		//2.使用反射 (输出的内容取决于items集合的内容)
		for (Object object : items) {
			//3.取出对象的属性值
			String var = getobjvalue(object,textval);//显示内容
			String value = getobjvalue(object,textvalue);//value
			sb.append("<option "+(value.equals(seleteval) ? "selected" : "")+" value='"+value+"'>"+var+"</option>");
		}
		sb.append("</select>");
		return sb.toString();//转成string输出
	}

	/**
	 * 取出对象的属性值
	 * @param object
	 * @param value
	 * @return
	 * @throws SecurityException 
	 * @throws NoSuchFieldException 
	 */
	private String getobjvalue(Object object, String value) throws Exception {
		//实例类类
		Class class1 = object.getClass();
		//取得的对应的属性
		Field declaredField = class1.getDeclaredField(value);
		//获取权限
		declaredField.setAccessible(true);
		return declaredField.get(object).toString();
	}

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

	
	
}

           

3.2.2 创建标签库描述文件(tld)

将助手类对应的属性进行描述:注意不要copy错误了!!!

代码如下:

<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<!-- 标签库描述符 -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
	<!-- 代表标签库的版本号 -->
	<tlib-version>1.0</tlib-version>
	<!-- 代表jsp的版本 -->
	<jsp-version>1.2</jsp-version>
	<!-- 你的标签库的简称 -->
	<short-name>test</short-name>
	<!-- 你标签库的引用uri -->
	<uri>/zking</uri><!-- 在jsp页面调用tld的路径 -->

	

	<tag>
		<!-- 标签名 -->
		<name>select</name>
		<!-- 标签工具类 -->
		<tag-class>com.lya.tag.SeleteTag</tag-class>
		<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
		<body-content>jsp</body-content>
		<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->

		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>items</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>true</rtexprvalue>
			<description>select标签保存的集合</description>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>textval</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue><!-- var是string类型 -->
			<description>select标签输出的内容</description>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>textvalue</name>
			<!-- true表示必填 -->
			<required>true</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue><!-- var是string类型 -->
			<description>select标签输出的value值</description>
		</attribute>
		<attribute>
			<!-- 自定义标签的属性名称 -->
			<name>seleteval</name>
			<!-- true表示必填 -->
			<required>false</required>
			<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
			<rtexprvalue>false</rtexprvalue><!-- var是string类型 -->
			<description>select传递值,使页面显示对应的内容</description>
		</attribute>

	</tag>
</taglib>

3.2.3 在JSP通过taglib指令导入标签库,使用自定义标签

注意不要写标签时不要写错误了,最好通过快捷方式!!!

代码如下:

<%@page import="com.lya.entity.Dpat"%>
<%@page import="java.util.Arrays"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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>

	<%
		request.setAttribute("name", "zs");

		List list = new ArrayList<>();
		list.add(0, "zs");
		list.add(1, "ls");
		list.add(2, "ww");

		List<Dpat> list2 = new ArrayList<Dpat>();
		list2.add(new Dpat("0", "学历部"));
		list2.add(new Dpat("1", "产品部"));
		list2.add(new Dpat("2", "电竞部"));
		list2.add(new Dpat("3", "..."));

		request.setAttribute("list", list);//通过request作用域保存list
		request.setAttribute("list2", list2);//通过request作用域保存list
	%>

	
	<pre>
	使用自定义select标签。
	</pre>

	<select>
		<z:foreach items="${list }" var="a">
			<option>${a }</option>
		</z:foreach>
	</select>
	<hr>
<z:select items="${list2 }" textvalue="did" textval="dname"></z:select>
<z:select items="${list2 }" textvalue="did" textval="dname" seleteval="1"></z:select>
<z:select items="${list2 }" textvalue="did" textval="dname" seleteval="2"></z:select>
<z:select items="${list2 }" textvalue="did" textval="dname" seleteval="3"></z:select>


</body>
</html>

四.总结

我们在写助手类时,1.要牢记自己定义的属性名称, 

                                 2.使用StringBuffer进行拼接要小心,注意单引号双引号的转换       

                                 3.编写描述类时不要将助手类的名称写错!!!

                                  最后注意逻辑的梳理!!!

                                希望本篇讲解能帮助到你!!!😀

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值