在本节中,我们要介绍 session、application、pageContext 这三个对象。session 对象提供一 些机制,让服务器能个别辨认用户。当程序在执行时,application 对象能提供服务端(Server-Side) 的 Context,说明哪些资源是可利用的,哪些信息是可获取的。pageContext 对象提供存取所有在此 网页中可被利用的隐含对象,并且可以管理它们的属性。
session 对象
session 对象表示目前个别用户的会话(session)状况,用此项机制可以轻易识别每一个用户,
然后针对每一个别用户的要求,给予正确的响应。例如:购物车最常使用 session 的概念,当用户 把物品放入购物车时,他不须重复做身份确认的动作(如:Login),就能把物品放入用户的购物车。
但服务器利用 session 对象,就能确认用户是谁,把它的物品放在属于用户的购物车,而不会将物 品放错到别人的购物车。除了购物车之外,session 对象也通常用来做追踪用户的功能,这在第十 章有更加详细的说明。
session 对象实现 javax.servlet.http.HttpSession 接口,表 5-12 列出了一些常用的方法。
表 5-12 javax.servlet.http.HttpSession 接口所提供的方法
方 法 说 明
long getCreationTime() 取得 session 产生的时间,单位是毫秒,由 1970 年 1 月 1 日零时算起
String getId() 取得 session 的 ID
方 法 说 明
long getLastAccessedTime()
取得用户最后通过这个 session 送出请求的时 间,单位是毫秒,由 1970 年 1 月 1 日零时算 起
long getMaxInactiveInterval() 取得最大 session 不活动的时间,若超过这时 间,session 将会失效,时间单位为秒
void invalidate() 取消 session 对象,并将对象存放的内容完全
抛弃
boolean isNew()
判断 session 是否为"新"的,所谓"新"的 session,表示 session 已由服务器产生,但 是 client 尚未使用
void setMaxInactiveInterval(int interval)
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - Login.jsp</title>
</head>
<body>
<h2>javax.servlet.http.HttpSession - session 对象</h2>
<form action=Login.jsp method="POST" >
Login Name: <input type="text" name="Name"><br>
Login Password: <input type="text" name="Password" ><br>
<input type="submit" value="Send"><br>
<form>
<% if (request.getParameter("Name") != null &&
request.getParameter("Password") != null) {
String Name = request.getParameter("Name");
String Password = request.getParameter("Password");
if (Name.equals("mike") && Password.equals("1234")) {
session.setAttribute("Login", "OK");
response.sendRedirect("Member.jsp");
}
else {
out.println("登录错误,请输入正确名称");
} }
%>
</body>
</html>
在 Login.jsp 的程序中,我要求用户分别输入名称和密码,如果输入的名称和密码分别为 mike 和 1234 时,就把名称为 Login、其值为 OK 的属性,加入到 session 对象当中,然后进入 Member.jsp 网页,如图 5-9;若输入错误时,就显示出“登录错误,请输入正确名称”。不允许登录至 Member.jsp,
如图 5-10 所示。
图 5-9 登录成功,顺利进入 Member.jsp
图 5-10 登录失败画面
这时大家一定会想,如果我不通过 Login.jsp 网页,直接执行 Member.jsp,那不就能够进去了。
没错,因此我们还要在 Member.jsp 中加入一段程序代码,来确认用户是否有先通过 Login.jsp 的身 份确认,然后再到 Member.jsp 中。Member.jsp 程序如下:
Member.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - Member.jsp</title>
</head>
<body>
<h2>javax.servlet.http.HttpSession - session 对象</h2>
<%
String Login = (String)session.getAttribute("Login");
if (Login != null && Login.equals("OK")) { out.println("欢迎进入");
session.invalidate();
}
else {
out.println("请先登录,谢谢") ;
out.println("<br>经过五秒之后,网页会自动返回 Login.jsp");
response.setHeader("Refresh","5;URL=Login.jsp");
}
%>
</body>
</html>
在 Member.jsp 中我利用 session.getAttribute("Login"),如果用户是通过 Login.jsp 网页进入,
并且顺利通过身份确认取得 Login=OK,到 Member.jsp 再做确认时,也能顺利通过;否则,如果直接 连接到 Member.jsp 时,Login 的值会等于 NULL,则程序经过五秒后,重新加载 Login.jsp,要求用户 先行登录。若直接执行 Member.jsp,而没有经过登录手续时,就会发现如图 5-11。
图 5-11 直接执行 Member.jsp,并未经过登录手续
最后要提醒读者一点,session 对象不像其他的隐含对象,可以在任何的 JSP 网页中使用,如果 在 JSP 网页中,page 指令的属性 session 设为 false 时,使用 session 对象就会产生编译错误 (javax.servlet.ServletException: Compilation error occurred ),如下所示:
<%@ page session="false" %>
<%
String Login = (String)session.getAttribute("Login");
….
….
%>
在本书“第十章:Session Tracking”中对 session 有更多更详细的介绍。
application 对象
application 对象实现 javax.servlet.ServletContext 接口,它主要功用在于取得或更改 Servlet 的设定。下面程序用来说明 JSP 网页被编译成 Servlet 时,application 对象是如何初 始化的:
pageContext = JspxFactory.getPageContext ( this , request , response ,
"errorpage.jsp" , true , 8192 , true );
application = pageContext.getServletContext( );
你可以看到产生的 Servlet 取得了目前的 ServletContext,并且将它储存在 application 对象 当中。application 对象拥有 Application 的范围,意思就是说它的生命周期是由服务器产生开始 至服务器关机为止。表 5-13、表 5-14、表 5-15 列出了其相关方法:
表 5-13 javax.servlet.ServletContext 接口容器相关信息的方法
方 法 说 明
int getMajorVersion( ) 取得 Container 主要的 Servlet API 版本,如:2 int getMinorVersion( ) 取得 Container 次要的 Servlet API 版本,如:4 String getServerInfo( ) 取得 Container 的名称和版本
<%= application.getMajorVersion() %><br>
<%= application.getMinorVersion() %><br>
<%= application.getServerInfo() %><br>
上述的 getMajorVersion( )和 getMinorVersion( )是取得 Servlet Engine 的版本信息,假如 想要取得 JSP 容器的版本信息,则可能就要使用到下面这段程序代码:
GetJspVersion.jsp
<%@ page import="javax.servlet.jsp.JspFactory"
contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - GetJspVersion.jsp</title>
</head>
<body>
<h2>取得 JSP Container 版本 - JspFactory 对象</h2>
<%
JspFactory factory = JspFactory.getDefaultFactory();
out.println("JSP v 2.0"+
执行结果如图 5-12 所示。
表 5-14 javax.servlet.ServletContext 接口有关服务端的路径和文件的方法
方 法 说 明
String getMimeType(String file) 取得指定文件的 MIME 类型 ServletContext getContext(String
uripath)
取得指定 Local URL 的 Application context
String getRealPath(String path) 取得本地端 path 的绝对路径
范例:
<%= application.getMimeType("MyFile") %>
<%= application.getContext("/") %>
<%= application.getRealPath("/") %>
表 5-15 javax.servlet.ServletContext 接口有关信息记录的方法
方 法 说 明
void log(String message) 将信息写入 log 文件中
void log(String message, Throwable throwable)
将 stack trace 所产生的异常信息写入 log 文件中
application 对象最常被使用在存取环境的信息,因为环境的信息通常都储存在 ServletContext 中,
所以常利用 application 对象来存取 ServletContext 中的信息。
图 5-12 GetJspVesion.jsp 的执行结果 pageContext 对象
pageContext 对象能够存取其他隐含对象。当隐含对象本身也支持属性时,pageContext 对象也 提供存取那些属性的方法。不过在使用下列方法时,需要指定范围的参数:
Object getAttribute(String name, int scope) Enumeration getAttributeNamesInScope(int scope)
void removeAttribute(String name, int scope)
void setAttribute(String name, Object value, int scope)
范围参数有四个常数,分别代表四种范围:PAGE_SCOPE 代表 Page 范围,REQUEST_SCOPE 代表 Request 范围,SESSION_SCOPE 代表 Session 范围,最后 APPLICATION_SCOPE 代表 Application 范围(见表 5-16、表 5-17、表 5-18)。
表 5-16 javax.servlet.jsp.PageContext 类取得其他隐含对象的方法
方 法 说 明
Exception getException( ) 回传目前网页的异常,不过此网页要为 error page,
例如:exception 隐含对象
JspWriter getOut( ) 回传目前网页的输出流,例如:out 隐含对象
Object getPage( ) 回传目前网页的 Servlet 实体(instance),例如:page 隐含对象
ServletRequest
getRequest( ) 回传目前网页的请求,例如:request 隐含对象
ServletResponse
getResponse( ) 回传目前网页的响应,例如:response 隐含对象
ServletConfig getServletConfig( )
回传目前此网页的 ServletConfig 对象,例如:config 隐含对象
ServletContext getServletContext( )
回 传 目 前 此 网 页 的 执 行 环 境 (context) , 例 如 : application 隐含对象
HttpSession getSession( ) 回 传 和 目 前 网 页 有 联 系 的 会 话 (session) , 例 如 : session 隐含对象
表 5-17 javax.servlet.jsp.PageContext 类所提供取得属性的方法
方 法 说 明
Object getAttribute(String name, int scope)
回传 name 属性,范围为 scope 的 属 性 对 象 , 回 传 类 型 为 java.lang.Object
Enumeration getAttributeNamesInScope(int scope)
回传所有属性范围为 scope 的属 性名称,回传类型为 Enumeration int getAttributesScope(String name) 回传属性名称为 name 的属性范围 void removeAttribute(String name) 移除属性名称为 name 的属性对象 void removeAttribute(String name, int 移 除属性 名称 为 name,范 围为
void setAttribute(String name, Object value, int scope)
指定属性对象的名称为 name、值 为 value、范围为 scope
Object findAttribute(String name) 寻 找 在 所 有 范 围 中 属 性 名 称 为 name 的属性对象
表 5-18 javax.servlet.jsp.PageContext 类所提供范围的变量
常 数 说 明
PAGE_SCOPE 存入 pageContext 对象的属性范围
REQUEST_SCOPE 存入 request 对象的属性范围
SESSION_SCOPE 存入 session 对象的属性范围
APPLICATION_SCOPE 存入 application 对象的属性范围
接下来示范一个小程序,让读者能够更加明白。
PageContext.jsp
<%@ page import="java.util.Enumeration"
contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - PageContext.jsp</title>
</head>
<body>
<h2>javax.servlet.jsp.PageContext - pageContext </h2>
<%
Enumeration enum =
pageContext.getAttributeNamesInScope(PageContext.APPLICATION_SCOPE );
while (enum.hasMoreElements())
{
out.println("application attribute:"+enum.nextElement( ) +"<br>"); }
%>
</body>
</html>
PageContext.jsp 主要目的是:在这页当中,取得所有属性范围为 Application 的属性名称,
然后再依序显示出来这些属性。
首先要记得导入 java.util.Enumeration。pageContext.getAttributeNamesInScope( )会回传 所有指定范围的属性名称,因此,我们产生 Enumeration 对象 enum,利用 enum 来收集所有属性范 围为 Application 的数据,然后再一一地取出打印出来。这里最重要的是让读者了解如何设定 scope 的参数,因此下面这行代码:
PageContext.APPLICATION_SCOPE
是最主要的。有了这个范例程序之后,读者应该能够快速学会使用 pageContext 对象所提供的 方法。
pageContext 对象除了提供上述的方法之外,另外还有两种方法:forward (Sting Path)、include (String Path),这两种方法的功能和之前提到的<jsp:forward>与<jsp:include>相似,因此在这也 不多加讨论。