3.1、JSP概述
Jsp页面实在jsp容器中运行的。Servlet容器一般也是JSP容器。例如,Tomcat就是一个Servlet/JSP容器。
第一次请求一个jsp页面时,Servlet/JSP容器要做两件事情:
1、将JSP页面转换成一个JSP页面实现类,这是一个实现javax.servlet.jsp.JspPage接口或其子接口javax.servlet.jsp.HttpjspPage的Java类,JspPage是javax.servlet.Servlet的子接口,这样就会使每个jsp页面都成为一个Servlet。
2、如果转换成功,Servlet/JSP容器将会编译Servlet类。
3.2、备注
Jsp页面可以使用两种备注:
1、jsp备注。说明该页面的作用
2、HTML/XHTML备注。这些将被发送到浏览器。
JSP备注以<%--开头,以--%>结束。例如,下面就是一个JSP备注:
<%-- retrieve products to display --%>
JSP备注不会被发送到浏览器,也不能进行嵌套。
HTML/XHTML备注不是由容器进行处理,而是被发送到浏览器。HTML/XHTML备注的用途之一是标识JSP页面:
<!-- this is /jsp/store/displayProducts.jspf -->
在处理带有许多JSP片段的应用程序时,这个特别有用。开发者通过查看浏览器的HTML源代码,可以轻松查出某个HTML代码部分生成了哪个JSP页面或者哪个片段。
3.3、隐式对象
Jsp中存在9个隐式对象:request、response、out、session、application、config、pageContext、page、Exception。
3.4、指令
指令是第一种jsp句法元素,其指示jsp转换器应该如何将某个jsp页面转换成Servlet的命令。最重要的是这两个:page和include。
3.4.1、page指令
Page指令的语法如下:
<%@ page attrubute1=”value1” attribute=”value2” ...%>
@和page之间的空格是可选的,attribute1、attribute2等都是page指令的属性。下面是page指令的属性列表:
import。指定要导入的一种或多种java类型,供本页的java代码所用。例如:import=”java.util.List”。
session。值为true时,表示这个页面参与session管理;值为false时,表示不参与session管理。默认值为true,意味着如果之前还没有javax.servlet.http.HttpSession实例,那么调用JSP页面将始终会创建一个。
buffer。指定隐式对象out的缓冲区大小,以千字节为单位。
autoFlush。默认值为true,表示当缓冲区满时,杯缓存的输出应该自动刷新。值为false时,表示只有在调用隐式对象response的flush方法时,才进行刷新缓冲区。因此,当缓冲区溢出时会抛出一个异常。
isThreadSafe。表示页面中实现的线程安全级别。建议JSP的作者不要使用这个属性,因为它会产生一个包涵不建议使用的代码的Servlet。
Info。指定所生成Servlet的getServletInfo方法返回值。
errorPage、表示负责处理该页面可能出现的错误的页面。
isErrorPage。表明这个页面是否负责处理错误。
contentType。指定该页面隐式对象response的内容类型,其默认值为text/html。
pageEncoding。指定该页面的字符编码,其默认值为ISO-8859-1.
isELIgnored。表名是否忽略EL表达式。EL是Expression Language的缩写。
Language。指定该页面使用的脚本语言,其默认值为java。
Extends。指定这个JSP页面的实现类必须扩展的超类。该属性很少使用,使用时应该特别小心。
deferredSyntaxAllowedAsLiteral。指明是否允许用字符序列#{做为该页面和编译单元的String字面值,其默认值为false。#{很重要,因为它在EL表达式中是一个特殊的字符序列。
trimDirectiveWhitespaces。表明是否从输出内容中删除只包含空格的模版文本,其默认值为false,也就是说,不删除空格。
Page指令也可以多次出现。但是,在多个page指令中多次出现的同一个属性,它的值必须一致,只有import属性例外。放在多个page指令中的import属性,其效果可以累积。例如,下面的page指令将会同时导入java.util.ArrayList和java.io.File
<% @page import=”java.util.ArrayList”%>
<% @page import=”java.io.File”%>
其结果与下面的这行代码相同:
<% @page import=”java.util.ArrayList, java.util.Date”%>
下面再举个例子。这个page指令将session属性值设为false,并将页面的缓冲区容量设为16kb
<% @page session=”false” buffer=”16kb”%>
3.4.2、include指令
Include指令的语法如下:
<%@ include file=”url”%>
此处@和include之间的空格是可选的,并且url是表示一个include文件的相对路径,如果url以一个正斜线(/)开头,那么其在服务器中就会杯解读成是一条绝对路径。如果不是以正斜线开头,则被解读为是相对于当前JSP页面的路径。
按照规范,include文件的扩展名应为jspf,表示为JSP fragment。如今。JSP fragment也称作JSP segmen,只是为了保持一致,仍然用jspf做为扩展名。
3.5、脚本元素
第二种JSP句法元素是脚本元素,它将java代码合并成一个JSP页面。脚本元素有3种类型:Scriplet、声明及表达式。
3.5.1、Scriptlet
Scriptlet是一个java代码块,它以<%开头,以%>结束。
3.5.2、表达式
表达式的运算结果会杯填入隐式对象out的print方法中。表达式以<%开头,并以%>结束。例如,下面就是一个表达式:
Today is <%=java.util.Calendar.getInstance().getTime()%>
注意:表达式后面不需要用分号。
这个表达式和下面的Scriplet是一样的
<%
Out.print(java.util.Calendar.getInstance().getTime()) ;
%>
3.5.3、声明
声明能够在JSP页面中使用变量和方法。声明要用<%!和%>包起来。下面就声明了一个方法。
<%!
public String getTodaysDate(){
return new java.util.Date() ;
}
%>
声明可以放在jsp页面中的任何位置,并且同一个页面中可以有多个声明。
我们可以利用声明覆盖实现类中的init和destroy方法。覆盖init,要声明一个jspInit方法;覆盖destroy,要声明一个jspDestroy方法。例如:
<%!
Public void jspInit(){
System.out.println(“jspInit...”) ;
}
Public void jspDestroy(){
System.out.println(“jspDestroy...”) ;
}
%>
3.5.4、关闭脚本元素
随着jsp2.0中EL的发展,建议做法是利用EL来访问服务器的对象,而不是在JSP页面中编写java代码。为此,原本开启的jsp2.0脚本元素,可以通过在部署描述符的<jsp-property-group>中定义一个scripting-invalid元素,将它关闭,如下所示:
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
3.6、动作
3.6.1、useBean
这个动作将创建一个与某个java对象相关的脚本变量。它将是表现逻辑与业务逻辑分割开来最容易的方法之一。但是有了像定制标签和EL这类技术之后,现在已经很少使用useBean了。
<jsp:useBean id=”today” class=”java.util.Date”/>
3.6.2、setProperty和getProperty
<jsp:useBean id=”employee” class=”app03a.Employee”/>
<jsp:setProperty name=”employee” property=”fitstName” value=”Abigail”>
First Name:<jsp:getProperty name=”employee” property=”firstName”/>
3.6.3、include
Include动作用于动态地包含另一个资源,它可以包含另一个jsp页面、一个Servlet或者一个静态的HTML页面。
<jsp:include page=”jspf/menu.jsp”>
</jsp:include>
理解include指令和include动作之间的区别是很重要的。使用include指令时,这种包含是发生在页面转换的时候,例如jsp容器将页面转换成一个生成的Servlet的时候。使用include动作时,这种包含则是发生在请求的时候。因此,可以利用include动作传递参数,而不是利用include指令。
第二个区别在于,使用include指令时,杯包含资源的文件扩展名并不重要。而使用include动作时,文件扩展名则必须为jsp,以便它能够做为一个jsp页面进行处理。例如,在include动作中用jspf做为扩展名时,将会使得这个jsp segment被当作静态文件进行处理。
3.6.4、forward
Forward动作是将当前页面跳转到另一个不同的资源。例如,下面的forward动作就是将当前页面跳转到login.jsp页面。
<jsp:forward page=”jspf/login.jsp”>
</jsp:forward>
3.6.5、错误处理
在jsp中错误处理支持得很好。你可以利用try语句处理java代码,也可以指定一个页面,让他在应用程序遇到未捕捉的异常时显示出来,那么,一旦发生异常,用户将会看到一张经过精心设计的页面,解释目前发生了什么状况,而不是用一条错误消息打发用户,让他们皱眉不已。
利用page指令的isErrorPage属性,就可以把一个jsp页面变成一个错误处理页面,该属性必须为true。下面是一个错误处理程序。
buggy.jsp
errorHandler.jsp如果运行这个buggy.jsp页面,它就会抛出一个异常。但你不会看到Servlet/JSP容器产生的错误消息,而是会看到errorHandler.jsp页面显示的内容。
3.7、小结
Jsp实在java中构建web应用程序的第二种技术,作为servlet技术的补充,而不是要取代他。设计得好的java web应用程序一般都会用到servlet和jsp。