web基础开发(六)

来源:互联网 发布:c语言格式控制符 编辑:程序博客网 时间:2024/05/19 22:25

今天将开始jsp自定义标签的学习!!

自定义标签

为什么要使用自定义标签,一般我们是不予许在一个jsp页面呢或者html中有过多的java代码,这样会影响后期维护的效力。

定义自定义标签

  • 先建立自己的标签类,在类中实现自己的java代码。
  • 在web-inf目录下,建立后缀名为tld的文件,在其中进行自定义标签的注册。

具体代码如下:

import javax.servlet.jsp.JspException;import javax.servlet.jsp.tagext.TagSupport;public class DateTag extends TagSupport{@Overridepublic int doStartTag() throws JspException {// TODO Auto-generated method stubSimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");try {pageContext.getOut().print(sdf.format(new Date()));//给个输出流} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return super.doStartTag();}}

需要注意的是:自定义的标签类要继承TagSupport,并且实现dostarttag方法,在其中实现自己的java代码。

<?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>c1</short-name>    <uri>/test-tag</uri>      <tag>        <name>date</name>                 <tag-class>com.example.tag.DateTag</tag-class>        <body-content>empty</body-content>    </tag> </taglib>

注意点:
  1. 创建tld,不会出现上面那些配置信息,在使用的时候,最好从其他地方就行复制。
  2. 在上述复制结束之后,需要进行一些配置的修改。<uri>必须是/开始,后面的信息,你自己随便定义,,在jsp使用的时候,填写的uri必须一致。<tag>标签下的是标签库的描述类,<tag-classs>是配置标签类的位置。<name>是配置标签使用的名称,方便jsp中的使用。

使用自定义标签

<%@ taglib prefix="tag" uri="/test-tag" %> <tag:date/>

prefix是标签的前缀,可以自定义。必须引入和tld一致的uri,才能使用标签。使用标签的时候要对应寻找在tld文件配置的tag的name。

 如何控制标签体内容的执行

还是正常写一个标签,在标签的dostarttag方法中,需要就行逻辑处理。

在配置的时候,<body-content>这个标签下,有4个属性值,其中empty表示这个标签下没有内容;scriptless表示这个标签体下可以有 文本,el 表达式,jsp动作;jsp表示这个标签体下,可以出现jsp的脚本,就是java代码; tagdependent表示 标签的内容写入body-content,由自定义的标签体类处理,而不被jsp容器去解析。

具体代码如下:

public int doStartTag() throws JspException {// TODO Auto-generated method stubString name = pageContext.getRequest().getParameter("name");//获取请求参数的值if(name!=null&&name.equals("laoqiang")){return EVAL_BODY_INCLUDE;//这个常量是执行标签体内容}else{return SKIP_BODY;//这个常量是跳过标签体内容

   <tag:ControlSkilTagContent>//携带内容的标签体   sdasdadddddddd   </tag:ControlSkilTagContent>

http://localhost:8080/TagTest/MyJsp.jsp?name=laoqiang//请求网址

该代码可以实现类似,不同的用户,展示不同部分的页面。

如何实现标签结束控制

主要用途:判断用户是否从超链接和表单提交到本站点。

主要实现方法:
@Overridepublic int doStartTag() throws JspException {// TODO Auto-generated method stubHttpServletRequest request = (HttpServletRequest) pageContext.getRequest();String refer = request.getHeader("referer");//通过获取请求头的,来判断用户是从哪个地方连接过来,只有超练接和浏览器表单提交才可以。String url = "http://"+request.getServerName(); //获取本站点的url。System.out.println(url+"ggggggggggggg");if(refer!=null&&refer.startsWith(url)){return EVAL_PAGE;}else{try {pageContext.getOut().print("不能访问");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return SKIP_PAGE;}}

注意在本标签使用的时候,为了阻止该页面的显示,标签一定要放在前面。

自定义标签属性

主要实现的方法就是通过在标签类中定义所需要的属性的set、get方法。在配置标签的时候,通过attribute进行配置。具体代码例子如下:

public class DbConnectionTag extends TagSupport {private String driver;private String passward;private String username;private String url;private String sql;public String getSql() {return sql;}public void setSql(String sql) {this.sql = sql;}public String getDriver() {return driver;}public void setDriver(String driver) {this.driver = driver;}public String getPassward() {return passward;}public void setPassward(String passward) {this.passward = passward;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}@Overridepublic int doEndTag() throws JspException { Connection conn = null; Statement stat = null; ResultSet res = null;// TODO Auto-generated method stub    try {Class.forName(this.driver);conn = DriverManager.getConnection(this.url, this.username, this.passward);stat = conn.createStatement();res = stat.executeQuery(this.sql);if(res!=null){while(res.next()){pageContext.getOut().println((res.getString("userNo")));}}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(res!=null){try {res.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(stat!=null){try {stat.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(conn!=null){try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}    return super.doEndTag();}}

标签配置

  <tag>        <name>DbConnectionTag</name>                 <tag-class>com.example.tag.DbConnectionTag</tag-class>        <body-content>empty</body-content>        <attribute>        <name>driver</name>        <required>true</required>        </attribute>        <attribute>        <name>passward</name>//属性的名称        <required>true</required>//属性是否必须显示使用         <rtexprvalue>true</rtexprvalue>//这个标签是属性值可以是表达式        </attribute>        <attribute>        <name>username</name>        <required>true</required>        </attribute>        <attribute>        <name>url</name>        <required>true</required>        </attribute>        <attribute>        <name>sql</name>        <required>true</required>        </attribute>    </tag>

自定义标签的遍历

主要是通过doAfterBody方法来实现的,下面不多说,直接上代码:
public class IterationTag extends TagSupport {private String[] array;private int i = 1;private String var;public String getVar() {return var;}public void setVar(String var) {this.var = var;}public String[] getArray() {return array;}public void setArray(String[] array) {this.array = array;}@Overridepublic int doStartTag() throws JspException {// TODO Auto-generated method stubif(array!=null&&array.length>0){pageContext.setAttribute(this.var, array[0]);return EVAL_BODY_INCLUDE;}else{return SKIP_BODY;}}@Overridepublic int doAfterBody() throws JspException {// TODO Auto-generated method stubif(i<array.length){pageContext.setAttribute(this.var,array[i]);i++;return EVAL_BODY_AGAIN;}else{return SKIP_BODY;}}}

利用这种标签遍历,会受到tomcat的缓存影响,第一次遍历出来,刷新后只有第0个位置元素。

修改标签体的内容

主要是通过定义标签处理类来继承BodyTagSupport,通过bodycontennt来获取标签体的内容。
public class ModifyBodyTag extends BodyTagSupport{private BodyContent bodyContent;@Overridepublic int doEndTag() throws JspException {// TODO Auto-generated method stubString  s =  bodyContent.getString();//获取标签体的内容String newcontent  ="我是修改后的内容";JspWriter js = bodyContent.gtEnclosingWriter();//获取输出流try {js.write(newcontent);//将修改后的内容输出到jsp} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return EVAL_PAGE;}@Overridepublic void setBodyContent(BodyContent b) {// TODO Auto-generated method stubsuper.setBodyContent(b);bodyContent = b;}}

重点啦!!!

通过上面的代码,我们已经初步对自定义标签有所了解,但是上述的自定义标签方法,在使用的时候还是不是太方面,所以引入simpletag、simpletagsupport,但是在实际开发中,我们还是主要使用标签库2.0的simpletagsupport。下面介绍simpletagsupport的方法:
  1. dotag 是核心方法,处理标签逻辑。
  2. setparent 将父标签处理器对象传递给标签处理器。
  3. getparent 获取当前标签的父标签。
  4. setjspcontext 方法将jsp页面的pagecontext对象传递给标签处理器对象。
  5. setjspbody 将代表当前标签体的jspfragment对象给标签处理器对象。
  6. getjspcontext 返回jsp页面pagecontext。
  7. getjspbody 返回标签体的内容。
使用2.0标签,在配置的时候 :

 <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"> </taglib>

tld文件的版本必须是2.0。

将之前几个例子通过simpletagsupport实现,代码如下:


@Overridepublic void doTag() throws JspException, IOException {// TODO Auto-generated method stubsuper.doTag();// TODO Auto-generated method stubSimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");JspWriter js = getJspContext().getOut();//通过获取jsp的上下文,然后拿到输出流js.write(sdf.format(new Date()));//将内容写入到jsp。}

public class ControlSkilTagContent extends SimpleTagSupport {@Overridepublic void doTag() throws JspException, IOException {// TODO Auto-generated method stubsuper.doTag();PageContext pageContext = (PageContext) getJspContext();//获取pagecontextString name = pageContext.getRequest().getParameter("name");if(name!=null&&name.equals("liujinxin")){getJspBody().invoke(null);//getJspBody()得到Jspfragment,将内容作为标签体内容显示出来}}

public void doTag() throws JspException, IOException {// TODO Auto-generated method stubsuper.doTag();PageContext pageContext = (PageContext) getJspContext();HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();String refer = request.getHeader("referer");//判断请求是否是从超链接if(refer==null){throw new SkipPageException();//跳过jsp页面,不显示。}}

private String[] array;private String var;public String getVar() {return var;}public void setVar(String var) {this.var = var;}public String[] getArray() {return array;}public void setArray(String[] array) {this.array = array;}@Overridepublic void doTag() throws JspException, IOException {// TODO Auto-generated method stubsuper.doTag();PageContext pageContext = (PageContext) getJspContext();if(array!=null&&array.length>0){pageContext.setAttribute(this.var, array[0]);getJspBody().invoke(null);//将遍历出来的内容,作为标签体的内容输出出来。}}

@Overridepublic void doTag() throws JspException, IOException {// TODO Auto-generated method stubsuper.doTag();StringWriter sw = new StringWriter();//构建一个缓冲区.JspFragment jf = getJspBody();//获取标签体的内容jf.invoke(sw);//将标签体写到缓冲区中String content = sw.toString();//从缓冲区得到内容getJspContext().getOut().write(content);//将内容写到jsp页面上}

复合标签组合

  <tag:choose>    <tag:when grade="$(grade)==100">    very good     </tag:when>    <tag:otherwise>    加油吧,骚年!!!!!!!    </tag:otherwise>    </tag:choose>

主要代码如下

private boolean grade;public boolean isGrade() {return grade;}public void setGrade(boolean grade) {this.grade = grade;}@Overridepublic void doTag() throws JspException, IOException {// TODO Auto-generated method stubsuper.doTag();if(grade){getJspBody().invoke(null);ChooseTag ct  = (ChooseTag)getParent();//获取该标签的父类标签ct.setFlag(true);//设置标志位}}

小伙伴们,jsp自定义标签已经学习完毕啦!