1.要实现自定义的jsp标签,要编写一个助手类,这个类需要实现BodyTagSupport类
而且需要载BodyTagSupport类几个方法:
doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag();
他们执行顺序如下:
doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()
我们拿foeach来进行举例:
编写助手类:并继承BodyTagSupport类(而且必须提供对应属性的get和set方法)
package com.hmc;
import java.util.ArrayList;
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 String var;
private List<Object> items=new ArrayList<Object>();
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;
}
重写方法(foreach使用 doStarTag和doAfterBody方法即可)
)
@Override
public int doStartTag() throws JspException {
Iterator<Object> it=items.iterator();
//作用域进行存值
pageContext.setAttribute(var, it.next());
pageContext.setAttribute("it", it);
//EVAL_BODY_INCLUDE:告诉服务器正文的内容,并把这些内容送入输出流
return EVAL_BODY_INCLUDE;
}
@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);
//EVAL_BODY_AGAIN:让服务器继续处理正文内容
return EVAL_BODY_AGAIN;
}
else {
// EVAL_PAGE:让服务器继续执行页面
return EVAL_PAGE;
}
}
@Override
public void doInitBody() throws JspException {
// TODO Auto-generated method stub
super.doInitBody();
}
@Override
public void setBodyContent(BodyContent b) {
// TODO Auto-generated method stub
super.setBodyContent(b);
}
@Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
return super.doEndTag();
}
说明:
doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,
如果返回EVAL_BODY_INCLUDE则继续执行;
如果返回SKIP_BODY则接下来的doInitBody(),
setBodyContent(),
doAfterBody()三个方法不会被执行,
而直接执行doEndTag()方法。
setBodyContent()方法用于设置标签体内容,
如果在此之前要作一些初始化工作,则在doInitBody()方法中完成。
标签体内容执行完后,会调用doAfterBody()方法,
此方法可返回EVAL_BODY_TAG, SKIP_BODY, EVAL_PAGE或SKIP_PAGE。
如果返回EVAL_BODY_TAG则会再次设置标签体内容,直到返回SKIP_BODY;
如果返回EVAL_PAGE则标签体执行完后会继续执行JSP页面中接下来的部分;
如果返回SKIP_PAGE,则JSP页面的后续内容将不再执行。
返回值:
EVAL_BODY_INCLUDE:告诉服务器正文的内容,并把这些内容送入输出流
SKIP_BODY:告诉服务器不要处理正文内容
EVAL_PAGE:让服务器继续执行页面
SKIP_PAGE:让服务器不要处理剩余的页面
EVAL_BODY_AGAIN:让服务器继续处理正文内容,只有doAfterBody方法可以返回
EVAL_BODY_BUFFERED:BodyTag接口的字段,在doStartTag()返回
EVAL_BODY_INCLUDE、SKIP_BODY一般由doStartTag()返回,而EVAL_PAPGE、SKIP_PAGE由doEndTag()返回。
2.创建tld文件,注:tld的文件格式为xml格式,创建xml时更改后缀名为tld即可;
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Simple Tags</short-name>
<!-- 设置被引用的路径 -->
<uri>/MyJSP</uri>
<!--foreach标签 -->
<tag>
<!-- 定义属性的名称 -->
<name>foreach</name>
<!-- 输入助手类的全路径限定名 -->
<tag-class>com.hmc.ForeachTag</tag-class>
<!-- -指定为jsp元素 -->
<body-content>JSP</body-content>
<!--设置属性 -->
<attribute>
<!-- -定义属性名 -->
<name>items</name>
<!---是否必填 -->
<required>true</required>
<!-- 是否支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>flase</rtexprvalue>
</attribute>
</tag>
3.创建jsp文件对标签进行测试
创建后必须引用文件给的路径(即tld文件的uri)
<%@page import="com.hmc.Stuent"%>
<%@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="/MyJSP" %>
调用foeach测试
<%
List<String> mys=new ArrayList<>();
mys.add("编号1");
mys.add("编号2");
mys.add("编号3");
request.setAttribute("mys", mys);
%>
<z:foreach items="${mys }" var="i">
${i}<br>
</z:foreach>
结果:
编号1
编号2
编号3
forech标签就完成了,当然,这只是一个例子,还有其他的如Out,Set,If,Redirect,selec--->https://i.cnblogs.com/Files.aspx 等标签,这些标签的作用可以提高
我们的开发效率,让程序可以变得更加灵活。达到高内聚,弱耦合的特性。