Java Web(六) JSP

如今的Java Web开发已经不多使用JSP脚本了,业务逻辑都交给Servlet处理,JSP只负责显示视图,因此接下来的内容就对JSP脚本不作叙述了。。。html

JSP概述

JSP全名为Java Server Page,是为了简化Servlet的工做而出现的替代品。JSP是一种基于文本的程序,其特色是HTML与Java程序共同存在。执行时JSP会被Tomcat自动编译,编译后的JSP和HttpServlet同样,都是javax.servlet.Servlet接口的子类,所以JSP是另外一种形式的Servlet。java

JSP工做原理

JSP是一种Servlet,可是与HttpServlet的工做方式不太同样。HttpServlet是先由源代码编译为class文件后部署到服务器下的,先编译后部署。而JSP则是先部署源代码后编译为class文件的,先部署后编译。JSP会在客户端第一次请求JSP文件时被编译为HttpJspPage类(接口Servlet的一个子类)。该类会被服务器临时存放在服务器工做目录上面。之后客户端访问这个JSP时,服务器再也不编译这个JSP文件,而是直接调用已有的class文件进行响应。因此客户端第一次请求时会感受比较慢,由于JSP须要编译,而以后速度就快多了。但若是JSP被修改,或者class文件被删除,Tomcat可以检测到,Tomcat会在下一次请求时从新编译JSP,而不须要重启Tomcat。(这种自动检测功能是默认的,能够在web.xml中关闭)web

JSP生命周期

JSP会被容器转译为Servlet源代码,自动编译为.class文件,载入.class文件,而后生成Servlet对象,如图:数组

  img

JSP也是Servlet,运行时只有一个实例。和Servlet同样,JSP实例化,销毁时也会调用Servlet的init()方法与destroy()方法。另外JSP还有本身的初始化方法与销毁方法_jspInit()与_jspDestroy()。Servlet的init方法和destory()方法会相应的调用_jspInit()与_jspDestroy()方法。注意到这两个方法名称前有个下划线,表示这些方法时由容器转译时维护,因此你不能重写这些方法。若是你想对JSP作些初始化工做或收尾工做,你能够重写jspInit()方法或jspDestory方法。浏览器

JSP指令

JSP指令的主要目的,在于指示容器将JSP转译为Servlet源代码时,一些必须遵照的信息,JSP指令的语法以下所示:缓存

<%@ 指示类型 [属性="值"]* %>安全

在JSP中有三种常见的指令:page、include 与 taglib。page指令告知容器如何转译目前的JSP网页。include指令告知容器将别的JSP页面包括进来进行转译。taglib指令告知容器如何转译这个页面中的标签库。服务器

  1. page指令cookie

    page指令是最经常使用的指令,能够声明JSP页面的属性等。JSP指令的多个属性能够写在一个page指令里,也能够写在多个page指令里。每一个属性只能出现一次,不然出现编译错误。(import属性除外)。session

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

    page指令的常见的属性:

    • language:指明解释该JSP时采用的语言。通常为Java语言。默认为Java语言。
    • import:指明编译该JSP时继承哪一个类。
    • session:指明该JSP是否内置Session对象。true则内置,false不内置。默认为true。
    • autoFlush:是否容许缓存。若是为true,则使用out.println()等方法输出字符不会马上到达服务器,而是暂时存在缓存里,缓存满时或者程序执行完毕或者执行out.flush()操做时才到客户端。默认为true。
    • buffer:指定缓存大小。当autoFlush设为true时才有效,例如:<%@ page buffer="10kb" %>。
    • isThreadSafe:指定是否线程安全。若是为true,则运行对个线程同时运行该JSP,不然只运行一个线程,其他线程等待。默认为false。
    • isErrorPage:指定该页面是否为错误处理页面。若是为true,则该JSP内置有一个Exception对象,可直接使用,不然没有,默认为false。
    • errorPage:指明一个错误显示页面。若是该JSP程序抛出了一个未捕捉的异常,则转到errorPage指定的页面。errorPage指定的页面一般是isErrorPage属性为true,且内置的Exception对象为未捕捉的异常。
    • contentType:客户端浏览器根据属性判断文档类型。
    • info:指明JSP的信息。该信息能够经过Servlet.getServletInfo()方法获得。
    • trimDirectiveWhitespaces:是否去掉指令先后的空白字符。默认为fasle。
  2. include指令

    include指令比较简单,只有一种形式:<%@ inlcude file="relativeURL" %>。relativeURL是另外一个JSP文件或HTML文件的路径。例如,网站内全部网站均有一个统一风格的导航栏head.jsp与页脚版权的foot.jsp,就可使用include指令。include指令能够实现页面的区块化。

    <%@include file="head.jsp"%>
    <h2>Hello World</h2>
    <%@include file="foot.jsp"%>
  3. taglib

    JSP支持标签技术,使用标签功能可以实现视图代码重用,不多量的代码就可以实现很复杂的显示效果。taglib指令用来指明JSP页面内使用的JSP标签库。taglib指令有两个属性,uri为类库的地址,prefix为便签的前缀。

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>book</title>
    </head>
    <body>
    <c:forEach var="book" items="books">
        <h2>${book.name}</h2>
    </c:forEach>
    </body>
    </html>

JSP九大隐式对象

Servlet和JSP中输出数据都须要使用out对象。Servlet中的out对象是经过response.getWriter()获得的。而JSP中没有定义out对象,却能够直接使用。这是由于out是JSP的内置对象。JSP中一共内置了9个内置对象,分别为out、request、response、config、session、application、page、pageContent、exception。

  • out为javax.servlet.jsp.JspWriter类的实例、服务器向客户端输出的字符内容能够经过out对象输出。
  • request为javax.servlet.ServletRequest类的实例,表明着客户端的请求。
  • response为javax.servlet.ServletResponse类的实例,表明着服务器的响应。
  • config是java.servlet.ServletConfig类的实例。ServletConfig封装了配置在web.xml中初始化JSP的参数。
  • session是java.servlet.http.HttpSession的实例。Session是记录客户会话状态的机制。
  • application是java.servlet.ServletContext的实例。application封装了JSP所在的Web应用程序的信息。
  • page是java.servlet.jsp.HttpJspPage类的实例、page对象表明当前JSP页面,是JSP编译后的Servlet类的对象。至关于java语言中的this。
  • pageContext为java.servlet.jsp.PageContext的实例,PageContext对象表明当前页面编译后的内容。经过PageContext对象可以获得JSP中的资源。  
  • exception为java.lang.Exception类的对象,Exception对象封装了JSP抛出的异常,要使用exception隐藏对象,须要设置<%@ isErrorPage="true" %>。exception一般用来处理错误页面。

EL表达式

JSP可使用EL表达式从page、request、session、application域中获取属性,还能够进行简单的运算和判断,这样能够大大减小JSP页面上Scriptlet的使用。

EL表达式的11个隐式对象

  • pageContext对应于JSP页面中的pageContext对象。
  • pageScope表明page域中保存属性的Map对象。
  • requestScope表明request域中保存属性的Map对象。
  • sessionScope表明session域中保寸属性的Map对象。
  • applicationScope表明application域中保存属性的Map对象。
  • param表明保持了全部请求参数的Map对象。
  • paramValues表明保存了全部请求参数的Map对象,他对于某个请求参数,返回的是一个String类型的数组。
  • header表明一个保存类全部头字段的Map对象。
  • headerValues表明一个保存类全部头字段的Map对象,返回String类型数组。
  • cookie表示类一个保存类全部cookie的Map对象。
  • initParam表示一个保存了全部Web应用初始化参数的Map对象。
  1. pageContext对象

    EL表达式中的pageContext隐式对象与JSP页面中的pageContext对象相对应,EL表达式能够经过pageContext隐式对象访问其它JSP隐式对象,如访问request、response对象属性时,可使用表达式$ {pageContext.response.contentType}等。

  2. 表明特定域属性的隐式对象(共4个)

    EL表达式中的pageScope、requestScope、sessionScope和applicationScope四个隐式对象分别用于访问JSP页面的page、request、session、application四个域中的属性。在EL表达式中也能够不使用这些隐式对象来指定查找域,而是直接引用这些域中的属性名称。例如,表达式$ {userName}就会在page、request、session、application这四个做用域内按顺序依次查找userName属性,直到找到为止。

  3. 表明请求参数的隐式对象(2个)

    EL表达式中的隐式对象param和paramValues用于获取客户端访问JSP页面时传递的请求参数的值,因为HTTP协议容许使用一个请求参数名出现屡次,即一个请求参数可能会有多个值,因此,EL表达式提供了param和paramValues这两个隐式对象来分别获取请求参数的某个值和全部值。Param隐式对象用于返回一个请求参数的某个值,若是同一个请求参数有多个值,则返回第一个参数的值。paramValues隐式对象用于返回一个请求参数的全部值,返回结果为该参数的全部值组成的字符串数组,例如表达式${paramValues.username[0]}用于返回数组中第一个元素的值。

  4. 表明HTTP请求消息的隐式对象(2个)

    EL表达式中的隐式对象header和headerValues用于获取客户端访问JSP页面时传递的请求头字段的值。因为HTTP协议容许一些请求头字段出现屡次,即一个请求头字段可能会有多个值,因此,EL表达式提供了header和headerValues两个隐式对象分别用于获取请求头字段的某个值和全部值。header隐式对象返回一个请求头字段的某个值,若是同一个请求头字段有多个值,则返回第一个值,例如,使用表达式${header.referer}能够很是方便的获取referer请求头字段的值。headerValues隐式对象用于返回一个请求头字段全部值组成的字符串数组。

  5. cookie隐式对象

    EL表达式中的隐式对象cookie是一个表明全部Cookie信息的Map集合,Map集合中元素的关键字为各个Cookie的名称,值则为对应的Cookie对象。使用cookie隐式对象能够访问某个Cookie对象,这些Cookie对象则是经过调用HTTPServletRequest.getCookies()方法获得的,若是多个Cookie共用一个名称,则返回Cookie对象数组中的第一个Cookie对象。例如,要访问一个名为userName的Cookie对象,可使用表达式${cookie.userName}。

  6. initParam隐式对象

    EL表达式中的initParam是一个表明Web应用程序中的全部初始化参数的Map对象,每一个初始化参数的值是ServletContext.getInitParameter(String name)方法返回的字符串。

EL表达式获取属性

EL表达式默认是以page、request、session、application的顺序来寻找EL中指定的属性的。EL经过[ ]运算符和 . 运算符来获取指定的属性。

  • 若是使用 . 运算符,则左边能够是JavaBean、Map对象或自定义对象。
  • 若是使用[ ]运算符,则左边能够是JavaBean、Map、数组、List对象或自定义对象。

简单来讲就是有下标的使用[ ],没下标的都用 。

${book.name}

EL表达式运算

EL表达式支持简单的运算,包括加(+)、减(-)、乘(*)、除(/或者div)、取余(%或者mod)、三目运算符等,例如:

${1 + 2}<!--输出3-->
${1 == 2 ? 3 : 4}<!--输出4-->

EL表达式支持简单的比较运算,包括大于(> 或 gt),小于(< 或 lt),等于(== 或 eq),不等于(!= 或 ne),大于等于(>= 或 ge),小于等于(<= 或 le)等,例如:

${1 < 2}<!--输出true-->
${5 >= 2}<!--输出false-->

EL表达式还支持逻辑运算,且(&& 或 and),或(|| 或 or),否(! 或 not),例如:

${1 < 2 && 5 >= 2}<!--输出false-->

还能够结合JSTL标签库判断域中某值是否为空,而后能够在界面上显示不一样的信息,例如:

<c:if test="${empty user}">
    <h3>请先登入</h3>
</c:if>
<c:if test="${not empty user}">
    <h3>${user.name},欢迎您</h3>
</c:if>

自定义EL函数

支持自定义EL函数的功能,若是咱们想使用EL表达式链接字符串,你可能会想到使用${ str1 + str2 },可是这是错的,由于EL表达式中的 + 只表明加法,要实现该功能,你能够自定义EL函数。

第一步:编写类,这个函数必须是公开的(public)且是静态方法(static),例如:

package Utils;

public class Util {
    public static String strcat(String str1, String str2) {
        return str1 + str2;
    }
}

第二步:编写标签程序库描述(Tag Liabrary Descriptor)文件,这个文件是一个XML文件。

<?xml version="1.0" encoding="utf-8"?>

<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.0</tlib-version>
    <short-name>util</short-name>
    <uri>http://kindleheart.com/util</uri>
    <function>
        <name>strcat</name>
        <function-class>Utils.Util</function-class>
        <function-signature>
            java.lang.String strcat(java.lang.String,java.lang.String)
        </function-signature>
    </function>
</taglib>

第三步:直接使用该标签,例如:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="util" uri="http://kindleheart.com/util" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>自定义EL函数</title>
</head>
<body>
<%
    String str1 = "今每天气";
    String str2 = "真好";
    request.setAttribute("str1", str1);
    request.setAttribute("str2", str2);
%>
${util:strcat(requestScope.str1, requestScope.str2)}
</body>
</html>

网页显示结果:

    

相关文章
相关标签/搜索