如今的Java Web开发已经不多使用JSP脚本了,业务逻辑都交给Servlet处理,JSP只负责显示视图,因此接下来的内容就对JSP脚本不作叙述了。。。html
JSP全名为Java Server Page,是为了简化Servlet的工做而出现的替代品。JSP是一种基于文本的程序,其特色是HTML与Java程序共同存在。执行时JSP会被Tomcat自动编译,编译后的JSP和HttpServlet同样,都是javax.servlet.Servlet接口的子类,所以JSP是另外一种形式的Servlet。java
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会被容器转译为Servlet源代码,自动编译为.class文件,载入.class文件,而后生成Servlet对象,如图:数组
JSP也是Servlet,运行时只有一个实例。和Servlet同样,JSP实例化,销毁时也会调用Servlet的init()方法与destroy()方法。另外JSP还有本身的初始化方法与销毁方法_jspInit()与_jspDestroy()。Servlet的init方法和destory()方法会相应的调用_jspInit()与_jspDestroy()方法。注意到这两个方法名称前有个下划线,表示这些方法时由容器转译时维护,因此你不能重写这些方法。若是你想对JSP作些初始化工做或收尾工做,你能够重写jspInit()方法或jspDestory方法。浏览器
JSP指令的主要目的,在于指示容器将JSP转译为Servlet源代码时,一些必须遵照的信息,JSP指令的语法以下所示:缓存
<%@ 指示类型 [属性="值"]* %>安全
在JSP中有三种常见的指令:page、include 与 taglib。page指令告知容器如何转译目前的JSP网页。include指令告知容器将别的JSP页面包括进来进行转译。taglib指令告知容器如何转译这个页面中的标签库。服务器
page指令cookie
page指令是最经常使用的指令,能够声明JSP页面的属性等。JSP指令的多个属性能够写在一个page指令里,也能够写在多个page指令里。每一个属性只能出现一次,不然出现编译错误。(import属性除外)。session
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
page指令的常见的属性:
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"%>
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>
Servlet和JSP中输出数据都须要使用out对象。Servlet中的out对象是经过response.getWriter()获得的。而JSP中没有定义out对象,却能够直接使用。这是由于out是JSP的内置对象。JSP中一共内置了9个内置对象,分别为out、request、response、config、session、application、page、pageContent、exception。
JSP可使用EL表达式从page、request、session、application域中获取属性,还能够进行简单的运算和判断,这样能够大大减小JSP页面上Scriptlet的使用。
pageContext对象
EL表达式中的pageContext隐式对象与JSP页面中的pageContext对象相对应,EL表达式能够经过pageContext隐式对象访问其它JSP隐式对象,如访问request、response对象属性时,可使用表达式$ {pageContext.response.contentType}等。
表明特定域属性的隐式对象(共4个)
EL表达式中的pageScope、requestScope、sessionScope和applicationScope四个隐式对象分别用于访问JSP页面的page、request、session、application四个域中的属性。在EL表达式中也能够不使用这些隐式对象来指定查找域,而是直接引用这些域中的属性名称。例如,表达式$ {userName}就会在page、request、session、application这四个做用域内按顺序依次查找userName属性,直到找到为止。
表明请求参数的隐式对象(2个)
EL表达式中的隐式对象param和paramValues用于获取客户端访问JSP页面时传递的请求参数的值,因为HTTP协议容许使用一个请求参数名出现屡次,即一个请求参数可能会有多个值,因此,EL表达式提供了param和paramValues这两个隐式对象来分别获取请求参数的某个值和全部值。Param隐式对象用于返回一个请求参数的某个值,若是同一个请求参数有多个值,则返回第一个参数的值。paramValues隐式对象用于返回一个请求参数的全部值,返回结果为该参数的全部值组成的字符串数组,例如表达式${paramValues.username[0]}用于返回数组中第一个元素的值。
表明HTTP请求消息的隐式对象(2个)
EL表达式中的隐式对象header和headerValues用于获取客户端访问JSP页面时传递的请求头字段的值。因为HTTP协议容许一些请求头字段出现屡次,即一个请求头字段可能会有多个值,因此,EL表达式提供了header和headerValues两个隐式对象分别用于获取请求头字段的某个值和全部值。header隐式对象返回一个请求头字段的某个值,若是同一个请求头字段有多个值,则返回第一个值,例如,使用表达式${header.referer}能够很是方便的获取referer请求头字段的值。headerValues隐式对象用于返回一个请求头字段全部值组成的字符串数组。
cookie隐式对象
EL表达式中的隐式对象cookie是一个表明全部Cookie信息的Map集合,Map集合中元素的关键字为各个Cookie的名称,值则为对应的Cookie对象。使用cookie隐式对象能够访问某个Cookie对象,这些Cookie对象则是经过调用HTTPServletRequest.getCookies()方法获得的,若是多个Cookie共用一个名称,则返回Cookie对象数组中的第一个Cookie对象。例如,要访问一个名为userName的Cookie对象,可使用表达式${cookie.userName}。
initParam隐式对象
EL表达式中的initParam是一个表明Web应用程序中的全部初始化参数的Map对象,每一个初始化参数的值是ServletContext.getInitParameter(String name)方法返回的字符串。
EL表达式默认是以page、request、session、application的顺序来寻找EL中指定的属性的。EL经过[ ]运算符和 . 运算符来获取指定的属性。
简单来讲就是有下标的使用[ ],没下标的都用 。
${book.name}
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表达式链接字符串,你可能会想到使用${ 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>
网页显示结果: