自定义标签

 

 

EL的不足,由JSTL来加强  -> 自定义标签来实现。

 

1:自定义标签

1:自定义标签也是类。

2:让用户在JSP页面使用,不引用Java代码的情况下,调用Java代码。

 

2:标签开的类的继承关系

 

 

3:快速的标签示例

1:创建一个类实现接口Tag

package cn.tag;

 

import java.text.SimpleDateFormat;

import java.util.Date;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.JspWriter;

import javax.servlet.jsp.PageContext;

import javax.servlet.jsp.tagext.Tag;

 

public class DateTag implements Tag {

/**

 * 为了在其他的方法中使用pageContext

 *

 */

private PageContext pageContext;

 

/**

 * 当在页面上使用了这个标签,当jsp在运行时,会先调用此方法 <br>

 * 将pageContext传递到DataTag类中类

 */

@Override

public void setPageContext(PageContext pc) {

this.pageContext = pc;

}

 

/**

 * 当这个标签开始时,即容器来调用以下的方法 <c:out> 标签的body部分 </c:out>

 */

@Override

public int doStartTag() throws JspException {

// 输出当前时间,到页面上去

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String str = sdf.format(new Date());

// 输出如果要输出,获取JspWriter就可以了

JspWriter out = pageContext.getOut();

try {

out.print("当前时间是:" + str);

} catch (Exception e) {

e.printStackTrace();

}

/*

 * 返回值是有固定值的 这个的返回值,决定了这个标签后面的body部分如何执行 <br>Tag.EVAL_BODY_INCLUDE

 * 执行body部分 SKIP_BODY:不执行body部分不显示

 */

return SKIP_BODY;

}

 

/**

 * 当执行标签结束的时</c:out>时执行以下的代码 <br>

 * 返回的值是: SKIP_PAGE : 页面的后面的部分,不执行不显<br>

 * EVAL_PAGE : 执行页面的 后面的部分

 */

@Override

public int doEndTag() throws JspException {

return EVAL_PAGE;

}

 

2:添加标签的配置文件

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="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">

    

  

 

</taglib>

 

 

以下是开发完成的完整的配置:

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="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">

<!-- 标签的版本 -->

   <tlib-version>1.0</tlib-version>

   <!-- 声明标签的名称 -->

    <short-name>ql</short-name>

<!-- 声明标签的引用方式标识符号 -->

<uri>/ql.com</uri>

<!-- 声明自己的标签 -->

<tag>

<!-- 声明标签的名称 -->

<name>date</name>

<!-- 声明标签的服务类 -->

<tag-class>cn.tag.DateTag</tag-class>

<!-- 声明body的内容是什么 -->

<body-content>empty</body-content>

</tag>

</taglib>

3:在JSP页面上引用

<%@ taglib uri="/ql.com" prefix="ql" %>

 

使用:

<ql:date/>

 

 

 

4:继承TagSupport

 

 

 

 

public class Date2Tag extends TagSupport {

@Override

public int doStartTag() throws JspException {

String str = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date());

JspWriter out = pageContext.getOut();

try {

out.print("当前的时间为:" + str);

} catch (Exception e) {

}

return SKIP_BODY;

}

}

配置:
<tag>

<name>myDate2</name>

<tag-class>cn.tag.Date2Tag</tag-class>

<body-content>empty</body-content>

</tag>

 

以下是使用:

<ql:myDate2/>

 

 

 

 

 

5:标签的功能

功能:

  让程序员在页面上像是使用HTML标签一样,使用Java代码。

 

防止重复提交:

  以下的情况下,可能会发生重复提交:

   1:刷新页面。

   2:服务或是网络比较慢。

 

如何防止重复提交:

   使用Session

在JSP页面上,生成一个UUID放放到Session中去。

同时在JSP页面上,和验证码一样,自动的提交这个UUID.

后台代码,从提交信息中,和Session中获取这个UUID的值比较。

 

 

 

 

 

 

自定义标签:

   

 

public class TokenTag extends TagSupport {

@Override

public int doStartTag() throws JspException {

String uuid = UUID.randomUUID().toString().replace("-", "");

pageContext.getSession().setAttribute("token", uuid);

// 向页面上输出

JspWriter out = pageContext.getOut();

try {

String html = "<input type='hidden' value='" + uuid + "' name='token'/>";

out.print(html);

} catch (Exception e) {

e.printStackTrace();

}

return SKIP_BODY;

}

}

 

配置:
<tag>

<name>token</name>

<tag-class>cn.tag.TokenTag</tag-class>

<body-content>empty</body-content>

</tag>

 

 

6:标签的细节

<body-content>JSP</body-content>

   JSP 可以包含任意的JSP代码

在doStartTag中返回的是skip_body,则有内容也不显示。

                        Eval_body_include则显示,执行body部分内容

   Empty : 则不能包含任意的内容

 

 

 doEndTag的返回值

Skip_page : 页面的后面的部分不显示

Eval_page : 则页面的后面的部分显示。

 

 

7:接收属性的标签、

<c:out value=.../>  c前缀 ,out标签功能   value = ... 属性。

 

让标签接收属性:

  思想:

     1:在标签类里面声明setXxx方法用于接收属性的值。

     2:在*.tld的配置文件中,声明这个标签类有xxx属性。

     3:在JSP页面上,使用标签时,设置属性的值。

 

修改时间:

   <ql:date2 name=张三/> - = >  你好张三,当前时间是:...

 

 

 

<!-- 声明属性 -->

<attribute>

<name>name</name>

<required>true</required>

<!-- runtime expression value是否接收运行时间 表达 式的值,即${..} -->

<rtexprvalue>true</rtexprvalue>

<type>java.lang.String</type>

</attribute>

 

<ql:myDate2 name="Jack"/>

<ql:myDate2 name="${param.name}"/>

 

 

8:遍历的标签

<c:forEach items=${map | list | set | String[] | Ob ject[] | int[] | double[]  | ..  } var=name>

     ${name} - > EL - > 表示:pageContext.findAttribute(name);从四个域对象中找

</c:forEach>

 

 

多一个方法 :

   

package cn.tag;

 

import java.lang.reflect.Array;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

 

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.TagSupport;

 

public class ForTag extends TagSupport {

// 声明一个可以遍历的对象

private Iterator<Object> it;

 

public void setItems(Object obj) {

if (obj instanceof Collection) {// List/Set

it = ((Collection) obj).iterator();

} else if (obj instanceof Map) {

it = ((Map) obj).entrySet().iterator();

} else if (obj.getClass().isArray()) {

// 获取数组的长度

int len = Array.getLength(obj);

List<Object> list = new ArrayList<Object>();

for (int i = 0; i < len; i++) {

Object val = Array.get(obj, i);

list.add(val);

}

it = list.iterator();

} else {

throw new RuntimeException("不接收的类型" + obj.getClass());

}

}

 

private String var;

 

public void setVar(String var) {

this.var = var;

}

 

@Override

public int doStartTag() throws JspException {

if (it.hasNext()) {

// 获取这什个值

pageContext.setAttribute(var, it.next());

return EVAL_BODY_INCLUDE;

} else {

return SKIP_BODY;

}

}

 

@Override

public int doEndTag() throws JspException {

pageContext.removeAttribute(var);

return EVAL_PAGE;

}

 

 

@Override

public int doAfterBody() throws JspException {

if (it.hasNext()) {

// 获取这什个值

pageContext.setAttribute(var, it.next());

return EVAL_BODY_AGAIN;

} else {

return SKIP_BODY;

}

}

}

 

 

 


<tag>

<name>for</name>

<tag-class>cn.tag.ForTag</tag-class>

<body-content>JSP</body-content>

<attribute>

<name>items</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

<type>java.lang.Object</type>

</attribute>

<attribute>

<name>var</name>

<required>true</required>

<rtexprvalue>false</rtexprvalue>

<type>java.lang.String</type>

</attribute>

</tag>

 

a

 

 

 

9:使用simpletagsupport实现

public class HelloTag extends SimpleTagSupport {

@Override

public void doTag() throws JspException, IOException {

String str = new Date().toLocaleString();

JspWriter out = getJspContext().getOut();

out.print("你好当前时间是:" + str);

}

}

 

<tag>

<name>hello</name>

<tag-class>cn.tag.HelloTag</tag-class>

<body-content>empty</body-content>

</tag>

 

接收属性,就是声明

setXxx,修改tld文件,在页面上传递

private String name;

public void setName(String name) {

this.name = name;

}

 

<tag>

<name>hello</name>

<tag-class>cn.tag.HelloTag</tag-class>

<body-content>empty</body-content>

<attribute>

<name>name</name>

<required>yes</required>

<rtexprvalue>true</rtexprvalue>

<type>java.lang.String</type>

</attribute>

</tag>

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(自定义标签)