自定义标签库
来源:互联网 发布:让人喜欢的女生知乎 编辑:程序博客网 时间:2024/06/07 10:18
1.自定义标签
*步骤:
**编写一个实现Tag接口的Java类,把页面中的java代码移到这个java类中(标签处理器类)
**编写标签库描述符(tld)文件,在tld文件中把标签处理器描述成一个标签。
*作用:
**用于移除JSP页面中的Java代码
**实现代码的重用
**可以使jsp代码更简洁(Jsp2.0的标签扩展API中又增加了SimpleTag接口和其实现类SimpleTagSupport。)
2.TLD文件元素
每个自定义标签都必须在TLD文件中声明,TLD文件也是XML文件,根元素是,它包含一个或者多个标签,该元素用来声明定制标签。元素中只有元素是必须的,其他都是可选的。
TLD的一些常用属性
3.编写第一个自定义标签
实例:编写一个DateTag标签,输出系统时间
eg://1.编写一个DateTag.java类,继承SimpleTagSupport类 public class DateTag extends SimpleTagSupport{//2.override doTag()方法,在该方法中,实现相应的处理逻辑 public void doTag() throws JspException{ PageContext ctx=getJspContext(); JspWriter out=ctx.getOut(); SimpleDateFormat sdf=nw SimpleDateForm("yyyy年MM月dd日"); out.println(sdf.format(new Date())); }}//3.在.tld文件中描述标签<?xml version="1.0" encoding="UTF-8" ?><taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"><tlib-version>1.1</tlib-version><short-name>c</short-name><uri>http:www.intcast.com.cn/mytag1</uri><tag> <name>date</name> <tag-class>mytag.DateTag</tag-class> <body-content>empty</body-content></tag></taglib>//4.将taglib导入标签中(JSP)<%@taglib prefix="c" uri="http:www.intcast.com.cn/mytag1"%><c:date/>
4.自定义标签扩展
自定义标签除了编写JSP页面,还需要在页面中引入一些逻辑,例如:
*控制JSP页面某一部分内容的执行;
*控制整个JSP页面是否执行;
*控制JSP页面内容是否重复执行;
*修改JSP页面内容输出;
*移除JSP页面的java代码。
tld文件中四种标签体类型:
EMPTY、 JSP (有标签体的情形,在JSP2.0以前使用的)|| scriptless(JSP2.0以后使用的) tagdepentend
eg:1. jsp文件中:<body> <itcast:demo/>ccccc</body>//2 .tld文件中配置如下:<tag> <name>TagDemo</name> <tag-class>com.Cecilia.ResponsewebTest.TagDemo</tag-class> <body-content>JSP</body-content></tag><tag> <name>TagDemo1</name> <tag-class>com.Cecilia.ResponsewebTest.TagDemo1</tag-class> <body-content>JSP</body-content></tag>
新建标签处理类:TagDemo.java
public class TagDemo extends TagSupport{ int x=5; public void doStartTag() throws JSPException{ //1.使用标签控制页面内容是否输出 return Tag.Skip_BODY;//控制标签体不输出(Tag.EVAL_BODY_ZNCLUDE—显示标签内容显示出来) //3.控制标签体执行多次,即标签重复输出 return Tag.EVAL_BODY_INCLUDE;//然后继续执行doAfterBody()进行判断} public void doEndTag() throws JSPException{ //2.控制整个JSP是否输出(实际上控制doStartTag和doEndTag()方法的返回值) return Tag.EVAL_PAGE;//内容可输出 resturn Tag.SKIP_PAGE;//内容不可输出}//如果要想控制某个标签体多次执行,需要继承JSPTag的子接口IteratorTag,然后重写doAfterBody()方法,控制返回值类型即可。 public void doAfterBody() throws JSPException{ x--; if(x>0){ return IterationTag.EVAL_BODY_AGAIN; }else{return IterationTag.SKIP_BODY;}}}
4.修改标签操作
/*1.编写一个java标签处理类,并且继承BodyTagSupport类;2.重写doStartTag(),返回值为BodyTag.EVAL_BODY_BUFFERED;3.重写doEndTag(),在执行doEndTag()时调用getBodyEontent()方法得到标签体内容,并对标签体内容进行修改,最后再输出就OK。*/
public class TagDemo1 extends BodyTagSupport{ public void doStartTag() throws JSPException{ return BodyTag.EVAL_BODY_BUFFERED;} public void doEndTag() throws JSPException{ //得到标签内容 BodyContent bc=this.getBodyEontent(); String content=bc.getString(); content=content.toUpperCase();//将标签内容修改为大写 try{ this.pageContent.getOut().write(content);//输出修改后的内容}catch(Exception e){ throw new RuntimeException(e);//若出现运行时异常,将其抛给页面提示错误} return Tag.EVAL_PAGE;//返回显示页面}
注意:以上使用的Tag接口、IteratorionTag接口、BodyTag接口是在JSP2.0以前使用的,在JSP2.0以后只是用一个SImpleTagSupport接口就可以完成三个标签的所有功能,在这里或许有人疑问:那我们就没必要了解和学习这三个接口啦?其实,那还是有必要的,在我们接下来要学习的框架是采用以上三个接口搭建成的,所以学习这三个接口能够有利于我们在学习框架时自己看懂源码,更好地理解框架的原理。
5.SimpleTagSupport接口及操作方法
在了解以上三个接口后,接下来,让我们重点来学习JSP2.0之后具有强大功能的SimpleTagSupport接口。
*基本运行原理UML图
*基本的操作方法
eg://1.jsp文件中:<body> <sitcast:demo/>cccccc</body>//.tld文件配置如下:<tag> <name>SimpleTagdemo</name> <tag-class>com.Cecilia.ResponsewebTest.SimpleTagdemo</tag-class> <body-content>scriptless</body-content>//表示无脚本的jsp文件</tag>//新建标签处理类SimpleTagdemo.javapublic class SimpleTagdemo extends SimpleTagSupport{ //1.实用简单标签控制标签体是否执行 public void doTag(){ JspFragment jf=this.getTagBody();//获得标签体对象 //输出标签内容 jf.invoke(this.getJspContext().getOut()); //2.控制标签是否执行 for(int i=0;i<5;i++){ jf.invoke(null);//重复输出5次 } //如要控制剩余的不执行,那么添加 throw new JspPageException()就可以。 //3.修改标签体 StringWriter sw=new StringWriter();//获得输出流对象 jf.invoke(sw); String Content=sw.toString();//转化成字符串 content=content.toUpperCase();//修改转化成大写 this.getJspContext().getOut().write(content);//输出修改后的内容 }}
6.开发带属性的标签
eg://JSP文件<body> <sitcast:demo/>aaaa</body>//.tld文件中声明<tag> <name>SimpleTagdemo</name> <tag-class>com.Cecilia.ResponsewebTest.SimpleTagdemo</tag-class> <body-content>scriptless</body-content>//添加属性 <attribute> <name>count</name> <required>true</required> <rtexprvalue></rtexpravlue>(如果给false,那么只能是值,如果是true,那么除了值还可以接受一个运行时表达式<%= %>) </attribute>//新建一个标签处理类public class SimpleTagdemo extends SimpleTagSupport{ private int count;//设置标签属性 public void setCount(int count){ thi.count=count; } public void doTag()throws JspException{ //获得便签内容对象 JSPFragment jf=this.getJspBody(); //输出标签内容 for(int i=0;i<count;i++){ jf.invoke(null); } }}
7.如何实现使用标签控制页面逻辑
*如何实现开发防盗链的标签()?
eg:
//1.在JSP文件中body体
<!-- 开发防盗链的标签referer --> 您好!XXXXXXXXXXXX <a href="/ResponseWebTest/1.jsp">点我</a>
//2. .tld文件配置如下:
<tag> <name>referer</name> <tag-class>com.Cecilia.MyJSPTest.RefererTag</tag-class> <body-content>empty</body-content> <attribute> <name>site</name> <require>true</require> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>page</name> <require>true</require> <rtexprvalue>true</rtexprvalue> </attribute> </tag>
//3.创建标签处理类Referer.java
/** * 需求:开发防盗链的标签 * @author 芷若初荨 * */public class RefererTag extends SimpleTagSupport{ private String site;//定义网站站点 private String page;//定义页面路径 public void setSite(String site) { this.site = site; } public void setPage(String page) { this.page = page; } @Override public void doTag() throws JspException, IOException { // TODO Auto-generated method stub PageContext pc=(PageContext) this.getJspContext();//获取jsp页面内容 //获取当前页面资源的请求和响应对象 HttpServletRequest request=(HttpServletRequest)pc.getRequest(); HttpServletResponse response=(HttpServletResponse)pc.getResponse(); //1.得到来访问者的referer String referer=request.getHeader("referer"); if(referer==null||!referer.startsWith(site)){ if(page.startsWith(request.getContextPath())){ response.sendRedirect(page);//跳转 return; }else if(page.startsWith("/")){ response.sendRedirect(request.getContextPath()+page); }else{ response.sendRedirect(request.getContextPath()+"/"+page); } //如果都不匹配的话,那就抛出异常 throw new SkipPageException(); } else{ //如果不是盗链者,那么不做任何 } super.doTag(); }
*如何实现开发标签?
标签处理类如下:
/** * 需求:开发<c:if>标签 * @author 芷若初荨 * */public class IfElseTag extends SimpleTagSupport{ //开发<c:if>标签 private boolean test; public void setTest(boolean test){ this.test=test; } @Override public void doTag() throws JspException, IOException { // TODO Auto-generated method stub if(test){ this.getJspBody().invoke(null); } }
*如何实现开发标签?
开发这个标签需要设置三个标签处理器,分别是父标签Choose标签处理器和两个子标签When标签处理器和otherwise标签处理器,这三个需要配合使用,如下:
**父标签choose处理器
/** * 创建choose标签的处理器 * @author 芷若初荨 * */public class ChooseTag extends SimpleTagSupport{ private boolean isDo; public boolean isDo() { return isDo; } public void setDo(boolean isDo) { this.isDo = isDo; } @Override public void doTag() throws JspException, IOException { // TODO Auto-generated method stub this.getJspBody().invoke(null);//获得当前JSP页面body内容以及输出 }}
**when标签处理器
/** * 创建when标签的处理器 * @author 芷若初荨 * */public class WhenTag extends SimpleTagSupport{ private boolean test;//定义when的属性——判断条件 public void setTest(boolean test) { this.test = test; } @Override public void doTag() throws JspException, IOException { // TODO Auto-generated method stub ChooseTag parent=(ChooseTag) this.getParent();//得到父标签 //如果test等于true,并且父标签isDao等于false,那么 if(test&&!parent.isDo()){ this.getJspBody().invoke(null); }else{} }}
**otherwise标签处理器
/** * 开发otherwise标签,是when的兄弟标签 * @author 芷若初荨 * */public class OtherWiseTag extends SimpleTagSupport{ @Override public void doTag() throws JspException, IOException { // TODO Auto-generated method stub ChooseTag parent=(ChooseTag) this.getParent();//获得父标签 if(!parent.isDo()){ //如果父标签不执行 this.getJspBody().invoke(null);//获得标签体并输出 parent.setDo(true);//并且将其设置为true } }}
*如何开发迭代标签?(foreach)
实例://实现迭代的标签处理类public class Foreach extends SimpleTagSupport{ //对应标签元素var private String var; //对应的标签元素items private Object items; //使用Collection接口 private Collection<Object> collection; public void setVar(String var){ this.var=var; } public void setItems(Object items) { this.items=items; } /* 判断参数类型后赋值给collection对象 */ public void setCollection(Object items){ //如果是collection对象,在这里可以看做是子类对象中的set和List if(items instanceof Collection(Object items)){ this.collection=(Object)items; }//如果是一个Map对象 if(items instanceof Map){ Map map=new Map(); this.collection=map.entrySet();//将map的键值对赋值给当前的collection变量 }//如果是一个数组(不需要关注数组类型)//如果是数组,那么创建实例,以便做迭代处理 if(items.getClass().isArray()){ this.colletcion=new ArrayList(); //获取数组长度 int length=Array.getLength(items); //循环遍历数组元素,并添加到Collection对象中 for(int i=0;i<length;i++){ Object object=Array.get(items,i);//循环遍历数组 this.collection.add(object);//并将其添加到Collection对象中 } } }//覆盖doTag()方法,实现迭代public void doTag() throws JSPException{ //调用set方法,设置collection对象 this.setColletion(items); //获取Collection的迭代器 Iterator<Object> iterator=collection.iterator(); while(iterator.hasNext()){ Object value=iterator.next();/ //将对象添加到pageContext中,JSPContext是PageContext的超类getJspContext().setAttribute(var,value);//输出标签内容getJSPBody().invoke(null); }}}
//.tld文件描述标签
<?xml version="1.0" encoding="UTF-8"?> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>2.0</jsp-version> <short-name>mine</short-name> <uri>http://myTags.com/myTags</uri> <tag> <description>测试</description> <name>out</name> <tag-class>com.abc.FirstST</tag-class> <body-content>scriptless</body-content> <attribute> <name>test</name> <requird>true</requird> <rtexprvalue>true</rtexprvalue> </attribute> </tag><tag> <description>Foreach遍历输出</description> <name>foreach</name> <tag-class>com.abc.ForeachTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>var</name> <requird>true</requird> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>items</name> <requird>true</requird> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
在JSP中编写测试效果
<%@ taglib prefix="myTags" tagdir="/WEB-INF/tags"%> <%@ taglib prefix="mine" uri="/WEB-INF/tags/myTags.tld" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html> <head> <title>测试自定义标签</title> </head> <body> <% Integer num[] = {1,2,3}; request.setAttribute("num", num);%> <% Map map = new LinkedHashMap(); map.put("a", "aaa"); map.put("b","bbb"); map.put("c", "ccc"); request.setAttribute("map", map); %> <br>---------自定义标签mine:foreach迭代效果---------<br> <mine:foreach var="object" items="${num}"> ${object} </mine:foreach> <mine:foreach var="object" items="${map}"> ${object} </mine:foreach> <br>---------标准标签c:foreach迭代效果---------<br> <c:forEach var="object" items="${num}"> ${object} </c:forEach> <c:forEach var="object" items="${map}"> ${object} </c:forEach> </body> </html>
*如何实现HTML转义标签?(<)
标签处理类如下:
/** * 需求:开发HTML的转义标签 * @author 芷若初荨 * */public class HTMLFilterTag extends SimpleTagSupport{ @Override public void doTag() throws JspException, IOException { // TODO Auto-generated method stub //1.获得标签体 JspFragment jf=this.getJspBody(); //获得输入流 StringWriter writer=new StringWriter(); //输出 jf.invoke(writer); //获得a标签内容 String content=writer.getBuffer().toString(); content=filter(content);//调用转义方法 this.getJspContext().getOut().write(content); } public String filter(String message){ if(message==null){ return(null);//如果为空,返回空 } char content[]=new char[(message.length())]; message.getChars(0, message.length(), content,0); StringBuffer result=new StringBuffer(content.length+50); for(int i=0;i<content.length;i++){ switch(content[i]){ case '<': result.append("<"); break; default: break; } } return message; }}
*如何打包自己的标签库?
建一个Java工程—>复制需要打包的类—>新建一个META-IF目录,将.tld文件拷贝在其目录下—>右键点开Export,选择java目录下的.jar,选择需要打包的工程,并去掉配置文件就OK。
0 0
- 自定义标签库 循环标签
- JSTL标签库,自定义标签
- JSP 自定义标签库
- 自定义标签库
- 自定义jstl标签库
- Jsp 自定义标签库
- 自定义标签库
- 自定义标签库
- 自定义标签库开发
- 自定义标签库开发
- 自定义标签库开发
- 自定义标签库开发
- JSP自定义标签库
- 自定义标签库-demo
- 打包自定义标签库
- 自定义标签库
- JSP自定义标签库
- JSP自定义标签库
- Vue---路由跳转和嵌套
- Cesium-3D Tiles 跳跃式层级细节
- [bigdata-069]mysql数据迁移从自建导入到rds+代码过滤增量导入 centos6.8+pymsql+mysqldump+source
- python学习之路之六--input与while
- jQuery基础篇(一)样式篇
- 自定义标签库
- 2.结构型模式
- Linux下打包压缩war和解压war包
- Eclipse使用git命令行
- 织梦自定义表单验证字段不能为空,绝对实用灵活
- python实现获取天气信息后自动登录邮箱发送到指定邮件联系人
- 【SqlServer】 分享 几个 优化 Sql 的 语句
- Entity SQL 初入
- android新组件