JavaWeb-12 (自定义标签库开发&JSTL标签库)

JavaWeb-12:自定义标签库开发&JSTL标签库

自定义标签库开发

一、自定义标签简介

自定义标签主要用于移除Jsp页面中的java代码。

使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤:

1、编写一个实现Tag接口的Java类(标签处理器类)。
2、编写标签库描述符(tld)文件,在tld文件中把标

实验:项目架构如下:

a.tld

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
  "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
    <tlib-version>1.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>myjstl</short-name>
    <uri>http://java.sun.com/jstl/myjstl</uri>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>showTime</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.taglib.ShowTime</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>empty</body-content>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>demo1</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.taglib.Demo1</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>tagdependent</body-content>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>demo2</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.taglib.Demo2</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>tagdependent</body-content>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>demo3</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.taglib.Demo3</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>tagdependent</body-content>
        <attribute>
            <!-- 属性的名字  -->
            <name>count</name>
            <required>true</required>
            <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>demo4</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.taglib.Demo4</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>scriptless</body-content>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>if</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.mytaglib.IfTag</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>scriptless</body-content>
        <attribute>
            <!-- 属性的名字  -->
            <name>test</name>
            <required>true</required>
            <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>choose</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.mytaglib.ChooseTag</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>scriptless</body-content>

    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>when</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.mytaglib.WhenTag</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>scriptless</body-content>
        <attribute>
            <!-- 属性的名字  -->
            <name>test</name>
            <required>true</required>
            <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>otherwise</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.mytaglib.OtherwiseTag</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>scriptless</body-content>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>foreach</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.mytaglib.SimpleForEachTag</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>scriptless</body-content>
        <attribute>
            <!-- 属性的名字  -->
            <name>items</name>
            <required>true</required>
            <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <!-- 属性的名字  -->
            <name>var</name>
            <required>true</required>
            <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 -->
            <rtexprvalue>false</rtexprvalue>
        </attribute>
    </tag>

    <tag>
        <!-- name是自定义标签的名字 -->
        <name>foreach1</name>
        <!--自定义标签相关联的类名-->
        <tag-class>com.heima.mytaglib.ComplexForEachTag</tag-class>
        <!-- body-content是用来描述主体内容的类型 -->
        <body-content>scriptless</body-content>
        <attribute>
            <!-- 属性的名字  -->
            <name>items</name>
            <required>true</required>
            <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        <attribute>
            <!-- 属性的名字  -->
            <name>var</name>
            <required>true</required>
            <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 -->
            <rtexprvalue>false</rtexprvalue>
        </attribute>
    </tag>
</taglib>

实验1:showTime.jsp/ShowTime.java

ShowTime.java

package com.heima.taglib;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//显示当前的时间
public class ShowTime extends SimpleTagSupport{

    public void doTag() throws JspException, IOException {
        //拿到当前的时间
        Date d = new Date() ;
        //格式化时间
        String time = d.toLocaleString() ;
        //拿到输出流对象
        PageContext pageContext = (PageContext)getJspContext() ;
        pageContext.getOut().write(time) ;
    }
}

showTime.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘1.jsp‘ starting page</title>

    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->

  </head>

  <body>
        <my:showTime />
  </body>
</html>

在浏览器输入:http://localhost:8080/day1200taglib/showTime.jsp,结果输入页面如下:

分析自定义标签的执行流程。

二、Tag接口的执行流程

JSP引擎将遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法。

1、public void setPageContext(PageContext?pc), JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信。

2、public void setParent(Tag?t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null。

3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法。

4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法。

5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web应用时,web容器才会调用release方法。

三、自定义标签功能扩展

1、自定义标签除了可以移除jsp页面java代码外,它也可以实现以下功能。

开发人员在编写Jsp页面时,经常还需要在页面中引入一些逻辑,例如:
1、控制jsp页面某一部分内容是否执行。
2、控制结束标签后的JSP内容是否执行
3、控制jsp页面内容重复执行。
4、修改页面内容输出。

2、tld文件中的四种标签体类型

EMPTY、JSP、scriptless、tagdependent

介绍tld头里标签的含义
<tag>
</tag>
tag标签里包括:

    <name>//name是自定义标签的名字

    <tag-class>//自定义标签相关联的类名,路径全称包括文件

    <body-content>//是用来描述主体内容的类型,即在页面上写上自定义标签时,包括在中间所会出现的内容。我们一般<body-content>empty</body-content>

四、简单标签

由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广, SUN公司为降低标签技术的学习难度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口来实现标签的功能。实现SimpleTag接口的标签通常称为简单标签。简单标签共定义了5个方法:

setJspContext方法:用于把JSP页面的pageContext对象传递给标签处理器对象 

setParent方法:用于把父标签处理器对象传递给当前标签处理器对象 

getParent方法:用于获得当前标签的父标签处理器对象 

setJspBody方法:用于把代表标签体的JspFragment对象传递给标签处理器对象 

doTag方法:用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容等。在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。

五、SimpleTag接口方法的执行顺序

当web容器开始执行标签时,会调用如下方法完成标签的初始化:

1、WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。

2、WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。

3、如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。

4、如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。

执行标签时:

容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。

六、JspFragment类(关键!!)

javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段,这段JSP片段中不能包含JSP脚本元素。

WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象。JspFragment类中只定义了两个方法,如下所示:

getJspContext方法:用于返回代表调用页面的JspContext对象.

public abstract void invoke(java.io.Writer?out) 

    用于执行JspFragment对象所代表的JSP代码片段,参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)

七、invoke方法详解

JspFragment.invoke方法是JspFragment最重要的方法,利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出。例如:

a. 在标签处理器中如果没有调用JspFragment.invoke方法,其结果就相当于忽略标签体内容;

b. 在标签处理器中重复调用JspFragment.invoke方法,则标签体内容将会被重复执行;

c. 若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。

实验:Demo1.java+1.jsp+servlet源码

Demo1.java

package com.heima.taglib;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//控制主体内容不显示
public class Demo1 extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        return ;
    }
}

1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
   <!-- 控制部分内容不显示 -->
      我<my:demo1>喜欢芙蓉姐姐</my:demo1><br>

  </body>
</html>

servlet源码1jsp.java如下:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class _1_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  static {
    _jspx_dependants = new java.util.ArrayList(1);
    _jspx_dependants.add("/WEB-INF/a.tld");
  }

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;

    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <base href=\"");
      out.print(basePath);
      out.write("\">\r\n");
      out.write("    \r\n");
      out.write("    <title>My JSP ‘index.jsp‘ starting page</title>\r\n");
      out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"expires\" content=\"0\">    \r\n");
      out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
      out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
      out.write("\t<!--\r\n");
      out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
      out.write("\t-->\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("   <!-- 控制部分内容不显示 -->\r\n");
      out.write("      我");
      if (_jspx_meth_my_005fdemo1_005f0(_jspx_page_context))
        return;
      out.write("<br>\r\n");
      out.write("\r\n");
      out.write("      \r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else log(t.getMessage(), t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }

  private boolean _jspx_meth_my_005fdemo1_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  my:demo1
    com.heima.taglib.Demo1 _jspx_th_my_005fdemo1_005f0 = new com.heima.taglib.Demo1();
    org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_my_005fdemo1_005f0);
    _jspx_th_my_005fdemo1_005f0.setJspContext(_jspx_page_context);
    _jspx_th_my_005fdemo1_005f0.setJspBody(new Helper( 0, _jspx_page_context, _jspx_th_my_005fdemo1_005f0, null));
    _jspx_th_my_005fdemo1_005f0.doTag();
    org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_my_005fdemo1_005f0);
    return false;
  }

  private class Helper
      extends org.apache.jasper.runtime.JspFragmentHelper
  {
    private javax.servlet.jsp.tagext.JspTag _jspx_parent;
    private int[] _jspx_push_body_count;

    public Helper( int discriminator, JspContext jspContext, javax.servlet.jsp.tagext.JspTag _jspx_parent, int[] _jspx_push_body_count ) {
      super( discriminator, jspContext, _jspx_parent );
      this._jspx_parent = _jspx_parent;
      this._jspx_push_body_count = _jspx_push_body_count;
    }
    public boolean invoke0( JspWriter out )
      throws Throwable
    {
      out.write("喜欢芙蓉姐姐");
      return false;
    }
    public void invoke( java.io.Writer writer )
      throws JspException
    {
      JspWriter out = null;
      if( writer != null ) {
        out = this.jspContext.pushBody(writer);
      } else {
        out = this.jspContext.getOut();
      }
      try {
        this.jspContext.getELContext().putContext(JspContext.class,this.jspContext);
        switch( this.discriminator ) {
          case 0:
            invoke0( out );
            break;
        }
      }
      catch( Throwable e ) {
        if (e instanceof SkipPageException)
            throw (SkipPageException) e;
        throw new JspException( e );
      }
      finally {
        if( writer != null ) {
          this.jspContext.popBody();
        }
      }
    }
  }
}

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/1.jsp,输出如下页面

发现实验中servlet的源码也没显示出被自定义标签所隐藏了的数据!

实验:控制内容不输出方法2:Demo2.java+2.jsp

Demo2.java

package com.heima.taglib;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//控制结束标签后的内容不执行
public class Demo2 extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        //主体是要输出的
        JspFragment body = getJspBody() ;
        //第一种方式
//      //拿到out对象
//      JspWriter out = ((PageContext)getJspContext()).getOut() ;
//      //输出主体内容
//      body.invoke(out) ;

        //第二种方式
        body.invoke(null) ;

        //抛出异常
        throw new SkipPageException() ;
    }
}

2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
      我<my:demo2>喜欢</my:demo2>芙蓉姐姐

  </body>
</html>

servlet源码2jsp.java如下:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class _2_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  static {
    _jspx_dependants = new java.util.ArrayList(1);
    _jspx_dependants.add("/WEB-INF/a.tld");
  }

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;

    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <base href=\"");
      out.print(basePath);
      out.write("\">\r\n");
      out.write("    \r\n");
      out.write("    <title>My JSP ‘index.jsp‘ starting page</title>\r\n");
      out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"expires\" content=\"0\">    \r\n");
      out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
      out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
      out.write("\t<!--\r\n");
      out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
      out.write("\t-->\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("      我");
      if (_jspx_meth_my_005fdemo2_005f0(_jspx_page_context))
        return;
      out.write("芙蓉姐姐\r\n");
      out.write("      \r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else log(t.getMessage(), t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }

  private boolean _jspx_meth_my_005fdemo2_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  my:demo2
    com.heima.taglib.Demo2 _jspx_th_my_005fdemo2_005f0 = new com.heima.taglib.Demo2();
    org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_my_005fdemo2_005f0);
    _jspx_th_my_005fdemo2_005f0.setJspContext(_jspx_page_context);
    _jspx_th_my_005fdemo2_005f0.setJspBody(new Helper( 0, _jspx_page_context, _jspx_th_my_005fdemo2_005f0, null));
    _jspx_th_my_005fdemo2_005f0.doTag();
    org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_my_005fdemo2_005f0);
    return false;
  }

  private class Helper
      extends org.apache.jasper.runtime.JspFragmentHelper
  {
    private javax.servlet.jsp.tagext.JspTag _jspx_parent;
    private int[] _jspx_push_body_count;

    public Helper( int discriminator, JspContext jspContext, javax.servlet.jsp.tagext.JspTag _jspx_parent, int[] _jspx_push_body_count ) {
      super( discriminator, jspContext, _jspx_parent );
      this._jspx_parent = _jspx_parent;
      this._jspx_push_body_count = _jspx_push_body_count;
    }
    public boolean invoke0( JspWriter out )
      throws Throwable
    {
      out.write(‘喜‘);
      out.write(‘欢‘);
      return false;
    }
    public void invoke( java.io.Writer writer )
      throws JspException
    {
      JspWriter out = null;
      if( writer != null ) {
        out = this.jspContext.pushBody(writer);
      } else {
        out = this.jspContext.getOut();
      }
      try {
        this.jspContext.getELContext().putContext(JspContext.class,this.jspContext);
        switch( this.discriminator ) {
          case 0:
            invoke0( out );
            break;
        }
      }
      catch( Throwable e ) {
        if (e instanceof SkipPageException)
            throw (SkipPageException) e;
        throw new JspException( e );
      }
      finally {
        if( writer != null ) {
          this.jspContext.popBody();
        }
      }
    }
  }
}

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/2.jsp,输出如下页面

记住该例子,关于jstl怎么输出的问题!

八、开发带属性的标签

自定义标签可以定义一个或多个属性,这样,在JSP页面中应用自定义标签时就可以设置这些属性的值,通过这些属性为标签处理器传递参数信息,从而提高标签的灵活性和复用性。

要想让一个自定义标签具有属性,通常需要完成两个任务:

1、在标签处理器中编写每个属性对应的setter方法

2、在TLD文件中描术标签的属性

为自定义标签定义属性时,每个属性都必须按照JavaBean的属性命名方式,在标签处理器中定义属性名对应的setter方法,用来接收JSP页面调用自定义标签时传递进来的属性值。 例如属性url,在标签处理器类中就要定义相应的setUrl(String url)方法。

在标签处理器中定义相应的set方法后,JSP引擎在解析执行开始标签前,也就是调用doStartTag方法前,会调用set属性方法,为标签设置属性。

实验:Demo3.java+3.jsp

Demo3.java

package com.heima.taglib;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//控制主体内容重复执行
public class Demo3 extends SimpleTagSupport {

    private String count ;

    //将由服务器调用
    public void setCount(String count) {
        this.count = count;
    }

    @Override
    public void doTag() throws JspException, IOException {
        //将count转换为整形
        int length = Integer.parseInt(count) ;
        for (int i = 0; i < length; i++) {
            getJspBody().invoke(null) ;
        }
    }
}

3.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
   <!-- 控制主体内容重复执行 -->
      <my:demo3 count = "5">
            <hr>
      </my:demo3>

  </body>
</html>

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/3.jsp,输出如下页面

实验:Demo4.java+4.jsp

Demo4.java

package com.heima.taglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//改变主体内容后输出
public class Demo4 extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        //获取主体内容
        JspFragment body = getJspBody() ;
        //创建一个StringWriter(可以从缓冲区中拿取)
        StringWriter sw = new StringWriter() ;
        //将数据写入sw
        body.invoke(sw) ;
        //从sw里面拿出数据
        String s = sw.toString() ;
        //将数据变成大写后输出
        getJspContext().getOut().write(s.toUpperCase()) ;
    }
}

4.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
   <!-- 改变主体内容后输出 -->
      <my:demo4>abcde</my:demo4>

  </body>
</html>

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/4.jsp,输出如下页面

九、在TLD文件中描述标签属性

tag标签子元素的attribute标签子元素用于描述自定义标签的一个属性,自定义标签所具有的每个属性都要对应一个attribute标签元素 。

<attribute>
    <description>description</description>
    <name>aaaa</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    <type>ObjectType</type>
</attribute>

案例,使用标签控制页面逻辑案例:

  • 开发<c:if>标签

实验:5.jsp+IfTag.java

IfTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if功能
public class IfTag extends SimpleTagSupport {

    private boolean test ;

    public void setTest(boolean test) {
        this.test = test;
    }

    @Override
    public void doTag() throws JspException, IOException {
        if(test)
            //执行主体内容
            getJspBody().invoke(null) ;
    }
}

5.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
   <!-- 实现if功能 -->
      <my:if test = "${10>5 }">
            ${"abc"}
      </my:if>

  </body>
</html>

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/5.jsp,输出如下页面

  • 开发<c:when><c:otherwise>标签

实验:chooseTag.java+WhenTag.java+OtherwiseTag.java+6.jsp

ChooseTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if..else功能
public class ChooseTag extends SimpleTagSupport {

    private boolean flag = true ;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void doTag() throws JspException, IOException {
        getJspBody().invoke(null) ;
    }
}

WhenTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if..else功能
public class WhenTag extends SimpleTagSupport {

    private boolean test ;

    public void setTest(boolean test) {
        this.test = test;
    }

    @Override
    public void doTag() throws JspException, IOException {
        if(test){
            getJspBody().invoke(null) ;
            //设置父标签中的变量flag设置为false
            //拿到父标签
            ChooseTag choose = (ChooseTag)getParent() ;
            choose.setFlag(false) ;
        }
    }
}

OtherwiseTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if..else功能
public class OtherwiseTag extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        //拿到父标签的flag属性,根据flag属性的值决定是否执行主体内容
        //拿到父标签
        ChooseTag choose = (ChooseTag)getParent() ;
        if(choose.isFlag())
            getJspBody().invoke(null) ;
    }
}

6.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
   <!-- 实现if功能 -->
       <my:choose>
             <my:when test = "${10<5 }">
                   abc
              </my:when>
              <my:otherwise>
                   123
            </my:otherwise>
       </my:choose>

  </body>
</html>

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/6.jsp,输出如下页面

注意:在WhenTag.java里ChooseTag choose = (ChooseTag)getParent() ;原因是该servlet继承了SimpleTagSupport类(不是接口),而该接口里有方法getParent(),返回的是JspTag类型,而JspTag是一个接口,而且查文档知道该接口被SimpleTagSupport类实现了,而ChooseTag也实现了SimpleTagSupport类,所以有以上代码,意思就是把符标签的类获取到并使用类中的方法,在该例子中ChooseTag充当了一个公共类的角色。

  • 开发迭代标签:实现简单循环功能/实现复杂循环功能

实验:实现简单循环功能插入,7.jsp+SimpleForEachTag.java,该例子有其传入对象类型的局限性

SimpleForEachTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现简单循环功能
public class SimpleForEachTag extends SimpleTagSupport {

    private ArrayList items ;

    private String var ;

    public void setVar(String var) {
        this.var = var;
    }

    public void setItems(ArrayList items) {
        this.items = items;
    }

    @Override
    public void doTag() throws JspException, IOException {
        int length = items.size() ;

        for (int i = 0; i < length; i++) {
            Object obj = items.get(i) ;
            //将此值存入一个域对象中
            ServletRequest request = ((PageContext)getJspContext()).getRequest() ;
            //想数据放入reqeust
            request.setAttribute(var, obj) ;

            //执行主体内容
            getJspBody().invoke(null) ;
        }
    }
}

7.jsp

<%@ page language="java" import="java.util.*,com.heima.mytaglib.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
   <!-- 实现循环功能 -->
        <%
            List<User> list = new ArrayList<User>() ;
            list.add(new User("1","张无忌",20)) ;
            list.add(new User("2","乔峰",25)) ;
            list.add(new User("3","郭靖",30)) ;

            //list.add("aaaaaaa") ;
            //list.add("bbbbbbbbb") ;
            //list.add("cccccccccc") ;
            //list.add("dddddddddddd") ;

            request.setAttribute("list", list) ;//该句为了让下面的el表达式利用导航原理获取list的对象
             %>
       <my:foreach items = "${list}" var = "t"><!--然后获取到了对象之后再传到foreach的属性里 -->
            ${t.username} : ${t.age}<br>
       </my:foreach>

  </body>
</html>

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/7.jsp,输出如下页面

实验:实现复杂循环功能:8.jsp+ComplexForEachTag.java+User.java,难点!!要记住

User.java

package com.heima.mytaglib;

public class User {

    private String id ;

    private String username ;

    private int age ;

    public User() {
    }

    public User(String id, String username, int age) {
        super();
        this.id = id;
        this.username = username;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

ComplexForEachTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现简单循环功能
public class ComplexForEachTag extends SimpleTagSupport {

    private Object items ;

    private String var ;

    public void setVar(String var) {
        this.var = var;
    }

    public void setItems(Object items) {
        this.items = items;
    }

    @Override
    public void doTag() throws JspException, IOException {
        //定义一个集合(目的是将items中的数据放入coll中)
        Collection coll = null ;
        //判断items的具体类型,做相应操作
        if(items == null)
            return ;
        if(items instanceof List)
            coll = (List)items ;
        else if(items instanceof Map)
            coll = ((Map)items).entrySet() ;
        else if(items.getClass().isArray()){
            coll = new ArrayList() ;
            //将数组中的数据拷贝到coll中
            for (int i = 0; i < Array.getLength(items); i++) {
                coll.add(Array.get(items, i)) ;
            }
        }else{
            throw new RuntimeException("不支持的数据类型") ;
        }

        //拿到pageContext对象
        PageContext pc = (PageContext)getJspContext() ;
        for (Object object : coll) {
            pc.setAttribute(var, object) ;
            //执行主体内容
            getJspBody().invoke(null) ;
        }
    }
}

8.jsp

<%@ page language="java" import="java.util.*,com.heima.mytaglib.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
   <!-- 实现循环功能 -->
        <%
            List<User> list = new ArrayList<User>() ;
            list.add(new User("1","张无忌",20)) ;
            list.add(new User("2","乔峰",25)) ;
            list.add(new User("3","郭靖",30)) ;

            //list.add("aaaaaaa") ;
            //list.add("bbbbbbbbb") ;
            //list.add("cccccccccc") ;
            //list.add("dddddddddddd") ;

            request.setAttribute("list", list) ;

            Map<String,User> map = new HashMap<String,User>() ;
            map.put("a", new User("1","张无忌",20)) ;
            map.put("b", new User("2","乔峰",25)) ;
            map.put("c", new User("3","郭靖",30)) ;

            request.setAttribute("map", map) ;

            String[] s = {"aaaaaaaa","bbbbbbbbbb","ccccccccc"} ;

            request.setAttribute("s", s) ;

            Set<String> set = new HashSet<String>() ;
            set.add("aaaaaaaa") ;
            set.add("bbbbbbb") ;
            set.add("cccccccccc") ;

            request.setAttribute("set", set) ;
             %>
       <my:foreach1 items = "${map}" var = "t"><!--更改el表达式里的集合名,切换来实验! -->>
            ${t.key} : ${t.value.username}<br>
       </my:foreach1>

  </body>
</html>

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/8.jsp,输出如下页面

JSTL标签库

一、JSTL标签库:

1、核心标签库 c:if c:forEach

2、国际化标签 国际化相关类和原理

3、数据库标签

4、XML标签

5、JSTL函数(EL函数);

实验:1.jsp

架构:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/core_rt" prefix = "c" %>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
       <!-- 输出数据 -->
       <c:out value="<font color = red>abcd</font>" default="张三"  escapeXml="true"></c:out><br>
       <!-- 条件语句 -->
       <%
        List<String> list = new ArrayList<String>() ;

        list.add("aaaaaaa") ;
        list.add("bbbbbbbbb") ;
        list.add("cccccccccc") ;
        list.add("dddddddddddd") ;
        list.add("eeeeeeeeeee") ;

        request.setAttribute("list", list) ;
        %>
       <c:if test="${not empty list}">
            <c:out value="不为空"></c:out>
       </c:if>
       <br>
       <c:choose>
            <c:when test="${ not empty list}">
                <c:out value="不为空"></c:out>
            </c:when>
            <c:otherwise>
                <c:out value="为空"></c:out>
            </c:otherwise>
       </c:choose>
       <br>
       <c:forEach items="${list }" var="p" begin="1" end="3" step="2" varStatus="t">
            ${p }:${t.index }:${t.count}<br>
       </c:forEach>
       <hr>
       <!-- 定义变量 -->
       <c:set var="name" value="张三丰" scope="session" />
       ${name }
       <!-- 请求重定向 -->
       <%--<c:redirect url="2.jsp"></c:redirect>--%>
       <hr>
       <!-- 拆分字符串,循环 -->
       <c:forTokens items="a,b,c,d,e" delims="," var="p">
            ${p }<br>
       </c:forTokens>

  </body>
</html>

在浏览器输入http://localhost:8080/day1201jstl/1.jsp,输出如下页面:

实验:2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/core_rt" prefix = "c" %>
<%@ taglib uri = "http://java.sun.com/jstl/fmt_rt" prefix = "fmt" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>">

    <title>My JSP ‘index.jsp‘ starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css">
    -->
  </head>

  <body>
       ${name }
       <%
            Date d = new Date() ;
            request.setAttribute("d", d) ;
       %>
       <fmt:formatDate value="${d}" dateStyle="long"/><br>
       <fmt:formatNumber value="12345.12" pattern="###,###.##" />
  </body>
</html>

在浏览器输入http://localhost:8080/day1201jstl/2.jsp,输出如下页面:

资源下载

时间: 2024-10-15 02:29:16

JavaWeb-12 (自定义标签库开发&JSTL标签库)的相关文章

javaweb学习总结(二十八)——JSTL标签库之核心标签【转】

原文地址:javaweb学习总结(二十八)——JSTL标签库之核心标签 一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心标签(用得最多) 国际化标签(I18N格式化标签) 数据库标签(SQL标签,很少使用) XML标签(几乎不用) JSTL函数(EL函数) 三.核心标签库使用说明 JSTL的核心标签库标签共13个,使用这些标签能够完成JSP页面的

标签案例-开发foreach标签

1 if(item.getClass().isArray()){ 2 this.collection = new ArrayList(); 3 int length = Array.getLength(items); 4 for(int i=0;i<length;i++){ 5 Object value = Array.get(items,i); 6 this.collection.add(value); 7 } 8 } 接收任何类型集合或数组的代码 标签案例-开发foreach标签,布布扣,b

javaweb学习总结(二十八)——JSTL标签库之核心标签

一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心标签(用得最多) 国际化标签(I18N格式化标签) 数据库标签(SQL标签,很少使用) XML标签(几乎不用) JSTL函数(EL函数) 三.核心标签库使用说明 JSTL的核心标签库标签共13个,使用这些标签能够完成JSP页面的基本功能,减少编码工作. 从功能上可以分为4类:表达式控制标签.流程控制

javaWeb学习总结(9)- JSTL标签库之核心标签

一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心标签(用得最多) 国际化标签(I18N格式化标签) 数据库标签(SQL标签,很少使用) XML标签(几乎不用) JSTL函数(EL函数) 三.核心标签库使用说明 JSTL的核心标签库标签共13个,使用这些标签能够完成JSP页面的基本功能,减少编码工作. 从功能上可以分为4类:表达式控制标签.流程控制

java基础开发—jstl标签库

在DRP项目中.接触到了JSTL标签库. 在未使用Jstl之前,我们使用JSP脚本实现一些声明或是表达式任务,做一些业务相关操作时,须要在页面中嵌入大量的java代码.在DRP项目开发前期.使用jsp页面给我的感受就是.jsp页面什么活都能干,权利过高.导致的结果就是,jsp页面提高了程序的复杂性.增强了代码维护的复杂度.以及代码阅读的困难.对程序猿的要求也相对较高.比如,虽然精通页面设计的开发者来维护jsp.也经常须要依赖于经验丰富的程序猿.所以须要一种技术来解决这些问题,以下简介一下jstl

JSP标签语法、JSTL标签库、EL表达式辨析

<一.JSP > JSP 语法语法格式: <% 代码片段 %>或者<jsp:scriptlet> 代码片段</jsp:scriptlet> JSP声明 <%! declaration; [ declaration; ]+ ... %><%! int i = 0; %> <%! int a, b, c; %> <%! Circle a = new Circle(2.0); %> 或者<jsp:declara

JSTL标签库(转)

原文地址:http://www.blogjava.net/maverick1003/articles/236575.html JSTL标签库 JSTL标签库的使用是为类弥补html表的不足,规范自定义标签的使用而诞生的.在告别modle1模式开发应用程序后,人们开始注重软件的分层设计,不希望在jsp页面中出现java逻辑代码,同时也由于自定义标签的开发难度较大和不利于技术标准化产生了自定义标签库. JSTL标签库可分为5类: 1      核心标签库 2        I18N格式化标签库 3 

18、EL表达式、JSP标签、JSTL标签、自定义标签

EL表达式 jsp的核心语法: jsp表达式 <%=%>和 jsp脚本<% %>. 以后开发jsp的原则: 尽量在jsp页面中少写甚至不写java代码. 使用EL表达式替换掉jsp表达式 EL表达式作用: 向浏览器输出域对象中的变量值或表达式计算的结果!!! 语法: ${变量或表达式} EL语法 1 输出基本数据类型变量 从四个域获取 ${name} 指定域获取 ${pageScope.name} 域范围: pageScoep / requestScope / sessionSco

JSP 标准标签库(JSTL)

JSP 标准标签库(JSTL) JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签. 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签. 根据JSTL标签所提供的功能,可以将其分为5个类别. 核心标签 格式化标签 SQL 标签 XML 标签 JSTL 函数 JSTL 库安装 Apache Tomcat安装JSTL 库步骤如下: 从Apache的标准标签库中下载