在JSP技术内部,已经被定义好了若干个JSP内部对象,在这些对象内部可以用来完成很多种要的功能。
JSP内部已经被定义好的对象有:
page对象、pageContext对象、request对象、session对象、application对象、response对象、out对象、config对象、exception对象,九大内置对象。
在详细介绍九大内置对象之前,说明一下page、request、session、applicatoin对象的作用域。
application作用域就是服务器从启动到关闭的整段时间,在这个作用域内设置的对象可以被所有应用程序使用。
application作用域上的信息是通过ServletContext实现的。
session作用域就是同一浏览器对服务器多次访问,在多次访问之间传递信息,就是session作用域的体现。
session通过HttpSession接口实现。
request就是一次HTTP请求可能需要多个servlet合作,而这几个servlet之间可以通过某种方式传递信息,但这个信息在请求结束之后就无效了。
Servlet之间的信息共享是通过HttpServletRequest接口来实现的。
page对象的作用域仅限于用户请求的当前页面,对于page对象的引用将在响应返回给客户端之后被释放,或者在请求被转发到其他地方后被释放。对page对象的引用通常存储在pageContext对象中。
在JSP转换成的Servlet中可以看到九大内置对象的定义:
以下是部分代码:
public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null;
这里包含了两个参数外加前六个变量,共八个内置对象。最后还差个exception对象,这个对象是只有在jsp页面的isErrorPage被定义为true时,才会出现。
Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request); if (exception != null) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); }
1、application对象
使用application对象的方式有以下几种方法:
(1)在JSP页面直接使用application以代表application对象
<% application.Method();%>
(2)使用ServletConfig接口
使用ServletConfig接口可以间接获取application对象,但是不可以定义变量为application,因为application是JSP引擎创建的默认的application对象变量,这样会造成变量重复定义。
ServletContext app = config.getServletContext();
(3)使用pageContext对象获取application对象
pageContext对象的getServletContext()方法同样可以返回一个application对象的副本。
ServletContext app = pageContext.getServletContext();
application对象除了setAttribute、removeAttribute和getAttribute方法之外,还有几个值得注意的方法。
A:getServletInfo()返回服务器的详细信息
B:getAttributeNames()返回所有与application绑定的参数或者对象的名字。返回值是个枚举对象(Enumeration)
C:log(String msg)
该方法用于往服务器的log文件中写入信息,至于是哪个log文件,则由服务器来决定。利用这个方法,我们可以在log文件中记录访问者的信息,这对于统计访问流量来源方面十分有用,同时也便于管理员监控网站的运行情况。其实,还有个同名但是用不同参数的log()方法,利用后者,我们可以将JSP程序执行过程中所发生的错误事件都记录到log日志里。
另外需要注意的一点是:大部分的服务器都支持application.Method()的方式,但是有些比较旧版本的服务器,不支持application的形式,但是他们支持getServletContext().Method()的方式。
(4)config对象
config对象是一个servlet程序初始化的时候,JSP引擎向它传递消息用的,此消息包括servlet程序初始化时所需的参数及服务器的相关信息。Config对象其实是实现javax.servlet.ServletConfig接口的类的实例对象,它可以使用以下3个方法:
A:getServletContext()
调用这个方法可以返回一个包含服务器相关信息的ServletContext对象,即JSP内置对象——application对象。
B:getInitParameter(String name)
获取servlet程序初始参数的值,参数名由name指定。
C:getInitParameterNames()
获取servlet程序初始化所需要的所有参数的名称构成的枚举对象Enumeration。
config对象在Servlet对象中作用很大,但是servlet程序中没有内置对象这一说,严格的说法是ServletConfig接口在servlet程序中作用很大。但是JSP页面中的config对象的作用很小。
(5)exception对象
如果想在JSP程序中使用exception对象,必须在page指令里指定isErrorPage属性为true,否则不能使用exception对象。
exception对象可以使用的主要方法有:
A:getMessage()返回错误信息
B:printStackTrace()以标准错误的形式输出一个错误和错误的堆栈
C:toString()该方法以字符串的形式返回一个对异常的描述
exception对象配合page指定的errorPage属性一起使用,将某个JSP程序指定为错误处理程序,把所有的错误和异常都集中到那个程序里处理,是的整个程序的健壮性得到加强,也使得程序的流程更加简单明晰,也是JSP比ASP、PHP优越的地方。
如果某个JSP页面出现异常,那么JSP引擎会自动产生一个异常对象,如果该JSP页面指定了错误处理页面,那么JSP引擎会将异常对象放到request对象中,传到错误处理程序中,在错误处理程序中,因为page编译指令的isErrorPage属性为true,那么JSP引擎会声明一个exception对象,这个exception对象从request对象所包含的HTTP参数中获得。
Throwable exception = (Throwable)request.getAttribute("javax.servlet.jsp.jspException");
从jsp转换成的servlet看exception的声明是通过下面的代码完成的
Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);
这里说从request的属性里可以获取到
Throwable exception = (Throwable)request.getAttribute("javax.servlet.jsp.jspException");
从测试结果上看:从request中获取属性得到的exception对象和servlet声明的exception对象是同一个对象(==)。
这里引出jsp的异常处理机制:参考。。。。。。。。。。。。??????????
另外:如果在JSP页面出现异常的时候,主动try-catch了,那么不会将异常传递到错误处理页面的。
(6)out对象
out对象主要是用来向客户端输出各种格式的数据,并且管理应用服务器上的输出缓冲区,out对象的基类是javax.servlet.jsp.JspWriter类。
out对象最主要的方法是:out.println(xxxx)和out.print(xxxx)。xxxx代表是java数据类型的数据。二者区别在于println会换行,print不会,但是需要注意的是:println()方法的换行并不会真的在网页效果上看到换行,只是输出的源码里的换行,如果想要在页面上换行,需要用到<br>标签。
这里也比较好理解:out.println()是用java代码输出html代码的过程,只是在生成的html代码里换行了,这并不能引起页面效果的换行。
out对象的其他方法:
A:newLine()
该方法用于输出一个换行符,同样的也只是能在查看html源文件的时候看出来,作用是规范了html源码的结构方便调试。
B:flush()
该方法用于强制输出服务器的输出缓存区里的数据。如果page指令的autoFlush属性的值为true,那么JSP程序会把输出数据缓存在服务器的输出缓存区中,知道程序结束或者缓冲区已经充满数据,服务器会自动将数据发送到客户端。如果在JSP程序中使用了flush()方法,那么服务器不管缓冲区有没有充满,都将数据强制发送到客户端。如果JSP编译指令page的autoflush属性为false,那么我们需要显示的调用flush()方法将数据发送到客户端。
C:close()
该方法首先将缓冲区的数据强制输出到客户端,然后关闭对客户端的输出流。
D:clearBuffer()
该方法用于强制清除缓存区的数据,但是不会将数据写到客户端,如果已经flush过(并不是说缓冲区为空),不会产生IOException。
E:clear()
该方法用于清除缓存区的里数据,但是不会将数据写到客户端,如果已经flush过(并不是说缓冲区为空),会产生IOException。所以使用这个方法要用try-catch来捕获异常。
F:getBufferSize()
该方法返回缓冲区的大小,缓冲区的大小可以在page指令里设置<% @ page buffer="8kb" %>
G:getRemaining()
该方法返回缓冲区还没有使用的字节数目。
H:isAutoFlush()
返回是否自动刷新缓存,该值由page指令的autoFlush属性值决定。
B、D、E方法的区别可以参考Out输出对象clear(),clearBuffer()和flush()的区别
值得注意的是,B、D、E中,只有flush()方法会将内容输出到客户端,而D、E方法只会清空缓冲区。而D、E的区别在于如果已经flush过,clear会产生IOException。这里要强调是flush而不是缓冲区为空。因为如果两个clear()连续调用,不会产生异常,而flush过后,会产生异常,并且Out输出对象clear(),clearBuffer()和flush()的区别英文文档上也说的很清楚,是flush之后二者会有区别。
由此猜测,该flush后clear产生的异常是通过flush产生的标识位来判断的,从源码上找到了印证:
public final void clear() throws IOException {
if ((bufferSize == 0) && (out != null))
// clear() is illegal after any unbuffered output (JSP.5.5)
throw new IllegalStateException(
getLocalizeMessage("jsp.error.ise_on_clear"));
if (flushed)
throw new IOException(
getLocalizeMessage("jsp.error.attempt_to_clear_flushed_buffer"));
ensureOpen();
nextChar = 0;
}
至于为什么有了clearBuffer还要有clear?
tomcat源码里的clear接口的定义给出了解释:
/**
* Clear the contents of the buffer. If the buffer has been already
* been flushed then the clear operation shall throw an IOException
* to signal the fact that some data has already been irrevocably
* written to the client response stream.
*
* @throws IOException If an I/O error occurs
*/
abstract public void clear() throws IOException;
clear抛出异常是为了表明数据已经发送给客户端,不可取消(irrevocably-不可撤回的)
(7)page对象
page对象是指向当前jsp程序本对象。page对象在JSP程序中的应用不是很广。
从源码上看:Object page = this;
(8)pageContext对象
pageContext对象提供了对JSP页面的所有的对象和命名空间的访问,可以直接访问绑定在application对象、page对象、request对象、session对象上的java对象。pageContext对象相当于JSP程序中所有对象的集成者。
值得注意的是:
A:pageContext访问JSP页面的内置对象,变量名不能跟内置对象默认名称相同,如:JspWriter out = pageContext.getOut();是不行的,out变量重复定义了。
B:pageContext可以指定两个参数name和scope来获取、设置、删除绑定在scope上的java对象,此外还有findAttribute(String name)方法,将在application对象、session对象、request对象、page对象内部查找是否有某个参数或者Java对象与这些对象绑定了,搜索顺序是从范围最小的page对象,其次是request对象、session对象、最后是application对象,这个方法的返回值是第一个符合要求的java对象的值。
还有几个方法:release()释放pageContext对象所占的资源,forward(String url)页面跳转,内部是通过RequestDispatcher来跳转的,include(String relativeUrlPath)包含一个外部文件。
(9)request对象
request对象可以获得客户端的输入信息。request对象包含了从客户端传来的请求信息。在HTTP1.1协议中,客户单请求信息是从客户端通过HTTP头(HTTP Header)和消息体传送到服务器端的。
请求的参数是一个请求的组成部分,它们被作为字符串从客户端传送到JSP/Servlet容器,并被利用于初始化request对象。
request对象的基类是javax.servlet.http.HttpServletRequest接口,它可用的主要方法如下:
A:getCookie()
该方法返回客户端的Cookie对象数组,这些Cookie对象是javax.servlet.http.Cookie类的实例对象。
B:getHeader(String name)
该方法获得HTTP协议所定义的特定HTTP文件头信息。该方法的参数name可以是HTTP文件头的名字,如User-Agent。
C:getAttribute、setAttribute、getAttributeNames()、getHeaderNames()
D:getParameterValues(String name)
使用这个方法可以获得由客户端向服务器端传送的指定参数的所有值。因为同一个参数可能被赋多个值,如果使用getParameter()方法,那么仅会获得该参数的第一个值,后面的值都被忽略了。但是使用getParameterValues()方法,就可以获取赋给指定参数的所有值,这个方法的返回类型是字符串数组。
E:getQueryString()、getRequestURI()、getServletPath()、getServerName()、getServerPort()、getRemoteAddr()、getRemoteHost()、getProtocol()
(10)response对象
response对象的作用是处理HTTP连接信息,如cookie、HTTP文件头信息等,它有很多功能是和request对象是相匹配的。它的重要性相对不如request对象、application对象、session对象。
A:addCookie(Cookie cookie)
当用户访问某个站点时,我们可以使用addCookie()方法添加一个Cookie对象,并将它发送到客户端,保存到客户端操作系统的某个特定目录下,用来保存客户端的特定信息。当该用户再次访问同一个站点时,浏览器会自动将这个Cookie对象发送回服务端,调用request对象的getCookie()方法可以获得多有存在的Cookie对象,getCookie()方法的返回值是一个数组。Cookie对象对于不同的用户来说是专有的。
B:addHeader(String name, String value)
该方法的作用是添加http文件头信息,这些信息会传送到客户端,发送特定的http文件头信息,可以控制客户端和服务端的连接。如果同名的http头文件已经存在,那么换来的http文件头的值会被覆盖。
例如利用response对象禁止使用代理服务器缓存(该方法需要测试,不一定好用)
<% //http 1.1
response.setHeader("Cahce-Control","no-store");
//http 1.0
response.setHeader("Paragma","no-cache");
//prevents caching at the proxy server
response.setDateHeader("Expires",0);
利用response对象设定应答的MIME类型及附件
<%
response.setContentType("application/pdf");
response.setHeader("Content-Disposition","attachmet;filename=\"syntax.pdf\"");
%>
C:containsHeader(String name)
该方法用于判断指定名字的http文件头是否存在,返回值为布尔类型
D:sendError(int sc)
该方法用于向客户端发送错误信息,例如505:服务器内部错误,404:网页找到不到的错误。
它的使用方法如下:
<%
response.sendError(response.SC_NO_CONTENT);
如果在jsp程序中包含了这行代码,那么不管jsp程序其他部分的输出如何,客户单的浏览器将会出现网页找不到的http404错误。
E:sendRedirect(String url)
使用response对象的sendRedirect()方法可以使当前页面重定向到另外的jsp程序或者html文件中。它的功能和<jsp:forward>动作一样,就是向目标程序传递http参数不是很方便。
<% response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location","/newpath/index.html");
%>
上面的jsp代码同样实现了重定向功能,使用setHeader方法,向客户端的浏览器发送http头文件-Location,浏览器接收到这个HTTP文件头以后,就会自动打开Location所指定的新的URL地址。
(11)session对象
session对象是十分重要的一个JSP内置对象,它可以用来在每一个用户之间分别保存用户信息,这与application对象不同。application用于在多个程序之间保存信息,application对象只有一个,它可以绑定若干个相当于全局变量的参数或者Java对象,每个JSP程序访问的都是application对象的一个同步副本,都是一样的,而且application对象的生命周期贯穿服务器的整个运行周期。但是,服务器上的session对象却可以有多个,不同的用户所面临的session对象一般来说是不同的,当用户登录网站,系统将为他生成一个独一无二的session,用以记录该用户的个人信息,一旦该用户退出网站,那么该session对象将会被注销。
session对象是javax.servlet.http.HttpSession接口的实例对象
A:getCreationTime()
该方法返回当前session对象的创建时间,单位以毫秒计算,从1970年1月1日开始。
B:getLastAccessedTime()
返回当前session对象最后一次被操作的时间,单位是毫秒,从1970年1月1日开始。我们可以利用A、B方法判断某个用户在网站上一共待了多长时间。
C:getMaxInactiveInterval()
该方法用于返回当前session的最大休眠时间。
D:setMaxInactiveInterval()
设定最大休眠时间。
E:invalidate()
清除当前session对象,解除它和任何参数或者Java对象的绑定关系。
需要单独的一篇文章来分析tomcat源码的,才能深入理解jsp