EL的不足,由JSTL来加强 -> 自定义标签来实现。
1:自定义标签
1:自定义标签也是类。
2:让用户在JSP页面使用,不引用Java代码的情况下,调用Java代码。
2:标签开的类的继承关系
3:快速的标签示例
1:创建一个类实现接口Tag
packagecn.tag;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importjavax.servlet.jsp.JspException;
importjavax.servlet.jsp.JspWriter;
importjavax.servlet.jsp.PageContext;
importjavax.servlet.jsp.tagext.Tag;
publicclassDateTagimplementsTag {
/**
* 为了在其他的方法中使用pageContext
*
*/
privatePageContextpageContext;
/**
* 当在页面上使用了这个标签,当jsp在运行时,会先调用此方法
* 将pageContext传递到DataTag类中类
*/
@Override
publicvoidsetPageContext(PageContextpc) {
this.pageContext=pc;
}
/**
* 当这个标签开始时,即容器来调用以下的方法标签的body部分
*/
@Override
publicintdoStartTag()throwsJspException {
// 输出当前时间,到页面上去
SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Stringstr=sdf.format(newDate());
// 输出如果要输出,获取JspWriter就可以了
JspWriterout=pageContext.getOut();
try{
out.print("当前时间是:"+str);
}catch(Exceptione) {
e.printStackTrace();
}
/*
* 返回值是有固定值的 这个的返回值,决定了这个标签后面的body部分如何执行
Tag.EVAL_BODY_INCLUDE
* 执行body部分 SKIP_BODY:不执行body部分不显示
*/
returnSKIP_BODY;
}
/**
* 当执行标签结束的时时执行以下的代码
* 返回的值是: SKIP_PAGE : 页面的后面的部分,不执行不显
* EVAL_PAGE : 执行页面的 后面的部分
*/
@Override
publicintdoEndTag()throwsJspException {
returnEVAL_PAGE;
}
2:添加标签的配置文件
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">
以下是开发完成的完整的配置:
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">
1.0
ql
/ql.com
date
cn.tag.DateTag
empty
3:在JSP页面上引用
使用:
4:继承TagSupport
publicclassDate2TagextendsTagSupport {
@Override
publicintdoStartTag()throwsJspException {
Stringstr=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(newDate());
JspWriterout=pageContext.getOut();
try{
out.print("当前的时间为:"+str);
}catch(Exceptione) {
}
returnSKIP_BODY;
}
}
配置:
myDate2
cn.tag.Date2Tag
empty
以下是使用:
5:标签的功能
功能:
让程序员在页面上像是使用HTML标签一样,使用Java代码。
防止重复提交:
以下的情况下,可能会发生重复提交:
1:刷新页面。
2:服务或是网络比较慢。
如何防止重复提交:
使用Session
在JSP页面上,生成一个UUID放放到Session中去。
同时在JSP页面上,和验证码一样,自动的提交这个UUID.
后台代码,从提交信息中,和Session中获取这个UUID的值比较。
自定义标签:
publicclassTokenTagextendsTagSupport {
@Override
publicintdoStartTag()throwsJspException {
Stringuuid= UUID.randomUUID().toString().replace("-","");
pageContext.getSession().setAttribute("token",uuid);
// 向页面上输出
JspWriterout=pageContext.getOut();
try{
Stringhtml="";
out.print(html);
}catch(Exceptione) {
e.printStackTrace();
}
returnSKIP_BODY;
}
}
配置:
token
cn.tag.TokenTag
empty
6:标签的细节
JSP
JSP 可以包含任意的JSP代码
在doStartTag中返回的是skip_body,则有内容也不显示。
Eval_body_include则显示,执行body部分内容
Empty : 则不能包含任意的内容
doEndTag的返回值
Skip_page : 页面的后面的部分不显示
Eval_page : 则页面的后面的部分显示。
7:接收属性的标签、
c前缀 ,out标签功能 value =“...”属性。
让标签接收属性:
思想:
1:在标签类里面声明setXxx方法用于接收属性的值。
2:在*.tld的配置文件中,声明这个标签类有xxx属性。
3:在JSP页面上,使用标签时,设置属性的值。
修改时间:
- = > 你好张三,当前时间是:...
name
true
true
java.lang.String
8:遍历的标签
${name} - > EL - > 表示:pageContext.findAttribute(“name”);从四个域对象中找
多一个方法 :
packagecn.tag;
importjava.lang.reflect.Array;
importjava.util.ArrayList;
importjava.util.Collection;
importjava.util.Iterator;
importjava.util.List;
importjava.util.Map;
importjavax.servlet.jsp.JspException;
importjavax.servlet.jsp.tagext.TagSupport;
publicclassForTagextendsTagSupport {
// 声明一个可以遍历的对象
privateIteratorit;
publicvoidsetItems(Objectobj) {
if(objinstanceofCollection) {// List/Set
it=((Collection)obj).iterator();
}elseif(objinstanceofMap) {
it=((Map)obj).entrySet().iterator();
}elseif(obj.getClass().isArray()) {
// 获取数组的长度
intlen= Array.getLength(obj);
Listlist=newArrayList();
for(inti= 0;i
Objectval= Array.get(obj,i);
list.add(val);
}
it=list.iterator();
}else{
thrownewRuntimeException("不接收的类型"+obj.getClass());
}
}
privateStringvar;
publicvoidsetVar(Stringvar) {
this.var=var;
}
@Override
publicintdoStartTag()throwsJspException {
if(it.hasNext()) {
// 获取这什个值
pageContext.setAttribute(var,it.next());
returnEVAL_BODY_INCLUDE;
}else{
returnSKIP_BODY;
}
}
@Override
publicintdoEndTag()throwsJspException {
pageContext.removeAttribute(var);
returnEVAL_PAGE;
}
@Override
publicintdoAfterBody()throwsJspException {
if(it.hasNext()) {
// 获取这什个值
pageContext.setAttribute(var,it.next());
returnEVAL_BODY_AGAIN;
}else{
returnSKIP_BODY;
}
}
}
for
cn.tag.ForTag
JSP
items
true
true
java.lang.Object
var
true
false
java.lang.String
a
9:使用simpletagsupport实现
publicclassHelloTagextendsSimpleTagSupport {
@Override
publicvoiddoTag()throwsJspException, IOException {
Stringstr=newDate().toLocaleString();
JspWriterout= getJspContext().getOut();
out.print("你好当前时间是:"+str);
}
}
hello
cn.tag.HelloTag
empty
接收属性,就是声明
setXxx,修改tld文件,在页面上传递
privateStringname;
publicvoidsetName(Stringname) {
this.name=name;
}
hello
cn.tag.HelloTag
empty
name
yes
true
java.lang.String