0
点赞
收藏
分享

微信扫一扫

自定义JSP[foreach,select]标签

脱下愤怒的小裤衩 2022-04-07 阅读 62

                                        foreach

业务

在定义foreach标签时我们需要了解它的业务是什么:很显然foreach标签需要得到一个集合,然后再这个集合的基础上遍历这个集合。当我们清楚业务逻辑后就可以开始定义foreach标签了

既然是需要得到一个集合,然后再遍历这个集合。那我们就知道了需要两个属性,一个是得到一个集合属性,另一个是遍历这个集合的值。


定义助手类

public class ForeachTag extends BodyTagSupport{

	//接收传进来的集合
	private List<?> items;
	
	//遍历输出的值
	private String var;

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

	public void setVar(String var) {
		this.var = var;
	}
	
	@Override
	public int doStartTag() throws JspException {
		
		if(this.items==null|"".equals(this.items)) {
			return SKIP_BODY;
		}
		//使用迭代器
		Iterator<?> iter = this.items.iterator();
		//得带它的下一位
		Object next = iter.next();
		//把下一位的值赋值给var
		this.pageContext.setAttribute(this.var, next);
		this.pageContext.setAttribute("iterator", iter);
		
		
		return EVAL_BODY_INCLUDE;
	}
	
	
	@Override
	public int doAfterBody() throws JspException {
		
		Iterator<?> iter=(Iterator<?>) this.pageContext.getAttribute("iterator");
		
		if(iter.hasNext()) {
			 Object next= iter.next();
			 this.pageContext.setAttribute(this.var, next);
			 return EVAL_BODY_AGAIN;
		}
		
		return SKIP_BODY;
	}
	
	
	
}

代码讲解

doStartTag()方法

在doStartTag()方法中,我们首先需要判断传进来的值是否有数据,如果连数据都没有的话那还怎么遍历呢。

if(this.items==null|"".equals(this.items)) {
			return SKIP_BODY;
		}

 如果有数据,if条件为false的话,就可以继续开始编写我们的代码了。因为我们是要遍历数据,所以我们需要把集合里面的值一个一个输出,然后一个一个的赋值。在这里我们就使用到了iterator()也就是迭代器。在迭代器中如果有值,我们就把值赋值给var,也就是我定义的遍历输出的值。注意:在这里我们不能直接在dostartTag方法里面把当前集合给赋值完,因为dostartTag方法只是开始,它是不能直接处理标签体的。如果不懂可以看下我前面的一篇文章,在那里我写到过。所以接下来我们就需要把迭代器的值用pageContext存储起来,在doAfterBody方法中要使用到

//使用迭代器
		Iterator<?> iter = this.items.iterator();
		//得带它的下一位
		Object next = iter.next();
		//把下一位的值赋值给var
		this.pageContext.setAttribute(this.var, next);
		this.pageContext.setAttribute("iterator", iter);

doAfterBody方法

在doAfterBody方法里面我们首先要得到我们存储的迭代器,然后就可以开始判断迭代器中是否还有数据。如果有数据,就把数据赋值到var中,如果没有则结束

EVAL_BODY_AGAIN:表示再次进入循环体

if(iter.hasNext()) {
			 Object next= iter.next();
			 this.pageContext.setAttribute(this.var, next);
			 return EVAL_BODY_AGAIN;
		}

现在我们的助手类已经编写完,接下来就可以开始定义我们的tld文件了

定义tld文件

<taglib >
	<tlib-version>1.0</tlib-version><!-- tld版本号 -->
	<jsp-version>1.2</jsp-version><!-- jsp版本号 -->
	<short-name>Simple Tags</short-name>
	<uri>/zking</uri><!-- 自己定义的路径 -->

<!-- foreach标签定义 -->
	<tag>
		<name>foreach</name>
		<tag-class>com.zking.jee09.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>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
	</tag>



</taglib>

tld文件的属性名是什么意思我就不在赘述了,这个也在我前面一篇文章里面讲解了。当我们tld文件定义好后就可以开始在页面上使用自定义jsp标签了


使用自定义jsp标签

<%
	//获取数据
		List<Book> ls=TestData.getBooks(); 
		
	//把数据放到request里面
	request.setAttribute("ls", ls);
	%>
	
	<!-- 使用foreach标签 -->
	<z:foreach items="${ls}" var="book">
		<p>${book.id}</p>
		<p>${book.name }</p>
	</z:foreach>

list集合是我定义的一个测试实体类,代码如下

public class Book {

	private int id;
	private String name;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}

代码讲解

因为在我们自定义jsp标签中,我们是需要判断传入的集合是否有值。所以我们在使用jsp标签之前,需要得到一个集合。所以就需要在jsp页面中写入java代码

<%
	//获取数据
		List<Book> ls=TestData.getBooks(); 
		
	//把数据放到request里面
	request.setAttribute("ls", ls);
	%>

之后我们再使用我们自己定义的jsp标签就可以了

<!-- 使用foreach标签 -->
	<z:foreach items="${ls}" var="book">
		<p>${book.id}</p>
		<p>${book.name }</p>
	</z:foreach>

这样我们的foreach标签就定义完了,接下来就开始定义我们的select标签

                                select标签

业务

使用select标签无疑就是要用到下拉按钮,在下来按钮中我们可以设置样式,可以设置id,可以设置name属性,还可以设置默认选中的值。所以这些都是我们在定义select标签中需要考虑的。那接下来就可以开始我们的助手类了

助手类


/**
 * select option  助手类
 * @author Administrator
 *
 */
public class SelectTag extends BodyTagSupport{

	//属性id
	private int id;
	
	//名称
	private String name;
	
	//读取数据库表
	private List<?> items;
	
	//提交值
	private String value;
	
	//表单名称
	private String test;
	
	//外部class样式
	private String cssClass;
	
	//内部样式
	private String cssStyle;
	
	//默认选中的值
	private String selectValue;
	
	//自动加载函数
	private String onChange;

	public void setId(int id) {
		this.id = id;
	}

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

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

	public void setValue(String value) {
		this.value = value;
	}

	public void setTest(String test) {
		this.test = test;
	}

	public void setCssClass(String cssClass) {
		this.cssClass = cssClass;
	}

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

	public void setSelectValue(String selectValue) {
		this.selectValue = selectValue;
	}

	public void setOnChange(String onChange) {
		this.onChange = onChange;
	}
	
	
	@Override
	public int doStartTag() throws JspException {
		JspWriter out =this.pageContext.getOut();
		try {
			out.println(html());
		} catch (IllegalAccessException|InvocationTargetException|NoSuchMethodException e) {
			e.printStackTrace();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return super.doStartTag();
	}
	
	
	
	private String html() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		
		StringBuilder sb=new StringBuilder();
		
		sb.append("<select id='"+this.id+"' name='"+this.name+"'");
		
		if(this.cssClass!=null|!"".equals(this.cssClass)) {
			sb.append(" class='"+this.cssClass+"'");
		}
		
		if(this.cssStyle!=null|!"".equals(this.cssStyle)) {
			sb.append(" style='"+this.cssStyle+"'");
		}
		
		if(this.onChange!=null|!"".equals(this.onChange)) {
			sb.append(" onchange='"+this.onChange+"'");
		}
		
		sb.append(">");
		
		for (Object obj : this.items) {
			String val= BeanUtils.getProperty(obj, this.value);
			String txt= BeanUtils.getProperty(obj, this.test);			
			boolean f=this.selectValue!=null&!"".equals(this.selectValue)&val.equals(this.selectValue);
			
			if(f==true) {
				sb.append("<option value='"+val+"' selected>" +txt+"</option>");
			}else {
				sb.append("<option value='"+val+"' >" +txt+"</option>");
			}
			
		}
		sb.append("</select>");
		
		return sb.toString();
		
		
	}
	
	
	
}

在助手类中其实跟foreach差不多,如果你认真看来foreach标签应该就能理解。

代码讲解

dostartTag方法

在dostartTag方法中就只有一个功能,就是显示下拉款而且。

@Override
	public int doStartTag() throws JspException {
		JspWriter out =this.pageContext.getOut();
		try {
			out.println(html());
		} catch (IllegalAccessException|InvocationTargetException|NoSuchMethodException e) {
			e.printStackTrace();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return super.doStartTag();
	}
	

private String html()方法

在这个方法中我们需要显示下拉款功能。因为我们是需要使用在jsp页面中的,所以我们需要在这个方法中写入HTML代码。在java代码中要写入HTML代码的话就需要使用拼接的方式来完成。这里有三种方法,第一个StringBuilder,第二个String,第三个StringBuffer。这三个有什么区别呢?还真的有区别,

StringBuilder

线程不安全,但是在使用拼接的时候速度会很快

String

在每次new的时候会产生新的节点,但是在jdk8之后使用拼接是跟StringBuilder一样的效果

StringBuffer

线程安全,但是速度慢


所以我们是在局部变量里面使用的,这里我就使用了StringBuilder的拼接方式来完成。因为我们不清楚每个人想要实现的功能是什么,所以我们需要对可写,可不写的属性要进行判断。如果需要此功能则加进去,如果不需要就不用增加进去

StringBuilder sb=new StringBuilder();
		
		sb.append("<select id='"+this.id+"' name='"+this.name+"'");
		
		if(this.cssClass!=null|!"".equals(this.cssClass)) {
			sb.append(" class='"+this.cssClass+"'");
		}
		
		if(this.cssStyle!=null|!"".equals(this.cssStyle)) {
			sb.append(" style='"+this.cssStyle+"'");
		}
		
		if(this.onChange!=null|!"".equals(this.onChange)) {
			sb.append(" onchange='"+this.onChange+"'");
		}
		
		sb.append(">");
		
		

接下来就要遍历我们的items了,为什么要遍历它呢?原因很简单。因为我们存储的是下拉框,那些数据是在数据库表里面的,所以我们需要定义一个集合来接收它。

在这里面我们需要进行判断默认选中的值,如果有默认选中的值则选中,没有则默认选中第一个。

for (Object obj : this.items) {
			String val= BeanUtils.getProperty(obj, this.value);
			String txt= BeanUtils.getProperty(obj, this.test);			
			boolean f=this.selectValue!=null&!"".equals(this.selectValue)&val.equals(this.selectValue);
			
			if(f==true) {
				sb.append("<option value='"+val+"' selected>" +txt+"</option>");
			}else {
				sb.append("<option value='"+val+"' >" +txt+"</option>");
			}
			
		}
		sb.append("</select>");

定义tld文件

<!-- select标签定义 -->
	<tag>
		<name>select</name>
		<tag-class>com.zking.jee09.SelectTag</tag-class>
		<!--该标签有标签体-->
		<body-content>empty</body-content>
		<attribute>
			<name>id</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>name</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>items</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>value</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>test</name>
			<required>true</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>selectValue</name>
			<required>false</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>cssClass</name>
			<required>false</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>cssStyle</name>
			<required>false</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
		
		<attribute>
			<name>onChange</name>
			<required>false</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute>
	</tag>

在页面上使用自定义jsp标签

<z:select name="aa" id="aa" test="name" items="${ls}" value="id" selectValue="2"/>

在这里我使用了我在上面定义的实体类,在这里value值就是book实体类中的id,items就是book实体类的集合,test是下拉框的名称,selectValue是默认选中的下拉框。这样直接复制代码区试一下,这样我们的select标签就出来了

举报

相关推荐

0 条评论