jsp自定义标签(二)

一、前言

上篇博客地址指路牌:自定义标签(一)
上一篇博客中我们已经讲述了自定义标签的开发步骤和简单实例,这篇博客我们讲述一下两个比较复杂的自定义标签。

二、自定义forEach标签实例

2.1代码示例

按照自定义标签开发步骤,首先写一个助手类:
items:需要遍历的集合;
name(一般来说用var来表示,我因为之前测试改成了name):保存集合中每个元素的key值;
varStatus:是保存index count 属性的对象的key;
代码详解跟随在代码中:

package com.zengjing.jsp.day0202;

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 static final long serialVersionUID = 1L;
	
	private List<Object> items;//需要遍历的集合
	
	private String name;//保存集合中每个元素的key值
	
	private String varStatus;//是保存index count 属性的对象的key
	
	//匿名内部类 将其视作对象,index 和count视作属性来操作
	public static class Status{
		//定义一个index用来读取下标
		public int index=0;

		public int getIndex() {
			return index;
		}

		public void setIndex(int index) {
			this.index = index;
		}
		/**
		 * 借助index来获取这是第几个值
		 * @return
		 */
		public int getCount() {
			return this.index+1;
		}
		/**
		 * index自增方法
		 */
		void incremetn(){
			this.index++;
		}
		
	}
	
	public String getVarStatus() {
		return varStatus;
	}



	public void setVarStatus(String varStatus) {
		this.varStatus = varStatus;
	}



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

	

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

	




	public String getName() {
		return name;
	}



	public void setName(String name) {
		this.name = name;
	}



	/**
	 * 执行到doAfterBody方法时,有需要操作的代码
	 */
	@Override
	public int doAfterBody() throws JspException {
		//获取之前存储的迭代器
		Iterator<Object> it =(Iterator<Object>) pageContext.getAttribute("it");
		//如果他有下一个值
		while(it.hasNext()) {
			//如果varStatus有值
			if(null!=varStatus && !"".equals(varStatus)) {
				//获取到varStatus的值
				Status s =(Status) pageContext.getAttribute(varStatus);
				//执行自增的方法
				s.incremetn();
				//重新保存到varStatus
				pageContext.setAttribute(varStatus, s);
			}
			//再获取到迭代器的下一个值
			Object next = it.next();
			//再保存到name中
			pageContext.setAttribute(name, next);
			//再执行主体一次
			return EVAL_BODY_AGAIN;
		}
		//如果没有下一个值就会跳出主体结束循环
		return super.doAfterBody();
	}


	/**
	 * 进入助手类首先执行的doStartTag方法
	 */
	@Override
	public int doStartTag() throws JspException {
		//第一次进入doStartTag方法的时候,varStatus如果有值,我们需要new一个Status给它,用来读取下标和个数
		if(null!=varStatus && !"".equals(varStatus)) {
			pageContext.setAttribute(varStatus, new Status());
		}
		//当集合不是空的时候,我们需要操作集合
		if(null!=items && 0!=items.size()) {
			//获取到他的迭代器
			Iterator<Object> it = items.iterator();
			//通过迭代器获取下一个值
			Object next = it.next();
			//将下一个值保存到name中
			pageContext.setAttribute(name, next);
			//将迭代器保存到当前页面
			pageContext.setAttribute("it", it);
			
			
		}
		return EVAL_BODY_INCLUDE;
	}
	
}

配置tld文件中的属性:
items:必填可为表达式;
name:必填不可为表达式;
varStatus:非必填不可为表达式;

 <tag>
	    <name>forEach</name>
	    <tag-class>com.zengjing.jsp.day0202.ForEachTag</tag-class>
	    <body-content>JSP</body-content>
	     <attribute>
	    	<name>items</name>
	    	<required>true</required>
	    	<rtexprvalue>true</rtexprvalue>
	    </attribute>
	    <attribute>
	    	<name>name</name>
	    	<required>true</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	     <attribute>
	    	<name>varStatus</name>
	    	<required>false</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	 </tag>

头部导入taglib标签:
在这里插入图片描述
效果图:
依次是集合中的内容、下标、第几个
在这里插入图片描述

2.2 注意事项

写forEach标签助手类的时候,保存值的时候一定不能忘记!否则会报空指针异常:
在这里插入图片描述

三、自定义select标签实例

3.1代码示例

按照自定义标签开发步骤,首先写一个助手类:
items:需要用select展示的集合
name:select的名字
valueKey:保存option中的value的key
textKey:保存option中text文本的key
cssStyle:样式
headKey:默认展示的key值
headValue:默认展示的文本
selectedOptionValue:默认选中的key值
代码详解在代码中:

package com.zengjing.jsp.day0202;

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;//需要用select展示的集合
	
	private String name;//select的名字
	
	private String valueKey;//保存option中的value的key

	private String textKey;//保存option中text文本的key
	
	private String cssStyle;//样式
	
	private String headKey;//默认展示的key值
	
	private String headValue;//默认展示的文本
	

	private String selectedOptionValue;//默认选中的key值

	public String getSelectedOptionValue() {
		return selectedOptionValue;
	}

	public void setSelectedOptionValue(String selectedOptionValue) {
		this.selectedOptionValue = selectedOptionValue;
	}

	public String getHeadKey() {
		return headKey;
	}

	public void setHeadKey(String headKey) {
		this.headKey = headKey;
	}

	public String getHeadValue() {
		return headValue;
	}

	public void setHeadValue(String headValue) {
		this.headValue = headValue;
	}

	public String getCssStyle() {
		return cssStyle;
	}

	public void setCssStyle(String cssStyle) {
		this.cssStyle = cssStyle;
	}

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

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

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getValueKey() {
		return valueKey;
	}

	public void setValueKey(String valueKey) {
		this.valueKey = valueKey;
	}

	public String getTextKey() {
		return textKey;
	}

	public void setTextKey(String textKey) {
		this.textKey = textKey;
	}

	/**
	 * 首先实例化助手类进入doStartTag方法
	 */
	@Override
	public int doStartTag() throws JspException {
		//获取到out
		JspWriter out = pageContext.getOut();
		try {
			//通过打印输出方法返回的字符串将内容展示在页面
			out.println(toHtml());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return super.doStartTag();
	}
	
	private String toHtml() throws Exception {
		//用StringBuffer拼接需要返回的字符串
		StringBuffer sb=new StringBuffer();
		//拼接开头
		sb.append("<select name='"+name+"' ");
		//拼接样式
		sb.append(" style='"+cssStyle+"' ");
		
		sb.append(">");
		
		System.out.println(items.size());
		//如果集合不是空的再操作下面的代码
		if(null!=items && 0!=items.size()) {
			//如果需要默认展示内容的不是空的,先拼接默认展示的内容
			if(null!=headKey && !"".equals(headKey.trim())) {
				sb.append("<option value='"+headKey+"' >"+headValue+"</option>");
			}
			//先定义要拼接的option中的value和text
			Object value=null;
			Object text =null;
			for (Object o : items) {
				//通过反射获取到集合中的对象对应的属性
				value = PropertyUtils.getProperty(o, valueKey);
				text = PropertyUtils.getProperty(o, textKey);
				//如果需要默认展示的key值与集合中的key值相等,把这一条数据默认展示
				if(selectedOptionValue.equals(value.toString())) {
					sb.append("<option selected value='"+value.toString()+"' >"+text.toString()+"</option>");
				}else {
					sb.append("<option value='"+value.toString()+"' >"+text.toString()+"</option>");				
			
				}
			}
			//System.out.println(value.toString()+text.toString());
			
		}
		
		sb.append("</select>");
		
		return sb.toString();
	}
	
}

需要配置的tld文件:
items:必填可为表达式
name:非必填不可为表达式
valueKey:必填不可为表达式
textKey:必填不可为表达式
cssStyle:非必填不可为表达式
headKey:非必填不可为表达式
headValue:非必填不可为表达式
selectedOptionValue:非必填不可为表达式

 <tag>
	    <name>select</name>
	    <tag-class>com.zengjing.jsp.day0202.selectTag</tag-class>
	    <body-content>JSP</body-content>
	     <attribute>
	    	<name>items</name>
	    	<required>true</required>
	    	<rtexprvalue>true</rtexprvalue>
	    </attribute>
	    
	    <attribute>
	    	<name>name</name>
	    	<required>false</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	    <attribute>
	    	<name>valueKey</name>
	    	<required>true</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	     <attribute>
	    	<name>textKey</name>
	    	<required>true</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	    <attribute>
	    	<name>cssStyle</name>
	    	<required>false</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	     <attribute>
	    	<name>headKey</name>
	    	<required>false</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	     <attribute>
	    	<name>headValue</name>
	    	<required>false</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	    <attribute>
	    	<name>selectedOptionValue</name>
	    	<required>false</required>
	    	<rtexprvalue>false</rtexprvalue>
	    </attribute>
	    
	 </tag>

头部导入taglib标签:
在这里插入图片描述
效果图:
在这里插入图片描述

3.2 注意事项

1.这里用value作比较时需要.toString(),不然因为它本来是object类型会比较不了:
在这里插入图片描述
2.拼接时也一定要小心不要拼错!单引号不要忘了!
3.还有反射需要这两个包:
在这里插入图片描述

四、今日总结

自定义标签到此结束!有问题欢迎留言评论指教哦!
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值