●●●范围( Scope )
      有些 JSP 程序员会将 requestsessionapplication pageContext 归为一类,原因在于:它们皆能借助 setAttribute( ) getAttribute( )来设定和取得其属性(Attribute),通过这两种方法来做到数据分享
      我们先来看下面这段小程序:
Page1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title>Page1.jsp</title>
</head>
<body>
</br>
<%   
     application.setAttribute("Name","mike");      
     application.setAttribute("Password","browser");
%>
<jsp:forward page="Page2.jsp"/>
</body>
</html>
      在这个程序中,我们设定两个属性:NamePassword,其值为:mikebrowser。然后再转交(forward)Page2.jsp。我只要在Page2.jsp当中加入 application.getAttribute( ),就能取得在Page1.jsp设定的数据。
Page2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title>Page2.jsp</title>
</head>
<body>
<%
     String Name = (String) application.getAttribute("Name");
     String Password = (String) application.getAttribute("Password");
     out.println("Name = "+Name);
     out.println("Password = "+ Password);
%>
</body>
</html>
      执行结果为:
      Name=mike Password=browser
      由这个例子可以看出,JSP提供给开发人员一项传递数据的机制,那就是利用setAttribute( )getAttribute( )方法,如同Page1.jspPage2.jsp的做法。
      在上面Page1.jspPage2.jsp的程序当中,是将数据存入到 application 对象之中。除了application之外,还有requestpageContext session,也都可以设定和取得属性值,那它们之间有什么分别吗?
      它们之间最大的差别在于范围(Scope)不一样,这个概念有点像 CC++中的全局变量和局部变量的概念。接下来就介绍JSP的范围。
      JSP有四种范围,分别为PageRequestSessionApplication
     1JSP Scope—Page
      所谓的 Page,指的是单单一页JSP Page的范围。若要将数据存入 Page 范围时,可以用pageContext对象的 setAttribute()方法;若要取得Page范围的数据时,可以使用 pageContext对象的getAttribute( )方法。我们将之前的范例做小幅度的修改,将application改为 pageContext
PageScope1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title>PageScope1.jsp</title>
</head>
<body>
<h2>Page 范围 - pageContext</h2>
<%   
     pageContext.setAttribute("Name","mike");      
     pageContext.setAttribute("Password","browser");
%>
<jsp:forward page="PageScope2.jsp"/>
</body>
</html>
PageScope2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title>CH5 - PageScope2.jsp</title>
</head>
<body>
<h2>Page 范围 - pageContext</h2>
</br>
<%   
     String Name = (String)pageContext.getAttribute("Name");
     String Password = (String)pageContext.getAttribute("Password");
     out.println("Name = "+Name);
     out.println("Password = "+ Password);
%>
</body>
</html>
      执行结果为:
      Name=null Password=null
      这个范例程序和之前有点类似,只是之前的程序是 application,现在改为 pageContext,但是结果却大不相同,PageScope2.jsp 根本无法取得 PageScope1.jsp 设定的 Name Password 值,因为在PageScope1.jsp当中,是把NamePassword 的属性范围设为Page,所以Name Password 值只能PageScope1.jsp当中取得。若修改PageScope1.jsp的程序,重新命名为PageScope3.jsp,如下:
PageScope3.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title>CH5 - PageScope3.jsp</title>
</head>
<body>
<h2>Page 范围 - pageContext</h2>
</br>
<%   
     pageContext.setAttribute("Name","mike");      
     pageContext.setAttribute("Password","browser");
     
     String Name = (String)pageContext.getAttribute("Name");    
     String Password = (String)pageContext.getAttribute("Password"); 
     
     out.println("Name = "+Name);    
     out.println("Password = "+ Password);
%>
</body>
</html>
      PageScope3.jsp的执行结果为:
      Name=mike Password=browser
      经过修改后的程序,Name Password 的值就能顺利显示出来。这个范例主要用来说明一个概念:若数据设为Page范围时,数据只能在同一个 JSP网页上取得,其他 JSP网页却无法取得该数据。
     2JSP Scope—Request
      Request 的范围是指在JSP网页发出请求到另一个JSP网页之间,随后这个属性就失效。设定 Request 的范围时可利用 request 对象中的setAttribute()getAttribute()。我们再来看下列这个范例:
RequestScope1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title>CH5 - RequestScope1.jsp</title>
</head>
<body>
<h2>Request 范围 - request</h2>
<%   
     request.setAttribute("Name","mike");     
     request.setAttribute("Password","browser");
%>
<jsp:forward page="RequestScope2.jsp"/>
</body>
</html>
RequestScope2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title>RequestScope2.jsp</title>
</head>
<body>
<h2>Request 范围 - request</h2>
<%   
     String Name = (String) request.getAttribute("Name"); 
     String Password = (String) request.getAttribute("Password");    
     out.println("Name = "+Name);    
     out.println("Password = "+ Password);    
%>
</body>
</html>
      执行结果为:
      Name=mike Password=browser
      RequestScope1.jsp转向到RequestScope2.jsp时, RequestScope2.jsp也能取得RequestScope1.jsp设定的NamePassword值。不过其他的JSP网页无法得到NamePassword值,除非它们也和RequestScope1.jsp有请求的关系。
      除了利用转向(forward)的方法可以存取 request 对象的数据之外,还能使用包含(include)的方法。
      假若我将RequestScope1.jsp
      <jsp:forward page="RequestScope2.jsp"/>
      改为
      <jsp:include page="RequestScope2.jsp" flush="true"/>
      执行结果还是一样的。表示使用<jsp:include>标签所包含进来的网页,同样也可以取得Request范围的数据。
      3JSP ScopeSessionApplication
      下表介绍了最后两种范围:SessionApplication
JSP内置对象的范围和属性_jsp
●●●属性(Attribute)
      下表列出了一般储存和取得属性的方法,以下 pageContextrequestsession application皆可使用(注意:pageContext并无getAttributeNames( )方法)。
JSP内置对象的范围和属性_职场_02
      使 Object getAttribute(String name)取得 name ,它 java.lang.Object,因此,我们还必须根据name属性值的类型做转换类型(Casting)的工作。
      例如,若要取得String类型的Name属性时:
      String Name = (String)Sessio.getAttribute("Name");
      若要取得Integer类型的Year属性时:
      Integer Year = (Integer)session.getAttribute("Year");
      假若我们的数据要设为Page范围时,则只需要:
      pageContext.setAttribute("Year", new Integer(2001));
      若要为 RequestSession Application 时,就分别存入 requestsession application对象之中,如下:
      request.setAttribute("Month", new Integer(12) );
      session.setAttribute("Day", new Integer(27) );
      application.setAttribute("Times", new Integer(10));
 (3)Response对象
       Response对象主要将 JSP 处理数据后的结果传回到客户端。Response对象实现的是javax.servlet.http.HttpServletResponse 接口。
       Response对象的方法:
       ①设定表头的方法
       void addCookie(Cookie cookie):添加一个Cookie对象(保存到硬盘),用来保存客户端的用户信息,用request的getCookies()方法可以获得这个Cookie。
       void addHeader(String name,String value):添加String类型的值(value)到指定名字(name)的HTTP文件头。该header将会传到客户端去,如果有同名的header存在,那么原来的header将会被覆盖掉。
       void addIntHeader(String name, int value):添加int类型的值(value)到指定名字(name)的HTTP文件头。该header将会传到客户端去,如果有同名的header存在,那么原来的header将会被覆盖掉。
       Void addDateHeader(String name, long date):添加long类型的值(value)到指定名字(name)的HTTP文件头。该header将会传到客户端去,如果有同名的header存在,那么原来的header将会被覆盖掉。
       void setHeader(String name,String value):指定String类型的值(value)到指定名字(name)的HTTP文件头。该header将会传到客户端去,如果有同名的header存在,那么原来的header将会被覆盖掉。
       void setIntHeader(String name, int value):指定int类型的值(value)到指定名字(name)的HTTP文件头。该header将会传到客户端去,如果有同名的header存在,那么原来的header将会被覆盖掉。
       Void setDateHeader(String name, long date):指定long类型的值(value)到指定名字(name)的HTTP文件头。该header将会传到客户端去,如果有同名的header存在,那么原来的header将会被覆盖掉。
       ②设定响应状态码的方法
       void sendError(int sc):向客户端发送状态码。例如,505指示服务器内部错误;404指示网页找不到的错误。
       void sendError(int sc, String msg):向客户端发送状态码和错误信息。
       void setStatus(int sc):设定状态码。
       ③与URL有关的方法
       sendRedirect(URL):可以将用户重定向到一个不同的页面(URL)。sendRedirect(URL)方法通过返回特定的状态代码而起作用,当它被调用时,返回一个状态代码,然后在响应中定位,给新页面一个新地址。状态代码和定位头会自动把浏览器重定位到新页面。不过,用户通常不能被顺利重定位到新的页而,特别是老一些的浏览器,而且一些新版本的浏览器在自动响应定向作用状态代码时会有些问题,当浏览器无法自动响应状态代码时,会收到一些字段信息。
       String encodeRedirectURL(String url):对使用sendRedirect( )方法的URL予以编码。
       ④其他方法
       Boolean containsHeader(String name):判断指定名字的HTTP文件头是否存在,并返回布尔值。
       void setContenType(String type):响应设置内容类型头。
       例子:
       有时候,当我们修改程序后,产生的结果却是之前的数据,执行浏览器上的刷新,才能看到更改数据后的结果,针对这个问题,有时是因为浏览器会将之前浏览过的数据存放在浏览器的 Cache中,所以当我们再次执行时,浏览器会直接从 Cache 中取出,因此,会显示之前旧的数据。现写一个Non-cache.jsp 程序来解决这个问题。
       Non-cache.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title> Non-cache.jsp</title>
</head>
<body>
<h2>解决浏览器 cache 的问题 - response</h2>
<%   
     if (request.getProtocol().compareTo("HTTP/1.0") == 0)       
          response.setHeader("Pragma", "no-cache");    
     else if (request.getProtocol().compareTo("HTTP/1.1") == 0)      
         response.setHeader("Cache-Control", "no-cache"); 
     response.setDateHeader("Expires", 0); 
%>
</body>
</html>
       先用 request 对象取得协议,如果为 HTTP/1.0,就设定标头,内容为 setHeader ("Pragma", "no-cache");若为HTTP/1.1,就设定标头为 response.setHeader ("Cache-Control", "no-cache"),最后再设定response.setDateHeader("Expires", 0)。这样 Non-cache.jsp网页在浏览过后,就不会再存放到浏览器或是 proxy服务器的 Cache 中。
       HTTP/1.1 Cache-Control 标头的设定参数详见http://esoft.bokee.com/5202557.html
       有时候,我们想要让网页自己能自动更新,因此,须使用到 Refresh 这个标头。举个例子,我们告诉浏览器,每隔三分钟,就重新加载此网页:response.setIntHeader("Refresh" , 180)
       如果想要过十秒后,调用浏览器转到 http://esoft.bokee.com的网页时,可用如下代码:
response.setHeader("Refresh","10; URL=http://esoft.bokee.com" )
       HTML 语法中也有类似的功能:
<META HTTP-EQUIV="Refresh" CONTENT=" 10; URL=http://Server/Path" >
       上述两种方法皆可以做到自动重新加载。
 (4)Session对象
       Session 对象表示目前个别用户的会话(session)状况,用此项机制可以轻易识别每一个用户,然后针对每一个别用户的要求,给予正确的响应。例如:购物车最常使用 session 的概念,当用户把物品放入购物车时,他不须重复做身份确认的动作(如:Login),就能把物品放入用户的购物车。但服务器利用 session 对象,就能确认用户是谁,把它的物品放在属于用户的购物车,而不会将物品放错到别人的购物车。session对象实现的是javax.servlet.http.HttpSession 接口。
       Session对象的方法:
       setAttribute(String name,java.lang.Object value):设定指定名字的属性值,并且把它存储在Session对象中。
       getAttribute(String name):获得指定名字的属性,如果该属性不存在,将会返回null。
       Enumeration getAttributeNames():返回Session对象中存储的每个属性对象,结果集是一个Enumeration类的实例。
       Boolean isNew():判断目前Session是否为新的Session,若是则返回ture,否则返回false(所谓"新"的Session,表示session已由服务器产生,但是client尚未使用)。
       String getId():返回Session对象在服务器端的编号。每生成一个Session对象,服务器都会给它一个编号,并且该编号不会重复,这样服务器才能根据编号来识别Session,并且正确的处理某一特定的Session及其提供的服务。
       long getCreationTime():返回Session对象被创建的时间,单位为毫秒,由1970年1月1日零时算起。
       long getLastAccessedTime():返回用户最后通过这个session送出请求的时间,单位是毫秒,由1970年1月1日零时算起。
       long getMaxInactiveInterval():取得最大session不活动的时间,若超过这时间,session 将会失效,时间单位为秒。
       void setMaxInactiveInterval(int interval):设置最大session不活动的时间,若超过这时间,session 将会失效,时间单位为秒。
       void removeAttribute(String name)“删除指定的属性(包含属性名、属性值)。如果在有效时间内,用户做出了新的请求,那么服务器就会将其看作一个新的用户,此时,服务器将创建一个新的Session,旧的Session信息将会丢失
       void invalidate():取消 session对象,并将对象存放的内容完全抛弃。
       例子:
       session 对象也可以储存或取得用户相关的数据,例如:用户名、用户所订购的物品、用户的权限等等,这些要看我们的程序如何去设计。例如:我要设定某些网页必须要求用户先做登录(Login)的动作,确定是合法的用户时,才允许读取网页内容,否则把网页重新转向到登录的网页上。
       Login.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title> 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网页;若输入错误时,就显示出“登录错误,请输入正确名称”。不允许登录至 Member.jsp
       这时大家一定会想,如果我不通过Login.jsp 网页,直接执行 Member.jsp,那不就能够进去了。没错,因此我们还要在Member.jsp中加入一段程序代码,来确认用户是否有先通过 Login.jsp的身份确认,然后再到Member.jsp中。Member.jsp程序如下:
       Member.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
 <title> 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,要求用户先行登录。
       最后要提醒一点,session对象不像其他的隐含对象,可以在任何的 JSP网页中使用,如果在JSP网页中,page 指令的属性session 设为 false 时,使用 session 对象就会产生编译错误 (javax.servlet.ServletException: Compilation error occurred )
 (5)Application对象
       Application对象用于取得或更改Servlet的设定,他的生存期是由服务器产生开始至服务器关机为止。application 对象实现的是javax.servlet.ServletContext接口。
       Application对象的方法:
       ①与容器相关的方法
       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> GetJspVersion.jsp</title>
</head>
<body>
<h2>取得 JSP Container 版本 - JspFactory 对象</h2>     
<%
       JspFactory factory = JspFactory.getDefaultFactory();
        out.println("JSP v 2.0"+ 
                        factory.getEngineInfo().getSpecificationVersion());
%>
</body>
</html>
       ②有关服务端的路径和文件的方法
       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("/") %>
       ③有关信息记录的方法
       void log(String message):将信息写入 log 文件中。
       void log(String message, Throwable throwable):将 stack trace 所产生的异常信息写入log文件中。
       application对象最常被使用在存取环境的信息,因为环境的信息通常都储存在ServletContext中,所以常利用application对象来存取ServletContext中的信息。
*******************************************************************************
●●●JSP内置对象与Servlet子类映射
JSP内置对象       Servlet子类                          作用域
request             javax.servlet.http.HttpServletRequest       Request
response           javax.servlet.http.HttpServletResponse     Page
session             javax.servlet.http.HttpSession                 Session
application        javax.servlet.ServletContext                    Application
out                  javax.servlet.jsp.JSPWrite                       Page
pageContext     javax.servlet.jsp.PageContext                  Page
config              javax.servlet.ServletConfig                     Page
page                java.lang.Object                                     Page
exception         java.lang.Throwable                               Page