一、自定义标签的简单概述
JSP自定义标签是指在JSP页面中自定义的标签,其实现原理是基于Servlet中的可重用HTTP方法、过滤器进行封装,以达到在JSP页面中调用的效果。在JSP中自定义标签的
好处
是可以将复杂的业务逻辑封装起来,使JSP页面看起来更加简洁明了。
二、foreach标签
foreach标签分析:
- 两个属性:var、items
- 分析线路:
第二条:eval_body_include
第三条:eval_body_again
- 我们编写一个Foreach的助手类
ForeachTag
,需要继承BodyTagSupport
里面的属性为var
、items
,itmes
定义为集合
并且获取它的get、set方法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;
}
我们重写刚刚分析的线路doStartTag
和doAfterBody
@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;
}
}
- 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>
- 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>
- 编写一个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
- 编写
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;
}
}
- 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>
- 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的下拉选择控件,一般情况下用于表单提交时的选择
作用
- 省略遍历过程
- 当做数据回显时,无需增加if判断,无需增加新的代码
分析:
- 后台遍历==》数据源===》items
- 需要一个对象的属性代表下拉框对应展示的内容==》textVal
- 需要一个对象的属性代表下拉框对应展示的value值==》textKey
- 默认的头部选项展示内容-->headerTextVal
- 默认的头部选项值-->headerTextValKey
- 数据中存储的值,为了方便做数据回显-->selectedVal
- id name cssStyle....
实践
我们进行一个简易化
一个助手类
重写doStartTag
方法 和 get、set 方法
// 下拉框的数据源
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>
全部的测试结果:
编写的有点简陋还请见谅!!!希望对你们有点帮助!!!