JAVA WEB从入门到精通day13 Jsp详解和EL,JSTL详解

JSP学习

jsp简介

JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计

JSP全称Java Server Pages,是一种动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码。标签通常以<%开头以%>结束。

JSP其实就是一种Java servlet,主要用于实现Java web应用程序的用户界面部分。网页开发者们通过结合HTML代码、XHTML代码、XML元素以及嵌入JSP操作和命令来编写JSP。

JSP通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。

JSP标签有多种功能,比如访问数据库、记录用户选择信息、访问JavaBeans组件等,还可以在不同的网页中传递控制信息和共享信息。

JSP结构

web服务器需要一个JSP引擎,也就是一个容器来处理JSP页面,容器负责截获对JSP页面的请求。(很多服务器都内嵌JSP引擎,比如Tomcat)

JSP容器与Web服务器协同合作,为JSP的正常运行提供必要的运行环境和其他服务。
并且能够正确识别专属于JSP网页的特殊元素。

JSP处理方式

(1)浏览器发送Http请求给服务器

(2)Web服务器识别这是对JSP网页的请求,将该请求传递给JSP引擎,通过使用URL或.jsp文件完成。 

(3)JSP引擎从磁盘中载入JSP文件,将其转换为Servlet,这种转换只是简单将所有文本改用request.getWriter().print("XXX"),并且将所有jsp元素转换成java代码。 

(4)jsp引擎将servlet编译成可执行类,并将原始请求传递给Servlet引擎。 

(5)然后服务器载入并执行servlet类,产生html静态页面并将其放入response中。 

(6)然后浏览器接收response处理生成的静态html页面。 

JSP生命周期

--编译阶段:浏览器请求jsp页面时,jsp引擎去检查是否需要编译这个文件
    如果这个文件没有被编译过,或者在上次编译后被更改过,则编译这个JSP文件。
    编译的过程包括三个步骤
    >解析jsp文件
    >将jsp文件转换成servlet
    >编译servlet

--初始化阶段:加载servlet类,创建实例,调用jspinit()初始化方法。

--执行阶段:初始化完成后,调用jspService()方法,完成相应的操作。

--销毁阶段:调用销毁方法,销毁servlet实例。

JSP语法

<% %>: java代码片段,方法体里可以放什么这里就可以放什么。 

<%= %>:java表达式,用于输出一条表达式或者变量的结果,结果都会被转换为String类型 

<%! %>:jsp声明,可以声明一个或多个变量,方法,供后面的java代码使用,类里面可以放什么这里就可以放什么。 

<%--注释--%>:jsp注释,注释内容不会被发送至浏览器甚至不会被编译 

jsp和Servlet的分工

jsp和Servlet一般分工完成任务。
jsp负责显示页面,Servlet负责处理逻辑。

案例:实现输入两个数,返回两个数的和

步骤:
-在初始页面提交两个数
-在servlet中进行处理
-将结果返回到最终的显示页面
起始页面 index.jsp 

        <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
                <title>Insert title here</title>
            </head>
            <body>
                <!--表单实现两个数的提交-->
                <form action="/JSPTest/AServlet" method="post">
                数字1:<input type="text" name="num1"/>
                数字2:<input type="text" name="num2"/>
                <br/>
                <input type="submit" value="提交">
                </form>
            </body>
        </html>
Servlet实现逻辑处理

      public class AServlet extends HttpServlet {
                    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                        String s1=request.getParameter("num1");  //获取传递的参数
                        String s2=request.getParameter("num2");
                        Integer num1=Integer.parseInt(s1);       //转换为int类型进行相加
                        Integer num2=Integer.parseInt(s2);
                        int num=num1+num2;
                        request.setAttribute("result", num);     //将相加后的值保存在request域
                        request.getRequestDispatcher("/result.jsp").forward(request, response);//请求转发到最终的显示结果页面
                    }

        }
显示结果页面
            <body>
                结果为:<%=request.getAttribute("result") %>>
            </body>

JSP指令

作用:JSP指令用来设置与整个jsp页面相关的属性

格式:<%@指令名称 属性1=”” 属性2=”“…. %>

JSP有三大指令标签

        -<%@page...%> 
        -<%@include...%>
        -<%@taglib...%>

page指令

  page指令常用属性
        ->  pageEncoding:它指定当前jsp页面的编码。在服务器要把jsp编译成.java时需要使用pageEncoding。 

        ->   contentType:表示添加一个响应头:Content-Type。等同于response.setContentType("text/html;charset=utf-8"); 

        ->   import:导包,可以出现多次 

        ->   errorPage:当前页面如果抛出异常,errorPage可以指定转发到其他页面。 

        ->   isErrorPage:它指定当前页面是否是处理错误的页面,使用isErrorPage(true)之后,该页面可以使用9大内置对象中的Exception  

        ->   autoFlush:指定jsp的输出流缓冲区满时,是否自动刷新。默认为true,如果设置为false,则缓冲区满时抛出异常。 

        ->   buffer:制定缓冲区大小,默认为8kb,通常不需要修改。 

        ->   isELIgnored: 是否忽略el表达式,默认为为false,即支持EL表达式。

        ->   language:指定当前jsp编译后的语言类型,默认为java。

include指令

     jsp可以通过include指令包含其他文件,被包含的文件可以是jsp文件,html文件或者文本文件
     它是在jsp被编译成java文件时完成。
     被包含的文件和当前jsp页面合并,共同生成一个java文件,即一个Servlet。

    而RequestDispatcher的include()方法,包含和被包含的是两个Servlet,它们只是把相应内容合并。

Taglib指令

作用:Taglib指令用来引入标签库。 

属性
    -uri:标签库的位置
    -prefix:指定标签库的前缀 

    例如:<%@taglib prefix="pre"  uri="/my-tags"%>
    如果想引用标签库中的text标签
    需要 <pre:text>这样来引用

JSP动作元素

动作元素由服务器执行,在请求处理阶段起作用。 

常用的动作标签
        -<jsp:forward> :转发。与RequestDispatcher的forward方法是一样的。
        -<jsp:include>:包含。与RequestDispatcher的include方法是一样的。
        案例:
            a.jsp页面
            <body>
                <h1>a.jsp</h1>
                <jsp:include page="/jspforward/b.jsp"></jsp:include> //包含b页面
            </body>

            b.jsp页面
            <body>
               <h1>b.jsp</h1>
            </body>

            结果页面显示 
            a.jsp
            b.jsp
        -<jsp:param>:作为forward和include的子标签。用来给转发或包含的页面传递参数
        案例:
            A页面

            <body>
                <h1>a.jsp</h1>
                <jsp:include page="/jspforward/b.jsp">        //请求包含到b页面,并携带参数
                    <jsp:param name="name" value="zhangsan"></jsp:param>
                    <jsp:param name="age" value="18"></jsp:param>
                </jsp:include>
            </body>

            B页面

            <body>
                <h1>b.jsp</h1>
                <%                                   //获取A页面传入的参数
                    String  name=request.getParameter("name"); 
                    String age=request.getParameter("age");
                %>
                <%=name+","+age %>                  //显示参数
            </body>

            结果是页面上显示 zhangsan,18    

JSP九大内置对象

*out对象:是JspWriter类的实例,等同于response.getWriter(),用来向客户端发送文本数据 

*config对象:是在Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时需要用到的参数以及服务器的有关信息(通过传递一个ServletContext对象)  

*request对象:客户端的请求信息被封装在request对象中,是HttpServletRequest的实例  

*response对象:包含了响应客户请求的有关信息,在JSP中很少直接使用它,是HttpServletResponse的实例  

*session对象:指的是客户端与服务器的一次会话。是HttpSession的实例  

*page:代表当前jsp页面本身,类似与类中的this,是Object的实例  

*application对象:可存放全局变量,实现了用户间数据的共享。是ServletContext类的实例  

*exception对象:只有错误的页面才能使用该对象。必须把isErrorPage设为true,才可以使用。是Throwable的实例 

*pageContext对象:只在当前页面有效,域对象,可以取得任何范围的参数,可以获取request,session,application域中的参数,还可以获得jsp其他八个内置对象。是pageContext类的实例

Servlet三大域:Request,Session,application(ServletContext)

JSP四大域:Request,Session,application(ServletContext),pageContext

page域

范围:作用范围是当前的jsp页面。page里的变量,只要页面跳转,就不可用了。
    可以设置和获取其他域的参数,例如request,session,application。 

    -方法
        -setAttribute(String name,Object value):设置属性
        -setAttribute(String name,Object value,int scope):给指定的域设置属性
         例如:pageContext.setAttribute("xxx","XXX",SESSION_SCOPE),给session域设置属性

    可以获取其他八个内置对象
        -方法
        -getSession()
        -getRequest()
        -getPage()
        -.........

    全域查找方法
        -pageContext.findAttribute(String name):按照域的大小,按照pageContext,request,session,servletContext从小到大的顺序查找。

JavaBean详解

JavaBean是特殊的java类,遵守javaBean API规范。
        必须满足如下规范:
        1)必须有一个默认构造方法(无参数的) 

        2)需要被序列化并且实现了Serializable接口 

        3)可能有一系列的set/get方法 

        4)所有属性为private 
       JavaBean程序示例
                public class Person {
                    private String name;
                    private int age;
                    public Person(){

                    }
                    public String getName() {
                        return name;
                    }
                    public void setName(String name) {
                        this.name = name;
                    }
                    public int getAge() {
                        return age;
                    }
                    public void setAge(int age) {
                        this.age = age;
                    }
                }

JAVA内省机制详解

反射和内省很类似,两者的区别在于:
-反射是在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态。  

-内省机制是通过反射来实现的,通过反射的方式访问JAVA BEAN的技术。
内省机制用到的类和接口 

    --BeanInfo用来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性,方法等。
    --PropertyDescriptor类
//java内省机制案例

public class Demo {
                //主函数里使用PropertyDescriptor类直接修改成员属性
            public static void main(String[] args) throws Exception {
                    Person p1=new Person();            //先创建实例
                    PropertyDescriptor p=new PropertyDescriptor("name",Person.class);//获取对应类的属性
                    Method m=p.getWriteMethod();     //获取写方法
                    m.invoke(p1, "zhangsan");        //操作该方法,并写入值
                    System.out.println(p1.getName());  //输出结果为zhangsan
                    getPropertys();                  //调用下面的方法
                }

                //这个函数使用获得BeanInfo类来修改属性
                public static void getPropertys() throws Exception
                {
                    Person p2=new Person();            //创建实例
                    BeanInfo bi=Introspector.getBeanInfo(Person.class);//获取BeanInfo
                    PropertyDescriptor[] p=bi.getPropertyDescriptors();//获取PropertyDescriptor数组
                    if(p!=null&&p.length>0)            //进行遍历,查找到age属性,进行修改
                    {
                        for(PropertyDescriptor pro:p)
                        {
                            if(pro.getName().equals("age"))
                            {
                                Method m=pro.getWriteMethod();  //获取写方法
                                m.invoke(p2, 18);               //执行该方法
                            }
                        }
                    }
                    System.out.println(p2.getAge());  //输出结果为18
                }
            }


            通过上面两个方法来看,第二个需要进行遍历,比较麻烦。

            由于内省比较麻烦,Apache开发了一个工具包 BeanUtils。
            可以在网上学习使用。

jsp中与Javabean相关的标签

-<jsp:useBean>:创建或查找bean,当bean存在时就查找,不存在就创建。
        例如:<jsp:useBean id="bean的名称" class="cn.cad.user(bean的类) scope=“域(request,session,application)”/>  

-<jsp:setProperty>:设置bean里的属性   
        例如:<jsp:setProperty property="属性的名字" name="要操作的bean的名称" value="属性的值"/>  

-<jsp:getProperty>
        例如:<jsp:getProperty name="要操作的bean的名称" property="属性的名字">

EL表达式

目的:为了使jsp写起来更简单

语法:${expression}

El表达式中的[]和.运算符

EL提供.和[] 来获取数据。 

当要获取的属性名称里包含一些特殊字符时,例如<或?等非字母数字的符号,就一定要使用[]。
    例如:${user["my-name"]}
如果要动态取值时,也必须用[]
    例如${user[data]},data是一个变量 

获取变量

EL获取变量数据的方法很简单。
例如 ${username},意思是取出某一范围中名称为username的变量。 

因为我们没有指定哪一范围的username,所以它会依次从page,request,session,application范围查找。查找到就返回,查找不到返回null。 

如果想查某一范围内的变量,可以使用
${ageScope.x},${requestScope.x},${sessionScope.x},${applicationScope.x}来查找。

JavaBean导航案例

创建一个javaBean
                public class Person {
                        private String name;
                        private int age;

                        public Person(){

                        }
                        public String getName() {
                            return name;
                        }
                        public void setName(String name) {
                            this.name = name;
                        }
                        public int getAge() {
                            return age;
                        }
                        public void setAge(int age) {
                            this.age = age;
                        }
                }

        创建一个jsp页面,在这个页面创建person对象,并实现存取,注意导包 

                <%@ page import="cn.cad.jsp.*"%>
                <body>
                <%
                    Person p=new Person();
                    p.setName("张三");
                    p.setAge(18);
                    request.setAttribute("person", p);
                %>

                ${requestScope.person.name }  //不需要使用get方法来获取,而直接用属性的名字即可获取,这就是javabean导航
                </body>

EL十一个内置对象

*pageScope:可以获取page范围里的属性。 

*requestScope:可以获取request范围里的属性  

*sessionScope:可以获取session范围里的属性  

*applicationScope:可以获取application范围里的属性
    例如:${xxxScope.name}  

*param:Map<String,String>类型,可以获取参数  

*paramValues:Map<String,String[]>类型,当一个参数名对应多值时,可以通过这个对象来获取
    例如:${param.username} 

*header:Map类型,对应请求头,key是头名称,value是单个头值  

*headerValues:Map类型,适用于一个请求头多值的情况 
    例如:${header['User-Agent']}

*initParam: 获取web.xml中<context-param>内的参数
    例如:web.xml设置了初始化参数
        <context-param>
            <param-name>name</param-name>
            <param-value>张三</param-value>
        </context-param>

        我们可以在jsp页面中通过 
    ${initParam.name}获取初始化参数值

*Cookie:Map(String ,Cookie)类型。key是cookie名,value是cookie对象。
    例如:我们获取JSESSIONID的cookie值需要
        ${cookie.JSESSIONID.value} 

*pageContext:pageContext类型。可以获取其他对象。
        ${pageContext.request.contextPath} // 获取request对象,然后调用request的getContextPath方法获取项目名,这里用了javabean导航

jstl标签库

jstl是apache提供的jsp标签库,封装了jsp中很多常用的功能。

使用jstl标签库。、
        -在官网上下载需要的jar包,放入tomcat的lib目录下,即可在jsp页面中使用jstl标签。

        jstl有四大标签库
        -core:核心标签库
        -fmt:格式化标签库
        -sql:数据库标签库
        -xml:xml标签库

想要在jsp页面使用标签库需要先导入标签库。
        <%@taglib prefix="前缀" uri="路径"%>        

-core:核心标签库

    常用标签 

    out:输出标签
            属性
            *value:输出的内容。可以使字符串常量,也可以是EL表达式等。
            *default:当要输出的内容不存在时,为null时,输出default指定的内容。
            *escapeXml:默认为true,设定是否转义特殊字符。
    例子:
                <body>
                    <h1>out标签的使用</h1> 
                        <c:out value="aaa"></c:out>  //输出aaa
                        <c:out value="<script>alert('hello')</script>" escapeXml="false"></c:out> //设置为不转义,弹出弹窗
                        <c:out value="${a}" default="不存在"></c:out>      //全域范围内找不到a变量,输出不存在
                </body>
      set:设置标签
                属性:
                *var:变量名
                *value:变量值,可以是el表达式
                *scope:指定的域。默认为page域。
      例子:
                <body>
                    <h1>set标签的使用</h1>
                        <c:set var="name" value="zhangsan"></c:set>     //默认往page域设置name变量
                        <c:set var="age" value="18" scope="request"></c:set> //往request域设置age变量 

                        <c:out value="${pageScope.name}"></c:out>         //输出zhangsan
                        <c:out value="${requestScope.age}"></c:out>       //输出18
                </body>
        remove:删除标签
                属性:
                var:变量名
                scope:指定的域
        例子:
                <body>
                    <h1>remove标签的使用</h1>
                        <% //往每个域里都设置一个a变量 pageContext.setAttribute("a", "page"); request.setAttribute("a", "request"); session.setAttribute("a", "session"); application.setAttribute("a", "application"); %>
                        <c:remove var="a"></c:remove>             //如果不指定域的话,就是删除所有域中的这个变量
                        <c:out value="${a}" default="全被删除"></c:out> //输出全被删除
                </body>
          url:路径标签
                属性:
                value:指定一个路径,会在路径前面自动添加项目名
                var:变量名
                scope:指定的域 
         例子:
                <body>
                    <h1>url标签的使用</h1>
                        <c:url value="/"></c:url><br/>          //输出  /项目名/
                        <c:url value="/Aservlet"></c:url><br/>  //输出 /项目名/Aservlet
                        <c:url value="/" var="a" scope="request"></c:url><br/>  //不输出,向request域里设置a变量,值为 /项目名/
                        <c:out value="${requestScope.a} "></c:out><br/>          //输出a变量  即为/项目名/

                        <c:url value="/index.jsp">                           
                            <c:param name="username" value="张三"></c:param>     //子标签,用来设置参数
                            <c:param name="password" value="123456"></c:param>
                        </c:url>
                 //  输出/项目名/index.jsp?username=%e5%bc%a0%e4%b8%89&password=123456                   
                </body>
            if:判断标签
                属性:
                text:必须是一个boolean类型的值,如果test值为true,则向下执行,否则不执行。
            例子:
                <body>
                    <h1>if标签的使用</h1>
                        <c:set var="name" value="zhangsan" scope="request"></c:set>
                        <c:if test="${not empty name }">     //判断name是否为空
                            <c:out value="${name }"></c:out>  //不为空,输出zhangsan
                        </c:if>
                </body>
            choose:多分支标签
            例子:
                <body>
                    <h1>choose标签的使用</h1>
                        <c:set var="score" value="${param.score }" scope="request"></c:set>  //设置一个score变量,值从提交的参数中获取
                        <c:choose>                                                            //多分支判断,注意分支的顺序,如果把D级放前面,输入91时就会输出D级,并且结束分支。
                            <c:when test="${requestScope.score>100||requestScope.score<0 }">您输出的分数不正确:${score} </c:when>
                            <c:when test="${requestScope.score>90}">A级</c:when>
                            <c:when test="${requestScope.score>80}">B级</c:when>
                            <c:when test="${requestScope.score>70}">C级</c:when>
                            <c:when test="${requestScope.score>60}">D级</c:when>
                            <c:otherwise>不及格</c:otherwise>
                        </c:choose>
                </body>     
            forEach:循环标签
                可以循环遍历数组,集合。
                属性:
                *var:循环变量名
                *begin:开始的位置
                *end:结束的位置
                *step:设置步长,默认为1。类似于 i+=2这种效果。
                *items:指定的数组或集合
            例子:循环变量
                <body>
                    <h1>forEach标签的使用</h1>
                        <c:forEach var="i" begin="1" end="10" step="3">
                            ${i }                                       //输出 1 4  7  10
                        </c:forEach>
                </body>
            例子:循环数组
            <body>
                    <h1>forEach标签的使用</h1>
                    <% String[] strs={"one","two","three"}; //创建数组,并放入request域中 request.setAttribute("strs", strs); %>
                    <c:forEach var="str" items="${requestScope.strs }">    //循环数组,类似于增强for循环
                        ${str }               //输出one,two,three
                    </c:forEach>
            </body>
            forEach的循环状态变量
                可以使用varStatus来创建循环状态变量。
                有几个属性
                *first:boolean类型,判断是否是第一个元素
                *last:boolean类型,判断是否是最后一个元素
                *count:int类型,当前已遍历元素的个数
                *index,int类型,当前元素的下标
                *current:当前循环的对象
            例子:
                <body>
                    <h1>forEach标签的使用</h1>
                    <%
                        ArrayList<String> list=new ArrayList<String>();  //创建一个集合,把集合放入request域中
                        list.add("一");
                        list.add("二");
                        list.add("三");
                        request.setAttribute("list", list);
                    %> 

                    <c:forEach var="ele" items="${requestScope.list }" varStatus="vs"> //循环集合
                            ${vs.first }                    //结果为:
                            ${vs.last }                     //true false 1 0 一 
                            ${vs.count }                    //false false 2 1 二
                            ${vs.index }                    //false true 3 2 三 
                            ${vs.current }
                            <br/>
                    </c:forEach>
                </body>

-fmt:格式化标签库

        作用:用来格式化并输出文本,日期,时间,数字等。

        formatDate:格式化日期标签
                    属性:
                    *value:要输出的日期对象
                    *pattern:输出的格式
            例子:
                    <body>
                            <h1>formatDate标签的使用</h1>
                            <% Date d=new Date(); //获取日期对象,并存入request域中 request.setAttribute("date", d); %>
                            <fmt:formatDate value="${requestScope.date }" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate> //按照指定的格式输出日期
                    </body>
        formatNumber:格式化数字标签
                    属性:
                    *value:要输出的值
                    *pattern:输出的格式
            例子:
                    <body>
                            <h1>formatNumber标签的使用</h1>
                            <% double d1=3.1; //创建两个double值 double d2=3.2; pageContext.setAttribute("d1", d1); pageContext.setAttribute("d2", d2); %>
                            <fmt:formatNumber value="${pageScope.d1 }" pattern="0.000"></fmt:formatNumber><br/>  //输出结果为3.100
                            <fmt:formatNumber value="${pageScope.d2 }" pattern="#.###"></fmt:formatNumber>        //输出结果为3.2
                    </body>

        //用0.000和#.###的区别在于 如果小数点后不足几位,是否自动补0.#不补0.

自定义标签

当jstl标签库已经无法满足我们的需求时,就需要自己开发自定义标签,来满足我们的需求。

自定义标签的步骤
        -编写标签处理类
        -编写标签库描述符文件(tld)

(一)编写标签处理类
            首先我们编写的标签处理类都需要实现Tag接口或者SimpleTag接口,父接口为JspTag
            我们一般都选择实现SimpleTag接口。

            SimpleTag接口的方法
            -JspTag getParent():返回父标签
            -void setJspBody(JspFragment jspBody):设置标签体,JspFragment表示标签体内容
            -void setJspContext(JspContext pc):设置jsp上下文对象。pageContext实现了JspContext接口。当把pageContext对象传入时,就可以获取其他对象来进行交互。
            -void setParent(JspTag parent):设置父标签
            -doTag():处理标签的方法。每次执行标签都会调用这个方法。

            这些方法由我们进行编写,除了getParent()方法以外都由Tomcat自动进行调用。
            doTag()方法会在其他三个方法之后被Tomcat调用。

        (二)编写标签库描述符文件(tld)
            我们可以从其他的tld模板中复制来前面的部分。
            然后在自己配置标签。

自定义标签的几个案例

        例子:自定义标签,输出Hello Tag.

                标签处理类 MyTag1.java 

                public class MyTag1 implements SimpleTag {
                    private PageContext pagecontext;   //获取服务器传进来的JspContext对象
                    private JspFragment body;        //获取服务器传进来的JspFragment对象

                    public void doTag() throws JspException, IOException {
                        pagecontext.getOut().print("Hello Tag."); //获取jsp的out对象对页面进行输出
                    }

                    @Override
                    public JspTag getParent() {
                        return null;
                    }

                    @Override
                    public void setJspBody(JspFragment body) {
                        this.body=body;

                    }

                    @Override
                    public void setJspContext(JspContext context) {
                        this.pagecontext=(PageContext) context;

                    }

                    @Override
                    public void setParent(JspTag arg0) {

                    }

                }

            第二步:编写tld文件 mytag.tld 
                <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>cad</short-name>
                  <uri>http://www.cad.com</uri> //这个前面的可以从其他的tld模板中复制

                  <tag>                                   //配置标签
                    <name>mytag1</name>                   //标签名字
                    <tag-class>cn.cad.tag.MyTag1</tag-class>  //标签类
                    <body-content>empty</body-content>        //标签体内容,这里我们不需要标签体,选择empty
                  </tag>
                 </taglib> 


                 在jsp页面中进行测试
                <%@ page language="java" contentType="text/html; charset=UTF-8"
                    pageEncoding="UTF-8"%>
                <%@ taglib prefix="cad" uri="/WEB-INF/tlds/mytag.tld" %>     //导入标签库文件
                <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
                <html>
                <head>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
                <title>Insert title here</title>
                </head>
                <body>
                    <h1><cad:mytag1/></h1>                 //使用标签,输出Hello Tag.
                </body>
                </html>

                SimpleTagSupport类实现了SimpleTag接口。帮我们简化了很多操作。
            案例:创建有标签体内容的标签
                    我们还记得tld文件的配置中有个<body-content>标签,用来设置标签体。
                    <body-content>可选的值有
                    -empty:无标签体
                    -JSP:标签体可以使任何东西,SimpleTag已经不再支持了。
                    -scriptless:标签体内容不能是java脚本,可以使El表达式,jstl标签等。如果有标签体,使用这个。
                    -tagdependent:标签提内容不做处理,由标签处理类自行处理。没人使用。

                    第一:编写标签处理类

                    public class MyTag2 implements SimpleTag {
                        private PageContext pagecontext;   //获取服务器传进来的JspContext对象和JspFragment对象
                        private JspFragment body;

                        @Override
                        public void doTag() throws JspException, IOException {
                            Writer out=pagecontext.getOut();
                            body.invoke(out);    //获取标签体的内容并执行,里面的参数是Writer流,指定执行的内容显示在哪里,所以我们需要先获取流。

                        }

                        @Override
                        public JspTag getParent() {
                            // TODO Auto-generated method stub
                            return null;
                        }

                        @Override
                        public void setJspBody(JspFragment body) {
                            this.body=body;

                        }

                        @Override
                        public void setJspContext(JspContext context) {
                            this.pagecontext=(PageContext) context;

                        }

                        @Override
                        public void setParent(JspTag arg0) {
                            // TODO Auto-generated method stub

                        }

                    }

                第二步:编写tld文件
                    <tag>
                        <name>mytag2</name>
                        <tag-class>cn.cad.tag.MyTag2</tag-class>
                        <body-content>scriptless</body-content>
                      </tag>


                 在jsp页面中进行测试
                        <body>
                            <cad:mytag2>${"AAA" }</cad:mytag2>   //结果输出 AAA
                        </body>
        案例:创建带有属性的标签

                    第一:编写标签处理类

                    public class MyTag3 implements SimpleTag {
                        private PageContext pagecontext;   //获取服务器传进来的JspContext对象和JspFragment对象
                        private JspFragment body;
                        private boolean test;        //先在类里创建属性,必须有set方法,会在doTag方法之前被调用,设置属性

                        public boolean isTest() {
                            return test;
                        }

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

                        @Override
                        public void doTag() throws JspException, IOException {
                            Writer out=pagecontext.getOut();
                            if(test==true)
                            {
                            body.invoke(out);    //获取标签体的内容并执行,里面的参数是Writer流,指定执行的内容显示在哪里,所以我们需要先获取流。
                            }else{
                                out.write("属性为假");
                            }
                        }

                        @Override
                        public JspTag getParent() {
                            // TODO Auto-generated method stub
                            return null;
                        }

                        @Override
                        public void setJspBody(JspFragment body) {
                            this.body=body;

                        }

                        @Override
                        public void setJspContext(JspContext context) {
                            this.pagecontext=(PageContext) context;

                        }

                        @Override
                        public void setParent(JspTag arg0) {
                            // TODO Auto-generated method stub

                        }

                    }

                第二步:编写tld文件
                    <tag>
                        <name>mytag3</name>
                        <tag-class>cn.cad.tag.MyTag3</tag-class>
                        <body-content>scriptless</body-content>
                        <attribute>                               //在这儿指定属性
                            <name>test</name>                      //属性的名字
                            <required>true</required>                           //属性是否必须填写
                            <rtexprvalue>true</rtexprvalue>         .//属性值是否可以是el表达式
                        </attribute>
                      </tag>

                 在jsp页面中进行测试 

                    <body>
                        <cad:mytag3 test="false">${"AAA" }</cad:mytag3>  //输出属性为假
                    </body>

你可能感兴趣的:(java,java,Web,jstl)