Java进阶学习第十三天——JSTL&EL学习

文档版本开发工具测试平台工程名字日期作者备注
V1.02016.05.06lutianfeinone

JSTL标签库

JSTL标签库概述

  • JSP标准标签库。
  • 作用:和EL表达式一起 取代<% %>
  • 版本:1.0 1.1和1.2(区别不大)
    • 1.0EL表达式没有纳入规范
    • 1.1和1.2EL表达式纳入规范
JSTL1.1下载相应的jar包
  • JSTL的下载

    • JSTL 主要由Apache组织的Jakarta Project 实现
    • http://tomcat.apache.org/taglibs/standard/
    • 容器必须支持Servlet 2.4 且JSP 2.0 以上版本
    • JavaEE1.4 以上
  • JSTL导入jar包

    • 解压缩后将lib 中的jstl.jarstandard.jar复制到WEB应用程序的WEB-INF\lib
    • 标签库
      • c.tld 核心的标签库
      • fn.tld EL表达式标签库
JSTL的快速入门
  • 导入jar包
    • jstl.jarstandard.jar
  • 新建jsp的页面

    • 在页面中引入核心标签库
      • <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
  • JSTL标签库关于导入版本的问题

    • http://java.sun.com/jsp/jstl/core 1.1或者1.2版本(使用该版本)
    • http://java.sun.com/jstl/core 1.0版本(不支持EL表达式)


JSTL的标签
<c:out>标签
  • 输出常量或者域范围中的变量(value属性,使用EL表达式)
  • 输出默认值(default属性)
  • 默认html标签不转义(escapeXml)

  • escapeXml:默认是true,进行转义,设置成false,不转义。

  • 代码:

    <c:out value="Hello"></c:out>
    <c:out value="${name }"></c:out>
    <!-- "" -->
    <c:out value="${ city }" default="北京"></c:out>
    <c:out value="<a href='#'>超链接</a>" escapeXml="false"/>
<!-- c:out 输出数据到浏览器 -->
<c:out value="Hello c out "></c:out>
Hello c out 
<!-- 输出一个变量 -->
<c:set var="m" value="10" scope="page"/>
<c:out value="${m}"></c:out>
${m }
<!-- 转义HTML 默认转义,通过设置escapeXml 为false 不进行转义-->
<c:out value="<a href='xxx'>link</a>" />
${fn:escapeXml("<a href='xxx'>link</a>") }
<!-- 允许输出默认值 ,如果city不存在,输出北京-->
<c:out value="${city}" default="北京"></c:out>
${empty city?"北京":city }


<c:set>标签
  • 属性

  • 向4个web域对象存入值

    • <c:set var="i" value="10" scope="request" ></c:set>
  • 修改JavaBean对象属性的值

    • <c:set target="${ user }" property="username" value="小凤"></c:set>
  • 练习

<!-- 保存一个数据到四个数据范围 -->
<%
    request.setAttribute("name","itcast");
%>
<c:set var="name" value="itcast" scope="request"></c:set>

<!-- 设置一个保存在四个范围的java对象的属性值 -->
<%
    Person person = new Person();
    person.setName("张三");
    pageContext.setAttribute("person",person);
%>
<c:set target="${person}" property="name" value="李四"></c:set>
${person.name }


<c:remove>标签
  • 用于删除各种Web域中的属性。

  • 属性

    • var :要删除的属性
    • scope :所在域的范围
  • 语法格式如下:

    <c:remove var="varName"     
            [scope="{page|request|session|application}"] /> 
  • 代码
    <c:set var="name" value="小凤" scope="page"></c:set>
    ${ name }

    <c:remove var="name" scope="page"/>
    ${name }
<%
    request.setAttribute("age",20);
    // 删除age
    request.removeAttribute("age");
%>

<c:set var="age" value="20" scope="request"></c:set>
<c:remove var="age" scope="request"/>


<c:catch>标签
  • 用于捕获嵌套在标签体中的内容抛出的异常
  • 语法格式如下:<c:catch [var="varName"]>nested actions</c:catch>
  • var属性用于标识<c:catch>标签捕获的异常对象,它将保存在page这个Web域中。
  • 属性:var 把异常的信息保存变量中

  • 代码

<%
    try {
        int d = 1/0;
    }catch(Exception e){
        e.printStackTrace();
    }
%>
<!-- 异常就会被捕获,保存page范围 e 对象中 -->
<c:catch var="e">
    <% 
        String s = "abc";
        s.charAt(4);
    %>
</c:catch>
${e.message }


<c:if>标签
  • <c:if test="">标签可以构造简单的“if-then”结构的条件表达式

    • 没有<c:else>标签
  • 属性

  • 代码

    <c:set var="i" value="10" scope="page"></c:set>
    <c:if test="${ i ge 10 }" var="x" scope="page">
        i >= 10
    </c:if>
    <c:if test="${ i lt 10 }">
        i < 10
    </c:if>
    ${ x }


<c:choose>标签
  • <c:choose>标签用于指定多个条件选择的组合边界,它必须与<c:when><c:otherwise>标签一起使用。使用<c:choose><c:when><c:otherwise>三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构。

  • 代码:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<c:set value="${param.count}" var="count“  /> pageContext(count,2)
<c:choose>
    <c:when test="${count == 0}">
        对不起,没有符合您要求的记录。
    </c:when>
    <c:otherwise>
        符合您要求的记录共有${count}条.
    </c:otherwise>
</c:choose>


<c:forEach>标签(重点)
  • <c:forEach>标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。

  • 循环遍历数据(数组,集合,Map集合)

  • 属性
    • begin :从哪开始
    • end :到哪结束
    • step :步长
    • varStatus:记录循环遍历的信息
      • index
      • count(常用)
      • first
      • last

  • varStatus:记录循环遍历的信息


  • 代码
<%
        String [] arrs = {"美美","小凤","芙蓉","小苍"};
        request.setAttribute("arrs", arrs);
    %>
    <!-- for(String s : arrs){ }  -->
    <c:forEach var="s" items="${ arrs }">
        ${ s }
    </c:forEach>

    <h4>遍历集合</h4>
    <%
        List<String> list = new ArrayList<String>();
        list.add("美美");
        list.add("小凤");
        list.add("芙蓉");
        list.add("小泽");
        request.setAttribute("list", list);
    %>
    <c:forEach var="s" items="${ list }">
        ${ s }
    </c:forEach>

    <h4>遍历Map集合</h4>
    <%
        Map<String,String> map = new HashMap<String,String>();
        map.put("aa", "美美");
        map.put("bb", "小凤");
        map.put("cc", "芙蓉");
        request.setAttribute("map", map);
    %>
    <c:forEach var="entry" items="${ map }">
        ${ entry.key } -- ${ entry.value }
    </c:forEach>

    <h4>遍历对象的集合</h4>
    <%
        List<User> uList = new ArrayList<User>();
        uList.add(new User("美美","123"));
        uList.add(new User("小风","234"));
        uList.add(new User("芙蓉","345"));
        request.setAttribute("uList", uList);
    %>
    <c:forEach var="user" items="${ uList }">
        ${ user.username } -- ${ user.password }
    </c:forEach>


    <h4>迭代数据</h4>
    <h4>迭代从1到10</h4>
    <c:forEach var="i" begin="1" end="10" step="2">
        ${ i }
    </c:forEach>


    <h4>计算从1加到100的和</h4>
    <c:set var="sum" value="0" scope="page"></c:set>
    <c:forEach var="i" begin="1" end="100" step="1">
        <c:set var="sum" value="${ sum + i }"></c:set>
    </c:forEach>
    ${ sum }

    <h4>遍历10到100的偶数,每到第3个数,显示红色</h4>
    <c:forEach var="i" begin="10" end="100" step="2" varStatus="status">
        <c:choose>
            <c:when test="${ status.first }">
                <font color="blue">${ i }</font>
            </c:when>
            <c:when test="${ status.count % 3 eq 0 }">
                <font color="red">${ i }</font>
            </c:when>
            <c:otherwise>
                ${ i }
            </c:otherwise>
        </c:choose>
    </c:forEach>


<c:param> 标签
  • 在JSP页面进行URL的相关操作时,经常要在URL地址后面附加一些参数。
  • <c:param>标签可以嵌套在<c:import><c:url><c:redirect>标签内,为这些标签所使用的URL地址附加参数
  • <c:param>标签在为一个URL地址附加参数时,将自动对参数值进行URL编码
    • 例如,如果传递的参数值为“中国”,则将其转换为“%d6%d0%b9%fa”后再附加到URL地址后面,这也就是使用<c:param>标签的最大好处。
  • 用于传递参数
  • 属性
    • name :参数名称
    • value :参数的值
  • 示例:<c:param name="name" value="value" />


<c:import>标签
  • 包含页面

  • url :要引入页面的地址

  • context :虚拟路径
  • var :引入页面保存到属性中
  • scope :域的范围

  • 代码

    <c:import url="/jstl/choose.jsp" context="/day13" var="i" scope="page">
        <c:param name="username" value="meimei"></c:param>
    </c:import>
    ${ i }
<!-- 引入foreach.jsp 效果类似包含-->
<c:import url="/jstl/foreach.jsp" context="/day8"></c:import>
<hr/>
<!-- 引入不显示,将内容保存另一个变量中 -->
<c:import url="/jstl/foreach.jsp" context="/day8" var="content" scope="page"></c:import>
${content }

<c:import url="http://java.sun.com" >
    <c:param name="test" value="1234" />
</c:import>


<c:url>标签
  • <c:url>标签用于在JSP页面中构造一个URL地址,其主要目的是实现URL重写
  • URL重写就是将会话标识号以参数形式附加在URL地址后面

    • http://localhost/day12/demo?jsessionid=xxxxxxx;
  • 属性

    • var :声明属性
    • value :要跳转的地址
    • scope :域范围
    • context :虚拟路径

  • 代码
    <c:url var="i" value="/jstl/choose.jsp" scope="request" context="/day13">
        <c:param name="username" value="xiaofeng"></c:param>
    </c:url>

    <a href="${ i }">choose</a>
<%
    String url = "/day8/index.jsp";
    url = response.encodeURL(url);
%>
<!-- 将/day8/index.jsp 进行url重写,保存page范围 myurl中 -->
<c:url value="/index.jsp" context="/day8" var="myurl" scope="page" />

<%=url %>
${myurl }

<!-- 通过c:url 结合 c:param 对中文完成URL编码 -->
<c:url value="/login" context="/day8" var="myurl2" scope="page">
    <c:param name="username" value="张三"></c:param>
</c:url>
${myurl2 }


<c:redirect>重定向
  • 用于实现请求重定向

  • 属性

    • url :重定向的地址
    • context :虚拟路径


* 代码

    <c:redirect url="/jstl/choose.jsp" context="/day13">
        <c:param name="username" value="furong"></c:param>
    </c:redirect>


<c:forTokens>标签 (了解)
  • 分隔字符串
<h4>分隔字符串</h4>
<c:set var="i" value="aa,bb,cc" scope="page"></c:set>
<c:forTokens items="${i }" delims="," var="x">
    ${ x }
</c:forTokens>
<c:forTokens 
        items=要切分的字符串
        delims=按着什么格式切分
        var=定义变量
        [varStatus="varStatusName"] 
        [begin="begin"] 
        [end="end"] 
        [step="step"]>
      //body内容
</c:forTokens>


EL函数

  • EL函数是用来操作字符串
  • 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用。
  • 这些EL函数在JSTL开发包中进行描述,因此在JSP页面中使用SUN公司的EL函数库,需要导入JSTL开发包,并在页面中导入EL函数库,如下所示:
    • <%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>


EL常用函数
fn:toLowerCase函数
  • fn:toLowerCase函数将一个字符串中包含的所有字符转换为小写形式,并返回转换后的字符串,它接收一个字符串类型的参数,例如
    • fn:toLowerCase("Www.IT315.org") 的返回值为字符串“www.it315.org”
    • fn:toLowerCase("")的返回值为空字符串


fn:toUpperCase函数
  • fn:toUpperCase函数将一个字符串中包含的所有字符转换为大写形式,并返回转换后的字符串,它接收一个字符串类型的参数。例如:
    • fn:toUpperCase("Www.IT315.org") 的返回值为字符串“WWW.IT315.ORG”
    • fn:toUpperCase("")的返回值为空字符串


fn:trim函数
  • fn:trim函数删除一个字符串的首尾的空格,并返回删除空格后的结果字符串,它接收一个字符串类型的参数。需要注意的是,fn:trim函数不能删除字符串中间位置的空格。
    • 例如,fn:trim(” www.it315.org “) 的返回值为字符串“www.it 315.org”。


fn:length函数
  • fn:length函数返回一个集合或数组大小,或返回一个字符串中包含的字符的个数,返回值为int类型。
  • fn:length函数接收一个参数,这个参数可以是<c:forEach>标签的items属性支持的任何类型,包括任意类型的数组java.util.Collectionjava.util.Iteratorjava.util.Enumerationjava.util.Map等类的实例对象和字符串。

  • 如果fn:length函数的参数为null或者是元素个数为0的集合或数组对象,则函数返回0;如果参数是空字符串,则函数返回0


* fn:split函数*
  • fn:split函数以指定字符串作为分隔符,将一个字符串分割成字符串数组并返回这个字符串数组。

  • fn:split函数接收两个字符串类型的参数,第一个参数表示要分割的字符串,第二个参数表示作为分隔符的字符串。

  • 例如,fn:split(“www.it315.org”, “.”)[1]的返回值为字符串“it315”。


fn:join函数
  • fn:join函数以一个字符串作为分隔符,将一个字符串数组中的所有元素合并为一个字符串并返回合并后的结果字符串。
  • fn:join函数接收两个参数,第一个参数是要操作的字符串数组,第二个参数是作为分隔符的字符串。
  • 如果fn:join函数的第二个参数是空字符串,则fn:join函数的返回值直接将元素连接起来。例如:
    • 假设stringArray是保存在Web域中的一个属性,它表示一个值为{“www”,”it315”,”org”}的字符串数组,则fn:join(stringArray, “.”)返回字符串“www.it315.org”
    • fn:join(fn:split(“www,it315,org”, “,”), “.”) 的返回值为字符串“www.it315.org”


fn:indexOf函数
  • fn:indexOf函数返回指定字符串在一个字符串中第一次出现的索引值,返回值为int类型
  • fn:indexOf函数接收两个字符串类型的参数,如果第一个参数字符串中包含第二个参数字符串,那么,不管第二个参数字符串在第一个参数字符串中出现几次,fn:indexOf函数总是返回第一次出现的索引值;如果第一个参数中不包含第二个参数,则fn:indexOf函数返回-1。如果第二个参数为空字符串,则fn:indexOf函数总是返回0。例如:
    • fn:indexOf(“www.it315.org”,”t3”) 的返回值为5


fn:contains函数
  • fn:contains函数检测一个字符串中是否包含指定的字符串,返回值为布尔类型
  • fn:contains函数在比较两个字符串是否相等时是大小写敏感的。
  • fn:contains函数接收两个字符串类型的参数,如果第一个参数字符串中包含第二个参数字符串,则fn:contains函数返回true,否则返回false。如果第二个参数的值为空字符串,则fn:contains函数总是返回true。实际上,fn:contains(string, substring)等价于fn:indexOf(string, substring) != -1。
  • 忽略大小的EL函数:fn:containsIgnoreCase


fn:startsWith函数
  • fn:startsWith函数用于检测一个字符串是否是以指定字符串开始的,返回值为布尔类型。

  • fn:startsWith函数接收两个字符串类型的参数,如果第一个参数字符串以第二个参数字符串开始,则函数返回true,否则函数返回false。如果第二个参数为空字符串,则fn:startsWith函数总是返回true。例如:

  • fn:startsWith(“www.it315.org”,”it315”)的返回值为false

  • 与之对应的EL函数:fn:endsWith


fn:substring函数
  • fn:substring函数用于截取一个字符串的子字符串并返回截取到的子字符串。
  • fn:substring函数接收三个参数,第一个参数是用于指定要操作的源字符串,第二个参数是用于指定截取子字符串开始的索引值,第三个参数是用于指定截取子字符串结束的索引值,第二个参数和第三个参数都是int类型,其值都从0开始。例如:
    • fn:substring(“www.it315.org”, 4, 9) 的返回值为字符串“it315”


fn:substringAfter函数
  • fn:substringAfter函数用于截取并返回一个字符串中的指定子字符串第一次出现之后的子字符串。
  • fn:substringAfter函数接收两个字符串类型的参数,第一个参数表示要操作的源字符串,第二个参数表示指定的子字符串,例如:

  • fn:substringAfter(“www.it315.org”, “.”)的返回值为字符串“it315.org”。

  • 与之对应的EL函数为:fn:substringBefore


自定义EL函数
  • EL自定义函数开发与应用包括以下三个步骤:
    • 编写一个Java类,方法必须是静态方法
    • WEB-INF目录下创建一个tld的文件。或WEB-INF目录下的除了classes和lib目录之外的任意子目录中。
      • VersionJspversion一定要选择2.0
      • 设置uri和shortname。
      • 如果没有标签的提示,复制xsi : schemaLocation中的地址http://java.sun.com/xml/ns/j2ee ,与后面的内容进行合并即可。
      • TLD文件中的<uri> 元素用指定该TLD文件的URI,在JSP文件中需要通过这个URI来引入该标签库描述文件。
    • 编写标签库描述符(tld)文件,在tld文件中配置自定义函数。
      • 使用function标签配置自定义函数
      • 使用name标签配置方法名(可以任意),指定EL自定义函数的名称。
      • 使用function-class标签配置类的全路径,指定完整的Java类名
      • 使用function-signature标签配置返回值类型(中间有空格)方法名称(参数类型)。指定Java类中的静态方法的签名,方法签名必须指明方法的返回值类型及各个参数的类型,各个参数之间用逗号分隔。
    • 在JSP页面中导入和使用自定义函数
    <!-- 配置自定义的EL函数 -->
     <function>
        <!-- 配置方法名称 -->
        <name>sayHi</name>
        <!-- 方法所在的类 -->
        <function-class>cn.itcast.el.ElDemo1</function-class>
        <!-- 配置方法的签名 -->
        <function-signature>java.lang.String sayHello(java.lang.String)</function-signature>
     </function>

//eldemo.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<%@ taglib uri="http://miaolu.test/myel" prefix="myel" %>    
<!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>
    ${fn:length("abcdefghhijklmn") }

    ${fn:toUpperCase("abcdefg") }

    ${myel:sayHi("小泽")}

</body>
</html>


//ELDemo.java
package test.el;

public class ELDemo {
    public static String sayHello(String name){
        return "hello"+name;
    }
}



自定义标签

  • 自定义标签主要用于移除Jsp页面中的java代码,提高代码的复用性。
  • 使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤:
    • 编写一个实现Tag接口Java类(标签处理器类)
    • 编写标签库描述符(tld)文件,在tld文件中对标签处理器类描述成一个标签


实现SimpleTag接口
  • 编写一个类,继承SimpleTagSupport类。
  • 重写5个方法

    • setJspContext 传入pageContext对象
    • setParent 传入父标签对象
    • setJspBody 传入标签体缓存对象 (封装了标签体内容)
    • doTag (执行标签,在该方法中编写标签代码逻辑)
    • 在setJspBody方法中传入对象 JspFragment ,该对象封装了 标签体内容,控制标签体内容输出
    • 最重要方法 invoke(Writer out) 意义将标签体内容输出到指定字符输出流中
    • 注意:在 简单标签库中 <bodyContent> 不能写JSP,而必须写scriptless
  • SimpleTag方法介绍

    • setJspContext方法
      • 用于把JSP页面的pageContext对象传递给标签处理器对象
    • setParent方法
      • 用于把父标签处理器对象传递给当前标签处理器对象
    • getParent方法
      • 用于获得当前标签父标签处理器对象
    • setJspBody方法
      • 用于把代表标签体的JspFragment对象传递给标签处理器对象
    • doTag方法
      • 用于完成所有的标签逻辑,包括输出迭代修改标签体内容等。在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。


SimpleTag接口方法的执行顺序
  • 当web容器开始执行标签时,会调用如下方法完成标签的初始化
    • WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象
    • WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。
    • 如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
    • 如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。
  • 执行标签时:
    • 容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。

  • JspFragment类

    • javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段,这段JSP片段中不能包含JSP脚本元素
    • WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象。JspFragment类中只定义了两个方法,如下所示:
    • getJspContext方法
      • 用于返回代表调用页面的JspContext对象 pageContext
    • public abstract void invoke(java.io.Writer?out) – 输出标签体内容
      • 用于执行**JspFragment对象所代表的**JSP代码片段
    • 参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)
  • invoke方法详解

  • JspFragment.invoke方法是JspFragment最重要的方法,利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出。例如:
    • 在标签处理器中如果没有调用*JspFragment.invoke方法,其结果就相当于忽略标签体内容*;
    • 在标签处理器中重复调用*JspFragment.invoke方法,则标签体内容将会被重复执行*;
    • 若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。


自定义标签快速入门的步骤(没有标签体)
  • 需求:自定义标签<myc:print>在页面中输出hello

  • 编写标签类

    • 编写一个类,继承SimpleTagSuppot类
    • 重写两个方法,doTag()setJspContext(JspContext pc)
    • JspContext对象可以获取out对象向外输出内容
  • 提供tld文件进行配置

    • 通过<tag>标签配置自定义标签
    • 配置标签名称<name>print</name>
    • 配置标签的类<tag-class>xxx.xxx.xxx</tag-class>
    • 配置标签体的内容<body-content>empty</body-content>
    <!-- 配置自定义标签 -->
     <tag>
        <!-- 配置标签名称 -->
        <name>print</name>
        <!-- 配置标签的类 -->
        <tag-class>cn.itcast.tag.TagDemo1</tag-class>
        <!-- 配置标签主体 -->
        <body-content>empty</body-content>
     </tag>


  • 在JSP的页面中引入该标签库
    • <%@ taglib uri="http://www.itcast.cn/1110/myc" prefix="myc" %>


带有标签主体的标签
  • 需求:自定义标签<myc:out>在页面中输出内容
  • 编写标签类

    • 编写一个类,继承SimpleTagSuppot类。
    • 重写两个方法,doTag()和setJspContext(JspContext pc)
    • 在doTag()中通过getJspBody()获取JspFragment标签体,调用invoke(null)
  • 提供tld文件进行配置

    • 通过<tag>标签配置自定义标签
    • 配置标签名称<name>out</name>
    • 配置标签的类<tag-class>xxx.xxx.xxx</tag-class>
    • 配置标签体的内容<body-content>scriptless</body-content>
  • 在JSP的页面中引入该标签库

    <!-- 配置自定义标签 -->
     <tag>
        <!-- 配置标签名称 -->
        <name>out</name>
        <!-- 配置标签的类 -->
        <tag-class>cn.itcast.tag.TagDemo2</tag-class>
        <!-- 配置标签主体 -->
        <body-content>scriptless</body-content>
     </tag>
  • <body-content>元素的可选值有:
    • empty:不能有标签体内容。
    • scriptless:标签体内容不能是Java代码段,但可以是EL、JSTL等;
    • JSP:标签体内容可以是任何东西:EL、JSTL、<%=%><%%>,以及html;但不建议使用Java代码段,SimpleTag已经不再支持使用<body-content>JSP</body-content>
    • tagdependent:标签体内容不做运算,由标签处理类自行处理,无论标签体内容是EL、JSP、JSTL,都不会做运算。
带有属性的标签
  • 需求:自定义标签<myc:if>在页面中输出内容

    • 编写标签类

      • 编写一个类,继承SimpleTagSuppot类。
      • 提供页面的属性,设置成boolean类型。并且提供set方法,页面的属性与类中的属性名称必须相同。
      • 重写doTag()方法,判断属性是否为true,通过getJspBody()获取JspFragment标签体,调用invoke(null)
    • 提供tld文件进行配置

      • 通过<tag>标签配置自定义标签
      • 配置标签名称<name>if</name>
      • 配置标签的类<tag-class>xxx.xxx.xxx</tag-class>
      • 配置标签体的内容<body-content>scriptless</body-content>
      • 配置属性<attribute>在属性中配置其他信息</attribute>
  • 编写类,继承SimpleTagSupport。

  • 重写doTag()
  • 编写一个属性,属性必须和标签中的属性是相同
  • 提供set方法
  • 获取标签主体对象
    JspFragment jf = getJspBody();
    jf.invoke(null);
  • 配置
    <!-- 配置自定义标签 -->
     <tag>
        <!-- 配置标签名称 -->
        <name>if</name>
        <!-- 配置标签的类 -->
        <tag-class>cn.itcast.tag.TagDemo3</tag-class>
        <!-- 配置标签主体 -->
        <body-content>scriptless</body-content>
        <!-- 配置属性 -->
        <attribute>
            <!-- 配置属性名称 -->
            <name>test</name>
            <!-- 属性是否是必须的 -->
            <required>true</required>
            <!-- 是否支持EL表达式 -->
            <rtexprvalue>true</rtexprvalue>
            <!-- 属性的类型 -->
            <type>boolean</type>
        </attribute>
     </tag>
attribute的配置
  • 配置属性名称
    • <name>test</name>
  • 属性是否是必须的
    • <required>true</required>
  • 配置是否支持EL表达式
    • < rtexprvalue>true</ rtexprvalue>
  • 配置属性的类型

    • <type>boolean</type>
  • 在TLD中描述标签属性 attribute

  • <tag>元素的<attribute>子元素用于描述自定义

  • 标签的一个属性,自定义标签所具有的每个属性
  • 都要对应一个<attribute>元素 。
<attribute>
    <description>description</description>
    <name>aaaa</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
    <type>ObjectType</type>

</attribute>


JSP开发的模式(MVC)

  • SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式
  • JSP+JavaBean模式适合开发业务逻辑不太复杂的web应用程序,这种模式下,JavaBean用于封装业务数据,JSP即负责处理用户请求,又显示数据。
  • Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。 Servlet+JSP、JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。

  • 第一种JSP+JavaBean设计模式

    • JSP 完成逻辑上的处理和显示


  • 第二种 Servlet+JSP+JavaBean 设计模式
    • Servlet:控制显示哪个JSP页面给用户、调用哪个Javabean
    • JSP:响应用户请求,把结果数据展现给用户
    • JavaBean : 对数据库的数据的存取,复杂的业务功能和逻辑处理

  • 根据此模式,servlet 处理数据存取和导航流, JSP 处理表现。此模式 使Java 工程师和HTML 设计者分别工作于它们所擅长和负责的部分。此模式 应用的一部分发生改变并不强求其他部分也跟着发生改变。HTML 开发人员可以改变程序的外观和感觉,并不需要改变后端servlet 的工作方式。

MVC设计模式
  • Model-View-Controller的简称
  • MVC是一种设计模式
  • 把应用程序分成三个核心模块
    • 模型、视图、控制器

MVC案例的编写
  • 数据库:暂时先使用XML作为数据库
  • 技术
    • Servlet + JavaBean + JSP
    • 封装数据
      • BeanUtils
    • 在JSP显示
      • JSTL + JSP
    • 解析XML
      • DOM4J解析XML
  • 环境准备

    • 新建web项目,导入jar包
    • 创建数据库,在磁盘上创建一个user.xml文件
  • 完成注册的需求

    • 注册表单(案例)
    • 数据库(没有)

      • 使用xml来代替。
    • 架构
      Servlet + JSP + JavaBean

    • 技术

      • 解析XML使用DOM4J技术
      • Servlet技术
      • BeanUtils技术
      • JSTL+EL表达式
    • 创建新的项目
    • 导入jar包
    • 创建包结构
  • 开发的步骤

    • 编写注册的页面,
      用户名,密码,确认密码,别名,邮箱,验证码
    • 先完成数据的校验 onsubmit()
      • 都不能为空,密码和确认密码一致
      • 邮箱格式正确(正则表达式)
    • 发送请求,请求Servlet,接收数据,封装,处理数据
    • 显示到JSP上。
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值