前篇文章我说了为什么要开发自定义标签简单来说就是给我们带来更方便的操作,减少多余的代码,利于维护,分离了JSP页面的内容和逻辑,简化了Web开发
前三个标签(out,if,foreach)我前一篇文章里写了,其中还有set,set标签的原理跟out差不多,有兴趣的可以去看看,这篇文章主要加深foreach标签以及重点Select标签
Out标签
标签助手类:
package com.zking.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class OutTag 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(this.value);
} catch (IOException e) {
throw new RuntimeException(e);
}
return super.doStartTag();
}
}
if标签
标签助手类:
package com.zking.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class IfTag extends BodyTagSupport{
private Boolean test;
public Boolean getTest() {
return test;
}
public void setTest(Boolean test) {
this.test = test;
}
@Override
public int doStartTag() throws JspException {
if(test) { //如果前端表达式为true,执行标签体并且输出
return EVAL_BODY_INCLUDE;
}else { //为false,跳过标签体
return SKIP_BODY;
}
}
}
foreach标签
标签助手类:
package com.zking.tag;
import java.util.Iterator;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class ForEachTag extends BodyTagSupport{
private List<Object> items;//数据源
private String var;//将遍历的元素保存到作用域中的键
private String varStatus; //将遍历元素的状态保存到作用域中的键
// 内部类 用来保存遍历的状态
public class Status{
private int index = 0;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public Status() {
}
//count
public int getCount() {
return this.index+1;
}
public void increment() {
this.index++;
}
}
public List<Object> getItems() {
return items;
}
public void setItems(List<Object> items) {
this.items = items;
}
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public String getVarStatus() {
return varStatus;
}
public void setVarStatus(String varStatus) {
this.varStatus = varStatus;
}
@Override
public int doAfterBody() throws JspException {
Iterator it =(Iterator)pageContext.getAttribute("it");//取出作用域中的迭代器
//在doAfterBody里面,不需要用while
//迭代遍历
if(it.hasNext()) {//判断集合中是否有下一个元素
Object next = it.next();
//将元素放入到作用域中
pageContext.setAttribute(this.var, next);
if (null != this.varStatus && !"".equals(this.varStatus.trim())) {//如果状态对象不为空,且不为空字符串
//从作用域中将保存状态的对象取出
Status status = (Status) pageContext.getAttribute(this.varStatus);
//调用自增长的方法
status.increment();
pageContext.setAttribute(this.varStatus, status);
}
return EVAL_BODY_AGAIN;
}
return super.doAfterBody();
}
@Override
public int doStartTag() throws JspException {
if(null==items || 0 ==items.size()) { // 如果集合为空,并且是一个长度为0的集合
return SKIP_BODY;//直接跳过标签体
}else {// 如果集合不为空,并且是一个长度不为0的集合
Iterator<Object> it = items.iterator();//得到集合的迭代器
Object next = it.next(); // 取出集合中的第一个元素
pageContext.setAttribute(this.var, next);//把第一个元素保存到作用域中,键为var中的值
pageContext.setAttribute("it", it); //将迭代器保存到作用域中
if (null != this.varStatus && !"".equals(this.varStatus.trim())) {//如果状态对象不为空,且不为空字符串
Status status = new Status();//实例化状态对象
pageContext.setAttribute(this.varStatus, status);
}
return EVAL_BODY_INCLUDE;
}
}
}
Select标签:
实体类:
package com.zking.tag;
/**
* 实体类 部门类
* @author Administrator
*
*/
public class Dept {
private Integer did;
private String dname;
public Integer getDid() {
return did;
}
public void setDid(Integer did) {
this.did = did;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public Dept() {
// TODO Auto-generated constructor stub
}
public Dept(Integer did, String dname) {
this.did = did;
this.dname = dname;
}
@Override
public String toString() {
return "Dept [did=" + did + ", dname=" + dname + "]";
}
}
标签助手类:
package com.zking.tag;
import java.lang.reflect.InvocationTargetException;
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;//数据源
private String valueName;//数据源中写入到select标签option中value值对应的属性名
private String textName;//数据源中写入到select标签option中文本值对应的属性名
private String name;
private String headText;
private String selectOptionValue; //默认选中的value值
private String cssStyle; //样式
public List<Object> getItems() {
return items;
}
public void setItems(List<Object> items) {
this.items = items;
}
public String getValueName() {
return valueName;
}
public void setValueName(String valueName) {
this.valueName = valueName;
}
public String getTextName() {
return textName;
}
public void setTextName(String textName) {
this.textName = textName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHeadText() {
return headText;
}
public void setHeadText(String headText) {
this.headText = headText;
}
public String getSelectOptionValue() {
return selectOptionValue;
}
public void setSelectOptionValue(String selectOptionValue) {
this.selectOptionValue = selectOptionValue;
}
public String getCssStyle() {
return cssStyle;
}
public void setCssStyle(String cssStyle) {
this.cssStyle = cssStyle;
}
@Override
public int doStartTag() throws JspException {
JspWriter out = pageContext.getOut();
try {
out.println(toHtml());
} catch (Exception e) {
throw new RuntimeException(e);
}
return super.doStartTag();
}
/**
* 拼接html代码
*<select name="">
<option value="1">财务部</option>
<option value="2">教学部</option>
<option value="3">就业部</option>
<option value="4">教质部</option>
</select>
* @return
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public String toHtml() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
StringBuffer sb = new StringBuffer();
if(null==items || 0==items.size()) {//如果数据源为空,或者长度为0
//就直接返回一个空字符串
return "";
}
sb.append("<select");
sb.append(" name='"+name+"' ");
if(null!=this.cssStyle) {
sb.append(" style='"+cssStyle+"' ");
}
sb.append(" >");
if(null!=headText && !"".equals(headText)) {
sb.append("<option>"+headText+"</option>");
}
Object value = null;
Object text = null;
//遍历数据源
for (Object obj : items) {
//1.获得类对象 object.getClass
//2.获取did属性对象,通过属性名
//3.打开属性限制
//4.get获取属性值
//反射获取对象的属性值
//获取option中的value的值
value=PropertyUtils.getProperty(obj,this.valueName );
//获取option中的文本的值
text=PropertyUtils.getProperty(obj,this.textName);
if(selectOptionValue.equals(value.toString())) {//如果传过来的selectOptionValue值和获取的value值一致,就默认选中
sb.append("<option selected=\"selected\" value='"+value+"'>"+text+"</option>");
}else {
sb.append("<option value='"+value+"'>"+text+"</option>");
}
}
//拼接结束标签
sb.append("</select");
return sb.toString();
}
}
这里为了方便是通过反射工具类来反射对象获取属性值,既然是工具类就要导jar包,如图所示:
工具类的两个反射获取属性方法
PropertyUtils.getProperty(bean, name);返回Object
BeanUtils.getProperty(bean, name);返回String
配置mytag.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>z</short-name>
<!-- 你标签库的引用uri -->
<uri>/zking</uri>
<tag>
<!-- 标签名 -->
<name>out</name>
<!-- 标签工具类 -->
<tag-class>com.zking.tag.OutTag</tag-class>
<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
<body-content>jsp</body-content>
<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
<attribute>
<!-- 自定义标签的属性名称 -->
<name>value</name>
<!-- true表示必填 -->
<required>true</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<!-- 标签名 -->
<name>if</name>
<!-- 标签工具类 -->
<tag-class>com.zking.tag.IfTag</tag-class>
<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
<body-content>jsp</body-content>
<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
<attribute>
<!-- 自定义标签的属性名称 -->
<name>test</name>
<!-- true表示必填 -->
<required>true</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<!-- 标签名 -->
<name>forEach</name>
<!-- 标签工具类 -->
<tag-class>com.zking.tag.ForEachTag</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>
</attribute>
<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
<attribute>
<!-- 自定义标签的属性名称 -->
<name>var</name>
<!-- true表示必填 -->
<required>true</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
<attribute>
<!-- 自定义标签的属性名称 -->
<name>varStatus</name>
<!-- true表示必填 -->
<required>false</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
<tag>
<!-- 标签名 -->
<name>select</name>
<!-- 标签工具类 -->
<tag-class>com.zking.tag.SelectTag</tag-class>
<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
<body-content>empty</body-content>
<!-- 自定义标签的属性定义,请注意一定要在标签类中提供对应的get/set方法 -->
<attribute>
<!--自定义标签的属性名称 -->
<name>items</name>
<!-- true表示必填 -->
<required>true</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<!--自定义标签的属性名称 -->
<name>name</name>
<!-- true表示必填 -->
<required>false</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<!--自定义标签的属性名称 -->
<name>valueName</name>
<!-- true表示必填 -->
<required>true</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<!--自定义标签的属性名称 -->
<name>textName</name>
<!-- true表示必填 -->
<required>true</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<!--自定义标签的属性名称 -->
<name>headText</name>
<!-- true表示必填 -->
<required>false</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<!--自定义标签的属性名称 -->
<name>selectOptionValue</name>
<!-- true表示必填 -->
<required>false</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<!--自定义标签的属性名称 -->
<name>cssStyle</name>
<!-- true表示必填 -->
<required>false</required>
<!-- true支持动态值,可以向值里面填jsp表达式、EL表达式,false则不支持 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
index.jsp
<%@page import="com.zking.tag.Dept"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="z" uri="/zking" %>
<!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>
<%
String name = "大黄";
request.setAttribute("name",name);
List list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
request.setAttribute("list", list);
List<Dept> deptlist = new ArrayList<Dept>();
deptlist.add(new Dept(1,"财务部"));
deptlist.add(new Dept(2,"教学部"));
deptlist.add(new Dept(3,"就业部"));
deptlist.add(new Dept(4,"教质部"));
request.setAttribute("deptlist", deptlist);
%>
<!-- 自定义out标签 -->
<c:out value="${name }"></c:out>
<z:out value="${name }"></z:out>
<br>
<!-- 自定义if标签 -->
<c:if test="${name eq '大黄'}">
来了老弟
</c:if>
<z:if test="${name eq '大黄'}">
走了老弟
</z:if>
<br>
<!-- 自定义foreach标签 -->
<c:forEach items="${list }" var="s" varStatus="vs">
${s },${vs.index },${vs.count }
</c:forEach>
<z:forEach items="${list }" var="s" varStatus="vs">
${s },${vs.index },${vs.count }
</z:forEach>
<br>
<!--自定义select标签 -->
<select name="" style="width:140px">
<option>请选择</option>
<option value="1">财务部</option>
<option value="2">教学部</option>
<option selected="selected" value="3">就业部</option>
<option value="4">教质部</option>
</select>
<z:select name="" cssStyle="width:140px" selectOptionValue="4" headText="----请选择---" items="${deptlist}" valueName="did" textName="dname"/>
</body>
</html>
效果图: