1.自定义标签步骤
- jsp引入tld文件及标签
- tld文件描述页面标签
- 后端class标签类(TagClass)的关系
2.jsp页面标签——设计(创造)
- 标签结构:<前缀:标签名 属性=”属性值”>标签体
3.extends TagSupport实现自定义标签
1.<%@ taglib prefix="mytag" uri="http://www.lps.com/mytag" %>
<mytag:nowTime format="yyyy-MM-dd HH:mm:ss" var="time" outEl="true">当前时间:${time}</mytag:nowTime>
2.
<?xml version="1.0" encoding="UTF-8" ?>
http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<description>web 1 tag</description>
<display-name>mytag</display-name>
<tlib-version>1.0</tlib-version> <!-- 版本 -->
<short-name>mytag</short-name> <!-- 前缀 -->
http://www.lps.com/mytag>
<tag>
<name>nowTime</name> <!-- 标签名 -->
<tag-class>com.lps.tag.NowTimeTag</tag-class> <!-- 对应类 -->
<body-content>JSP</body-content> <!-- 标签体内容格式 -->
<attribute> <!-- 属性 -->
<name>format</name> <!-- 属性名 -->
<required>false</required> <!-- 属性是不是必须添加 -->
<rtexprvalue>true</rtexprvalue> <!-- 是否可以输入表达式 -->
</attribute>
<attribute>
<name>var</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>outEl</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
3.
public class NowTimeTag extends TagSupport{
//结束标签后运行doEndTag(),开始解析标签时执行doStartTag()
private String format="yyyy年MM月dd日 hh:mm:ss";
private String var;
private boolean outEl;
// @Override
// public int doEndTag() throws JspException {
// System.out.println("doEndTag");
// return EVAL_PAGE;
// }
@Override
public int doStartTag() throws JspException {
try {
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat(format);
String dateStr=sdf.format(date);
if(var!=null&&outEl){
pageContext.setAttribute(var, dateStr);
}else{
pageContext.getOut().print(dateStr);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return EVAL_BODY_INCLUDE;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public boolean isOutEl() {
return outEl;
}
public void setOutEl(boolean outEl) {
this.outEl = outEl;
}
}
PS:
- doStartTag()执行在属性输入之后
- 标签体显示控制:doStartTag()返回值EVAL_BODY_INCLUDE则显示,SKIP_BODY则跳过
- doEndTag()控制后续页面是否显示:EVAL_PAGE,SKIP_PAGE
3.extends TagSupport实现for循环自定义标签
<mytag:for begin="1" end="10" step="1">
a<br>
</mytag:for><br>
public class ForTag extends TagSupport{
private int begin;
private int end;
private int step;
@Override
//在标签体后循环执行
public int doAfterBody() throws JspException {
if(end>=begin){
begin=begin+step;
return EVAL_BODY_AGAIN;
}else{
return EVAL_BODY_INCLUDE;
}
}
@Override
public int doStartTag() throws JspException {
if(end>=begin){
begin=begin+step;
return EVAL_BODY_INCLUDE;
}else{
return SKIP_BODY;
}
}
public int getBegin() {
return begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
}
4.extends BodyTagSupport创建可获取标签提体的自定义标签
<mytag:newBean var="user" type="com.lps.pojo.Users" scope="request" regex="," >
id:1,userName:李四,age:30
</mytag:newBean>
${user.id}<br>
${user.userName }
${user.age }
public class NewBeanTag extends BodyTagSupport{
private String var;
private String type;
private String regex=",";
private String scope="page";
private Class c;
private Object obj;
@Override
public int doEndTag() throws JspException {
try {
String body=bodyContent.getString().trim();
String fields[]=body.split(regex);
for(String field:fields){
String fieldName=field.split(":")[0];
String fieldValue=field.split(":")[1];
String setMethodName="set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
String getMethodName="get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
Method getMethod=c.getMethod(getMethodName, null);
Method setMethod=c.getMethod(setMethodName, getMethod.getReturnType());
if(getMethod.getReturnType()==Integer.class||getMethod.getReturnType()==int.class){
int num=Integer.parseInt(fieldValue);
setMethod.invoke(obj, num);
}else{
setMethod.invoke(obj, fieldValue);
}
}
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return EVAL_PAGE;
}
@Override
public int doStartTag() throws JspException {
try {
c=Class.forName(type);
obj=c.newInstance();
switch(scope){
case "page":pageContext.setAttribute(var, obj);break;
case "request":pageContext.getRequest().setAttribute(var, obj);break;
case "session":pageContext.getSession().setAttribute(var, obj);break;
case "application":pageContext.getServletContext().setAttribute(var, obj);break;
default:pageContext.setAttribute(var, obj);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return EVAL_BODY_BUFFERED;
}
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRegex() {
return regex;
}
public void setRegex(String regex) {
this.regex = regex;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}
ps:
- doStartTag()设置返回值为EVAL_BODY_BUFFERED,将标签体内容放入缓存(内存)
- doEndTag()或doAfterBody()中利用父类的bodyContent对象获取标签体内容。
5.extends SimpleTagSupport创建可获取标签提体的自定义标签
- 重写doTag()方法,没有任何返回值。
- 属性读取,标签体读取getJspBody(),页面输出或会话区间添加值getJspContext(),PageContext.SESSION_SCOPE
标签体读取getJspBody():
StringWriter sw=new StringWriter();
getJspBody().invoke(sw);
System.out.println(sw.toString().trim());
sb.append(sw.toString());
页面输出或会话区间添加值
System.out.println(getJspContext().getAttribute("demo"));
System.out.println(getJspContext().getAttribute("demo",PageContext.SESSION_SCOPE));
getJspContext().setAttribute("demoStr", "李珍基", PageContext.REQUEST_SCOPE);
6.嵌套标签
一般嵌套和普通标签开发无差别,唯一难点——当父标签采用BodyTagSupport并设置EVAL_BODY_BUFFERED时,必须将子表签重新写入父标签输出流,因为此时子标签的输出流不是pageContext.getOut()页面输出流而是父标签的bodyContent对象本身。