• 沒有找到結果。

5-4 与 Context 有关的隐含对象(1)

在文檔中 JSP 2.0技术手册 (頁 111-121)

在本节中,我们要介绍 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>相似,因此在这也 不多加讨论。

在文檔中 JSP 2.0技术手册 (頁 111-121)