学习笔记之 jstl标签库 与 自定义标签库

来源:互联网 发布:汽车epc软件 编辑:程序博客网 时间:2024/06/07 01:52

引用袁杰老师上课笔记

1.    课程回顾

JSP与EL表达式

 

JSP

       作用:开发动态web资源的技术!java server page!

       Jsp运行原理:

              访问jsp,翻译à 编译à运行

       Jsp语法:

               Jsp表达式:<%= %>  ,  取值

               Jsp 代码片段 <% %>  ,  jsp中写java代码的语法

               Jsp 声明      <%! %>,

              Jsp注释      <%-- --%>

 

              Jsp指令

                     Page指令, 设置页面的编码、导包、缓存大小、是否打开session….

                     Include,实现静态包含

                     Taglib,引入标签库文件(*.tld)

 

              Jsp动作

                     <jsp:forward>、include包含、param参数

 

九大内置对象

       pageContext           PageContext          代表jsp运行时环境

                                                               获取其他8大隐士对象

                                                               往其他域中设置值

                            pageContext.setAttribute(“cn”,”China”,PageContext.requestScope);

                                                               搜索各个域中值

                                                                      pageContext.findAttribute(“cn”);

                                                               其他

                                                                      转发、包含!

       Request          HttpServletRequest        封装请求信息

       Session           HttpSession                  会话对象

       Application     ServletContext                     代表当前项目

 

       response

       config

       out                 JspWriter                      带缓冲功能的printWriter

       exception

       page               this

 

EL表达式:

       取值,${cn},

       指定域取值, ${pageScope.cn},  ${requestScope.cn};

              (原理: pageContext.findAttribute(“cn”))

       获取对象的值:${user.id}, ${user.address.province}

       获取当前应用上下文:${pageContext.request.contextPath}-à/day12

       获取list集合值:${list[0]}, 获取集合中第一个元素

       获取map集合值:${map.cn},获取map对象中键为”cn”对应的值

Jsp : el + jstl 作为数据显示!

      

 

2.    jstl标签库

2.1 引入

EL表单式可以取值:取出域中的值!但是使用el标签式不能进行:设置值、条件判断、迭代!

所以 ,我们要学习新的技术,丰富我们对页面数据的处理!使用jstl标签库可以做到上述!

 

2.1  概述

l  JavaServer Pages Standard Tag Library  jsp标准标签库

l  使用el + jstl 就可以取代jsp中出现的java代码

l  JSTL 主要由Apache组织的Jakarta Project 实现

项目中使用:

1.      下载jar文件;  www.apache.org

2.      项目中引入,把jar包拷贝到lib目录下

       jstl-1.2.jar, standard.jar

 

或者:项目中不引用jar文件也可以,因为如果是javaee5.0以上的版本环境,会继承此jar包!

 

2.2  Jstl常用标签使用

常用功能: 核心标签库、国际化标签库、xml标签库、el函数库!

 

使用标签库:

1.      引入标签库文件

       <!-- 引入标签库文件: 核心标签库文件 -->

<%@taglib

       uri=http://java.sun.com/jsp/jstl/core      引入名称空间,通过名称空间找到c.tld文件

       prefix="c"                                         前缀

      

 %>

2.      使用标签

       <c:set></c:set>              设置值

      <c:outvalue=""></c:out>      输出值

      <c:iftest=""></c:if>             判断

      <c:choose></c:choose>         多重判断

      <c:forEach></c:forEach>    迭代

      <c:forTokensitems="" delims=""></c:forTokens>

 

Set标签

设置普通值。

       <c:set

              var="cn"              变量名称

              value="China"              名称对应的值

              scope="request">   变量存储的域:page/request/session/application

</c:set>

 

设置对象值

<c:set

        property="id"       对象的属性名称

       value="U000001" 属性名称对应的值

       target="${requestScope.user}">   设置的目标对象

</c:set>

 

out标签

获取输出值。(也可以使用el表达式获取值,推荐使用el表达式取值)

<c:out

       value="<h1>标题 </h1>"                  输出的值, 支持el表达式取值或直接输出

       scapeXml="false"                               默认为true,表示原样输出值

                                                               false, 以html标签解析执行内容

        default="默认值"></c:out>               默认值

 

 

<body>

    <!-- 1. 设置值

                String cn = "China";

                pageContext.set..("cn",cn);

    -->

   

    <c:setvar="cn"value="China"scope="request"></c:set>

   

   

    <!-- 输出值 -->

    <c:outvalue="<h1>标题</h1>"escapeXml="false"default="默认值"></c:out>

    ${cn }

   

    <hr/>

    <%

        // 存储user对象

        User user = new User();

        request.setAttribute("user",user);

    %>

    <c:setproperty="id"value="U000001"target="${requestScope.user}"></c:set>

    ${user.id }

  </body>

 

 

if、choose标签

<c:if test="${1==2}">

             条件成立

 </c:if>

 

<c:choose>

             <c:whentest="${1==1}">条件成立</c:when>

             <c:otherwise>

                    条件不成立

             </c:otherwise>

      </c:choose>

 

<body>

    <c:iftest="${1==2}">

        条件成立

    </c:if>

    <hr/>

    <!-- 多重判断 -->

    <c:choose>

        <c:whentest="${1==1}">条件成立</c:when>

        <c:otherwise>

            条件不成立

        </c:otherwise>

    </c:choose>

    <hr/>

    <%

        // 保存数据

        request.setAttribute("cn","China");

    %>

    <c:iftest="${cn != null}">

        迭代集合

    </c:if>

    或<br/>

    <c:iftest="${not emptycn}">

        迭代集合

    </c:if>

   

   

  </body>

 

(重)foreach标签

<c:forEach

        var="u"                      记录当前迭代的每一个元素值,临时变量,只是引用作用

        items="${listUser}"   要迭代的集合

       varStatus="vs">            记录当前迭代的状态:index/count

</c:forEach>

 

<body>

        <%

            User user1 = new User();

            user1.setId("u0001");

            user1.setName("Tom");

            User user2 = new User();

            user2.setId("u0002");

            user2.setName("Jack");

            //模拟数据:构建一个list集合

            List<User> list = new ArrayList<User>();

            list.add(user1);

            list.add(user2);

            request.setAttribute("listUser",list);

 

            //模拟数据:构建一个map集合

            Map<String,User> map = new HashMap<String,User>();

            map.put(user1.getId(),user1);

            map.put(user2.getId(),user2);

            request.setAttribute("map",map);

           

            /*for (Entry<String,User> en : map.entrySet() ){

                // 获取key

                en.getKey();

                // 获取值

                en.getValue();

            }*/

        %>

       

        <!-- 1. 遍历list集合 -->

        序号,编号, 名称<br/>

        <c:forEachvar="u"items="${listUser}"varStatus="vs">

            ${vs.index },  ${u.id } , ${u.name } <br/>

        </c:forEach>

        <hr/>

        <!-- 2. 遍历map集合 -->

        <c:forEachvar="en"items="${map}">

            ${en.key }, ${en.value.name } <br/>

        </c:forEach><hr/>

       

        <!-- 3. 迭代 -->

        <c:forEachvar="num"begin="0"end="10"step="2">

            ${num } ,

        </c:forEach><hr/>

       

        <!-- 分割字符串 -->

        <c:forTokensvar="str"items="1,2,3,4"delims=",">

            ${str }。

        </c:forTokens>

    </body>

 

 

其余jstl标签,

      

       <c:url></c:url>

      <c:catch>

             有可能出现异常的代码放到这里

      </c:catch>

      <c:redirect></c:redirect>

 

 

jstl标签  

       c.tld,标签库描述文件  

java代码

 

 

3.    自定义标签

作用:用于移除jsp中java代码!或实现一些公用的功能!

例如:

       在jsp中,输出当前来访者ip!

              欢迎你,127.0.0.1!

 

 

3.1  Hello Tag案例!

1. 标签处理器类:HelloTag.java

2. 标签描述文件: itcast.tld, 放到WEB-INF/itccast.tld目录

3. 页面使用

       a.先引入标签库文件:<%@taglib url=”” prefix=”” %>

public class HelloTag extends TagSupport{

   

    @Override

    public int doStartTag() throws JspException {

       

    HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();

       

        String ip = request.getRemoteAddr();

       

        try {

            this.pageContext.getOut().write(ip);

        } catch (IOException e) {

            e.printStackTrace();

        }

        return TagSupport.EVAL_BODY_AGAIN;

    }

}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.tld

<tlib-version>1.1</tlib-version>

    <short-name>itcast</short-name>

    <uri>6231565</uri>

 

    <!-- 描述一个标签的开始 -->

    <tag>

        <!-- 标签名称 -->

        <name>showIp</name>

        <!-- 标签对应的java代码类:标签处理器类 -->

        <tag-class>cn.itcast.tag.HelloTag</tag-class>

        <body-content>JSP</body-content>

    </tag>

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.jsp

<%@tagliburi="6231565"prefix="itcast"%>

<itcast:showIp></itcast:showIp>

 

 

 

 

3.1    传统标签的开发

 

Interface Tag

       void setPageContext(PageContext pc) – 把当前jsp运行时环境传入

       void setParent(Tag t)                    -- 传入当前标签的父标签

       int   doStartTag()                        --执行开始标签

       int   doEndTag()                         --执行结束标签

       void release()                                    -- 释放资源

 

EVAL_BODY_INCLUDE            执行标签体

EVAL_PAGE                              执行页面余下部分

SKIP_BODY                              不执行标签体                    

SKIP_PAGE                               不执行页面余下部分

 

查看自定义标签,翻译后的代码:

private boolean _jspx_meth_itcast_005fshowIp_005f0(PageContext _jspx_page_context)

          throws Throwable {

         // 1. 传入pageContext对象

    PageContext pageContext = _jspx_page_context;

 

    JspWriter out = _jspx_page_context.getOut();

   

       //2. 实例化标签处理器类

       //  itcast:showIp

    cn.itcast.tag.HelloTag _jspx_th_itcast_005fshowIp_005f0 = (cn.itcast.tag.HelloTag) _005fjspx_005ftagPool_005fitcast_005fshowIp_005fnobody.get(cn.itcast.tag.HelloTag.class);

  

   // 3. 设置当前jsp运行时环境

       _jspx_th_itcast_005fshowIp_005f0.setPageContext(_jspx_page_context);

       // 4. 设置当前标签的父标签,如果当前标签没有父标签,传入null

    _jspx_th_itcast_005fshowIp_005f0.setParent(null);

       // 5. 执行开始标签

    int _jspx_eval_itcast_005fshowIp_005f0 = _jspx_th_itcast_005fshowIp_005f0.doStartTag();

    if (_jspx_th_itcast_005fshowIp_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {

      _005fjspx_005ftagPool_005fitcast_005fshowIp_005fnobody.reuse(_jspx_th_itcast_005fshowIp_005f0);

      return true;

    }

    _005fjspx_005ftagPool_005fitcast_005fshowIp_005fnobody.reuse(_jspx_th_itcast_005fshowIp_005f0);

    return false;

  }

 

 

 

3.2    传统标签的执行流程

RationtionRose建模工具!时序图,说明自定义标签执行原理!

 

 

3.3    传统标签功能

1.      控制执行标签体

       开始标签:返回EVAL_BODY_INCLUDE

a.      编写标签处理器类

b.      标签描述文件

c.      页面引用标签描述文件,使用标签

 

2.      控制不执行标签体

 

 

 

 

 

 

 

4.    简单标签

传统标签中,使用了3个接口,2个实现类,来完成自定义标签的开发逻辑!但是这样,对于开发人员来说,学习成本较高,不利于自定义标签技术的普及!

所以,在jsp2.0以后,推出了简单标签技术! 只有1个接口,一个实现类,即可完成自定义标签的开发!(后面开发时候,统统使用简单标签!)

 

4.1   简单标签相关接口

Interface SimpleTag

       void setJspContext(JspContext pc)        把当前jsp运行环境传入

                                         (pageContext extendsJspContext)

       void setParent(JspTag parent)               把当前标签的父标签传入

       void  doTag()                                          标签处理器处理业务逻辑,都写到此方法中

       void setJspBody(JspFragment jspBody)       传入代表标签体的JspFragment对象

      

4.2   简单标签功能

1.      控制执行标签体

2.      控制不执行标签体

3.      控制执行页面余下部分

4.      控制不执行页面余下部分

5.      重复执行标签体

6.      修改标签体内容

 

开发步骤:

1.      标签处理器类, 继承simpleTagSuppport

2.      标签描述文件

3.      页面引入,使用描述的标签

 

 

/**

 *简单标签开发

 *1.    控制执行标签体

2.  控制不执行标签体

3.  控制执行页面余下部分

4.  控制不执行页面余下部分

5.  重复执行标签体

6.  修改标签体内容

 

 * @author Administrator

 *

 */

public class SimpleDemo1 extends SimpleTagSupport {

   

//  JspFragment jspBody;

//  public JspFragment getJspBody(){

//      return this.jspBody;

//  }

   

 

    // 标签处理器处理方法

    public void doTag() throws JspException, IOException {

       

        /****1. 控制执行标签体*****/

       

        //1.1 得到标签体

        //JspFragment jspBody =  this.getJspBody();

        //1.2 执行标签体

        //jspBody.invoke(this.getJspContext().getOut());

        //jspBody.invoke(null);// 默认使用jsp页面的jspWriter对象向浏览器写入数据

    }

   

   

//  public void setJspBody(JspFragment jspBody) {

//      this.jspBody = jspBody;

//  }

}

 

 

public class SimpleDemo2 extends SimpleTagSupport {

   

   

 

    /*4.    控制不执行页面余下部分*/

//  public void doTag() throws JspException, IOException {

//      throw new SkipPageException();

//  }

   

    //5.    重复执行标签体

//  public void doTag() throws JspException, IOException {

//      // 得到标签体

//      JspFragment jspBody =  this.getJspBody();

//     

//      // 重复执行

//      for (int i=0; i<10; i++) {

//          jspBody.invoke(null);

//      }

//  }

   

   

    //6.    修改标签体内容

    public void doTag() throws JspException, IOException {

       

        // 获取标签体

        JspFragment jspBody = this.getJspBody();

       

        // 缓存写入的内容

        StringWriter sw = new StringWriter();

        // 执行标签体

        jspBody.invoke(sw);

       

        // 直接获取标签体内容

        String content = sw.toString();

        // 修改标签体

        content = content.toUpperCase();//转换为大写

 

        // 向浏览器输出内容

        this.getJspContext().getOut().write(content);

    }

   

}

 

 

4.3   带属性标签的开发

重复执行标签体:可以指定重复次数!

 

1.        标签处理器类

 

/**

 * 带属性标签开发

 *

 * @author Administrator

 *

 */

public class SimpleAttr extends SimpleTagSupport {

 

    // 定义变量,接收页面传递的参数

    private int num;   

 

    public void setNum(int num) {

        this.num = num;

    }

 

    // 标签处理器处理方法

    public void doTag() throws JspException, IOException {

 

        // 1. 获取标签体

        JspFragment jspBody = this.getJspBody();

        // 2. 执行标签体

        for (int i = 0; i <num; i++) {

            jspBody.invoke(null);

        }

    }

 

}

 

 

2.        标签描述文件, 描述标签、描述属性

 

<!-- 简单表标签:2.带属性的标签 -->

  <tag>

    <name>showInfo</name>

    <tag-class>cn.itcast.simpletag.SimpleAttr</tag-class>

    <body-content>scriptless</body-content>

   

    <!-- 定义属性 -->

    <attribute>

    <!-- 属性名称 -->

    <name>num</name>

    <!-- 属性是否必填 -->

    <required>true</required>

    <!-- 属性是否执行表达式取值 -->

    <rtexprvalue>true</rtexprvalue>

    </attribute>

  </tag>

 

 

3.        页面使用

 

<%@ page language="java"import="java.util.*"pageEncoding="UTF-8"%>

<!-- 引入自定义标签 -->

<%@tagliburi="123456789"prefix="itcast"%>

 

 

<!DOCTYPEHTMLPUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>My JSP 'index.jsp' starting page</title>

    <metahttp-equiv="pragma"content="no-cache">

    <metahttp-equiv="cache-control"content="no-cache">

    <metahttp-equiv="expires"content="0">   

  </head>

 

  <body>

    <itcast:showInfonum="6">A</itcast:showInfo>

  </body>

</html>

 

4.4   标签体类型

       <body-content>JSP</body-content>

   <body-content>scriptless</body-content>

   <body-content>empty</body-content>

<body-content>tagdependent</body-content>

 

JSP: 只能在传统标签用,简单标签不支持

       如果指定标签体类型为jsp,表示支持jsp标本表达式取值,即<%= %>

scriptless  不支持jsp脚本表达式取值,但可以使用el表达式取值

empty   没有标签体

tagdependent         标签体内容原样输出

 

 

5.    简单标签,案例开发

5.1   开发一个防盗链标签 (referer)

1.        标签处理器类: 获取页面来源,判断

 

public class RefererTag extends SimpleTagSupport {

   

    // 保存标签属性值

    private Stringfrom;

    private StringerrorPage;

    public void setFrom(String from) {

        this.from = from;

    }

    public void setErrorPage(String errorPage) {

        this.errorPage = errorPage;

    }

 

 

    /**

     * 当前页面的来源,一定是from如果不是从from进入,跳转到errorPage

     */

    public void doTag() throws JspException, IOException {

        // 获取pageContext对象

        PageContext pageContext =  (PageContext) this.getJspContext();

        // 获取requestresponse对象

        HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();

        HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();

       

        // 获取当前页面来源

        String referer = request.getHeader("referer");

        // 判断:当前页面,要从指定页面进入

        if (referer ==null || !referer.contains(from)) {

            // 跳转到错误页面

            response.sendRedirect(request.getContextPath() + errorPage);

        }

       

    }

}

 

 

2.        标签描述文件

 

<!-- 简单表标签:3.开发防盗链标签 -->

  <tag>

    <name>referer</name>

    <tag-class>cn.itcast.referer.RefererTag</tag-class>

   <body-content>empty</body-content>

   

    <!-- 定义属性 -->

    <attribute>

    <name>from</name>

    <required>true</required>

    <rtexprvalue>true</rtexprvalue>

    </attribute>

    <attribute>

    <name>errorPage</name>

    <required>true</required>

    <rtexprvalue>true</rtexprvalue>

    </attribute>

  </tag>

 

 

3.        jsp页面 –excellent.jsp精彩内容页面: 不能直接访问,上一个页面必须是广告页面

 

<body>

    <!--

        当前页面要从广告页面进入!

        from: 页面来源

        errorPage: 错误页面,当不是从指定页面进入时,跳转到错误页面

     -->

     

     <itcast:refererfrom="/adv.jsp"errorPage="/error.jsp"/>

   

   

    精彩内容.........你看到没有!!!

  </body>

 

4.        广告页面:只能从广告页面,进入到精彩页面

 

<body>

    广而告之.......传智播客很好!!!<br/>

   

    <ahref="${pageContext.request.contextPath }/excellent.jsp">点我看精彩内容</a>

  </body>

 

 

5.2   开发if标签

1. 标签处理类

public class IfTag extends SimpleTagSupport {

 

    // 保存jsp页面的属性

    private boolean test;

    public void setTest(boolean test) {

        this.test = test;

    }

 

 

    // 标签处理器处理器方法

    public void doTag() throws JspException, IOException {

        // 当条件成立,执行标签体

        if (test) {

            JspFragment jspBody = this.getJspBody();//alt + shift + L

            jspBody.invoke(null);

        }

    }

}

 

2. 标签描述文件

<!-- 简单表标签:4.开发if标签 -->

  <tag>

    <name>if</name>

    <tag-class>cn.itcast.iftag.IfTag</tag-class>

   <body-content>scriptless</body-content>

   <!-- 属性 -->

   <attribute>

        <name>test</name>

        <required>true</required>

        <rtexprvalue>true</rtexprvalue>

   </attribute>

  

</tag>

 

 

3. 页面

  <body>

    <itcast:iftest="${1==2}">

    条件成立

    </itcast:if>

  </body>

 

 

 

 

5.3   开发choose标签

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`.jsp

<body>

     <itcast:choose>

        <itcast:whentest="${1==11}">执行when</itcast:when>

        <itcast:otherwise>

            执行otherwise

        </itcast:otherwise>

     </itcast:choose>

  </body>

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`.tld

<tag>

        <name>choose</name>

        <tag-class>cn.itcast.choosetag.Choose</tag-class>

        <body-content>scriptless</body-content>

    </tag>

    <tag>

        <name>when</name>

        <tag-class>cn.itcast.choosetag.When</tag-class>

        <body-content>scriptless</body-content>

        <attribute>

            <name>test</name>

            <required>true</required>

            <rtexprvalue>true</rtexprvalue>

        </attribute>

    </tag>

    <tag>

        <name>otherwise</name>

        <tag-class>cn.itcast.choosetag.Otherwise</tag-class>

        <body-content>scriptless</body-content>

    </tag>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` Choose.java

public class Choose extends SimpleTagSupport{

 

    private boolean flag = false;

    public boolean isFlag() {

        returnflag;

    }

 

    public void setFlag(boolean flag) {

        this.flag = flag;

    }

   

    public void doTag() throws JspException, IOException {

        // 执行标签体

        this.getJspBody().invoke(null);

    }

   

}

 

 

 

 

 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` When.java

public class When extends SimpleTagSupport{

 

    private boolean test;

    public boolean isTest() {

        returntest;

    }

    public void setTest(boolean test) {

        this.test = test;

    }

   

    public void doTag() throws JspException, IOException {

        // 执行标签体

        if (test) {

            //1. 执行标签体

            this.getJspBody().invoke(null);

            //2. 修改父标签的标记位

            //2.1 获取父标签

            Choose choose =  (Choose) this.getParent();

            //2.2 设置父标签标记位

            choose.setFlag(true);

           

        }

    }

   

}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` Otherwise.java

 

public class Otherwise extends SimpleTagSupport{

 

    public void doTag() throws JspException, IOException {

        // 什么情况执行标签体:当没有执行when标签的时候,执行otherwise标签体

       

        //1. 获取父标签

        Choose choose = (Choose) this.getParent();

        //2. 判断

        if (!choose.isFlag()) {

            // 执行标签体

            this.getJspBody().invoke(null);

        }

    }

   

}

 

 

5.4   开发forEach标签

 

 

 

 

重点:

1.      jstl 标签: 遍历list/map

2.      简单标签:开发一些个性化功能的案例!


0 0