一、实现遍历 List 集合、可以与自带的JSTL的forEach循环实现双(多)重循环
1.编写 JAVA 类
  import javax.servlet.jsp.tagext.SimpleTagSupport; // 要导入的 包
  import javax.servlet.jsp.JspException;
  //1.定义JAVA类、实现 SimpleTagSupport 接口
  public class ForEachList extends SimpleTagSupport {
    //2.定义属性、并给出 gette 、setter 方法
    private Object items; // 用于接收输入的值
    private String var; // 用户输出的值
     //3.重写 doTag() 方法
    public void doTag() throws JspException, IOException{
      //4.编写逻辑控制语句
      // 判断是不是 List 集合
      if(items instanceof List){
        // 强转为 list 集合
        List list = (List)items;
        // 使用 foreach 循环遍历
        for (Object obj : list) {
          //输出内容
          getJspContext().setAttribute(var, obj);
          //输出标签体
          getJspBody().invoke(null);
        }
      }else{
        throw new JspException("只能遍历 List 集合!");
      }
    }
  }
2.编写 *.tld 文件(在 WEB-INF 下创建)
  <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">
  <description>this is my tag library Definition</description>
  <tlib-version>1.0</tlib-version>
  <short-name>mytaglib</short-name>
  <!-- 用于指定在调用时的 uri -->
  <uri>http://127.0.0.0/servlet/mytaglib</uri>
    <!-- 创建标签 -->
    <tag>
      <!-- 标签名 -->
      <name>foreach</name>
      <!-- 给自己定义用于实现 自定义的 JSTL 标签的类 的全限定名 -->
      <tag-class>cn.jbit.auction.myjstl.ForEachList</tag-class>
      <body-content>scriptless</body-content>
      <!-- 指定foreach循环中的items属性和var属性 -->
      <attribute>
        <name>items</name>
        <required>true</required>
        <fragment>true</fragment>
      </attribute>
      <attribute>
        <name>var</name>
        <required>true</required>
        <fragment>true</fragment>
      </attribute>
    </tag>
  </taglib>
6.在 jsp 页面中调用
  <%-- 导入自带的 JSTL 标签 --%>
  <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
  <%-- 导入自定义的 JSTL 标签 --%>
  <%@taglib uri="http://127.0.0.0/servlet/mytaglib" prefix="m"%>

  <%-- 使用自定义JSTL标签 实现循环 --%>
    <%-- 创建循环 所使用的 LIST 集合 --%>
    <%
      List<String> list = new ArrayList<String>();
      list.add("a");
      list.add("b");
      list.add("c");
      list.add("d");
      // 保存到 session 中 也可以不保存 使用 EL 表达式都能获取
      session.setAttribute("list",list);
    %>
    <%--
      调用 遍历 LIST 集合
      m: 为导入自定义标签 的 prefix 值
      foreach:是在 *.tld 文件中的标签名 <name>foreach</name>
      var: 为输出属性
      items: 用于输入数据属性
    --%>
    <m:foreach var="s" items="${list }">
      ${s } <%-- 输出值 --%>
    </m:foreach>

  <%-- 与自带的 forEach 循环实现双重循环 --%>
    <%-- 创建循环 所使用的 LIST 集合 --%>
    <%
      List<String> list1 = new ArrayList<String>();
      list1.add("a");
      list1.add("b");
      list1.add("c");
      list1.add("d");
      List<String> list2 = new ArrayList<String>();
      list2.add("a");
      list2.add("b");
      list2.add("c");
      list2.add("d");
      // 在这个集合中放了两个 List 集合
      List<List> list = new ArrayList<List>();
      list.add(list1);
      list.add(list2);
      // 保存到 session 中 也可以不保存 使用 EL 表达式都能获取
      session.setAttribute("list",list);
    %>
    <%--
      调用 遍历 LIST 集合
      外层循环为 自带的、内层循环为 自定义的

      c:forEach 是自带的
      m: 为导入自定义标签 的 prefix 值
      foreach:是在 *.tld 文件中的标签名 <name>foreach</name>
      var: 为输出属性
      items: 用于输入数据属性
    --%>
    <c:forEach var="li" items="${list }">
      <m:foreach var="s" items="${li }">
        ${s } <%-- 输出值 --%>
      </m:foreach>
    </c:forEach>

  7.注意事项
    使用 EL 表达式时注意
      示:items="${list }" // 在{} 中 list 后面可以有空格 ${} 后面到 " 不能为空格、会导致发生错误
      正确:items="${list }" 或 items="${list}"
      错误:items="${list } " 或 items="${list } "

二、simpleTag接口中的方法:

  以下三个方法的共同特点:由服务器调用,在调用doTag之前就调完了。
  void doTag():由服务器调用。在JSP中遇到标签时调用。在自定义标签类中要重写的方法
  void setJspBody(JspFragment jspBody):由服务器调用。传入标签的内容。
  void setJspContext(JspContext pc):由服务器调用。传入当前页面的pageContext对象
  void setParent(JspTag parent):由服务器调用。传入你的爹。没爹传入null

  在自定义标签中 常调用方法
  Object getJspContext():获取 pageContext对象
  示:Object obj = getJspContext().getAttribute("name"); // 获取pageContext域中的保存的数据
  JspTag getParent():由程序员调用。获取该标签的父标签对象。没有返回null
  JspFragment jf=getJspBody();//获得主体内容

三、标签的实际作用
  获得主体内容并输出:
  JspFragment jf=getJspBody();
  jf.invoke(null);

  简易写法:
  getJspBody().invoke(null);

  1.使得主体内容不显示
    <body-content>scriptless</body-content>//主体内容为非脚本

  2.控制结束标签后的内容不执行
    throw new SkipPageException();

  3.控制主体内容重复运行
    在类中写入循环代码即可
    循环输出主体内容代码体现:
    jsp:<itcast:ShowFor count="5">saq</itcast:ShowFor> //count为标签属性

    *.tld 文件
      itcast.tld:
      <tag>
        <name>ShowFor</name>
        <tag-class>text.jsp.ShowFor</tag-class>
        <body-content>scriptless</body-content>
        //配置属性
        <attribute>
          <name>count</name>//属性名
          <required>true</required>//是否必须输入属性值
          <rtexprvalue>true</rtexprvalue>//是否支持表达式
        </attribute>
      </tag>

    类:
      public class ShowFor extends SimpleTagSupport {
        private int count;
        // 省略 getter 和 setter 方法
        public void doTag() throws JspException, IOException {
          for(int i=0;i<count;i++){
            getJspBody().invoke(null);//输出主体内容,当为null时,就输出主体内容
          }
        }

      }

  4.获取主体内容,并操作主体内容后输出
      public void doTag() throws JspException, IOException {
        //获取主体内容
        JspFragment jf=getJspBody();
        //将主体内容写入字符缓存
        StringWriter sw=new StringWriter();
        jf.invoke(sw);
        //调用string的大写转换方法
        String jfString=sw.getBuffer().toString();
        jfString=jfString.toUpperCase();
        //输出
        PageContext pc=(PageContext) getJspContext();
        pc.getOut().write(jfString);
      }

  body-content中的内容:
    1 jsp 不考虑,传统标签处理类中
    2 empty 传统标签和普通标签都能用,主体中不能有内容
    3 scriptless 简单标签使用,要求主体中有内容,但不能有“<”“%”,可以有EL表达式,但不能有java表达式
    4 tagdependent 简单标签使用,告诉类,主体标签中的为文本





posted on 2017-03-05 12:18  DDM-孤空幻影  阅读(163)  评论(0)    收藏  举报