`

关于request和session详解

 
阅读更多
原文地址:http://blog.sina.com.cn/s/blog_6a292d8e01013wnw.html

【前面的话】

在网上经常看到有人对request.getSession(false)提出疑问,我第一次也很迷惑,看了一下J2EE1.3 API,看一下官网是怎么解释的。

【官方解释】

  getSession

public HttpSessiongetSession(boolean create)

Returns the current HttpSession associated with this request or, if if there is no current session and create is true, returns a new session.

If create is false and the request has no valid HttpSession, this method returns null.

To make sure the session is properly maintained, you must call this method before the response is committed. If the container is using cookies to maintain session integrity and is asked to create a new session when the response is committed, an IllegalStateException is thrown.

Parameters:true - to create a new session for this request if necessary; false to return null if there's no current session

Returns: the HttpSession associated with this request or null if create is false and the request has no valid session

译:

getSession(boolean create)意思是返回当前reqeust中的HttpSession ,如果当前reqeust中的HttpSession 为null,当create为true,就创建一个新的Session,否则返回null;

简而言之:

HttpServletRequest.getSession(ture) 等同于 HttpServletRequest.getSession()

HttpServletRequest.getSession(false) 等同于 如果当前Session没有就为null;

【问题和bug】:

我周围很多同事是这样写的;

HttpSession session = request.getSession();   // a new session created if no session exists, 哈哈!完蛋啦!如果session不存在的话你又创建了一个!  
String user_name = session.getAttribute("user_name");

需要注意的地方是request.getSession() 等同于 request.getSession(true),除非我们确认session一定存在或者sesson不存在时明确有创建session的需要,否则尽量使用request.getSession(false)。在使用request.getSession()函数,通常在action中检查是否有某个变量/标记存放在session中。这个场景中可能出现没有session存在的情况,正常的判断应该是这样:

HttpSession session = request.getSession(false); 
 if (session != null) {      
     String user_name = session.getAttribute("user_name"); 
 }  


【投机取巧】:

如果项目中用到了Spring(其实只要是Java的稍大的项目,Spring是一个很好的选择),对session的操作就方便多了。如果需要在 Session中取值,可以用WebUtils工具(org.springframework.web.util.WebUtils)的 getSessionAttribute(HttpServletRequest request, String name)方法,看看高手写的源码吧:哈哈。。

  public static Object getSessionAttribute(HttpServletRequest request, String name) {    
  Assert.notNull(request, "Request must not be null");   
  HttpSession session = request.getSession(false);  
  return (session != null ? session.getAttribute(name) : null);
 }

注:Assert是Spring工具包中的一个工具,用来判断一些验证操作,本例中用来判断reqeust是否为空,若为空就抛异常。

上面的代码又可以简洁一下啦,看吧:

String user_name = WebUtils.getSessionAttribute(reqeust, "user_name"); 




2.9.8 session对象

session对象也是一个非常常用的对象,这个对象代表一次用户会话。一次用户会话的含义是:从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开为止,这个过程就是一次会话。
session通常用于跟踪用户的会话信息,如判断用户是否登录系统,或者在购物车应用中,用于跟踪用户购买的商品等。

session范围内的属性可以在多个页面的跳转之间共享。一旦关闭浏览器,即session结束,session范围内的属性将全部丢失。

session对象是HttpSession的实例,HttpSession有如下两个常用的方法:

setAttribute(String attName , Object attValue):设置session范围内attName属性的值为attValue。

getAttribute(String attName):返回session范围内attName属性的值。

下面的示例演示了一个购物车应用,以下是陈列商品的JSP页面代码。

程序清单:codes22.9jspObjectshop.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>选择物品购买</TITLE>
</HEAD>
<BODY>
<FORM METHOD=POST ACTION="processBuy.jsp">
书籍:<INPUT TYPE="checkbox" NAME="item" value="book"><br>
电脑:<INPUT TYPE="checkbox" NAME="item" value="computer"><br>
汽车:<INPUT TYPE="checkbox" NAME="item" value="car"><br>
<INPUT TYPE="submit" value="购买">
</FORM>
</BODY>
</HTML>

这个页面几乎没有动态的JSP部分,全部是静态的HTML内容。该页面包含一个表单,表单里包含3个复选按钮,用于选择想购买的物品,表单由processBuy.jsp页面处理,其页面的代码如下:

程序清单:codes22.9jspObjectprocessBuy.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" import="java.
util.*"%>
<%
//取出session范围的itemMap属性
Map<String,Integer> itemMap = (Map<String,Integer>)session
.getAttribute("itemMap");
//如果Map对象为空,则初始化Map对象
if (itemMap == null)
{
itemMap = new HashMap<String,Integer>();
itemMap.put("书籍" , 0);
itemMap.put("电脑" , 0);
itemMap.put("汽车" , 0);
}
//获取上个页面的请求参数
String[] buys = request.getParameterValues("item");
//遍历数组的各元素
for (String item : buys)
{
//如果item为book,表示选择购买书籍
if(item.equals("book"))
{
int num1 = itemMap.get("书籍").intValue();
//将书籍key对应的数量加1
itemMap.put("书籍" , num1 + 1);
}
//如果item为computer,表示选择购买电脑
else if (item.equals("computer"))
{
int num2 = itemMap.get("电脑").intValue();
//将电脑key对应的数量加1
itemMap.put("电脑" , num2 + 1);
}
//如果item为car,表示选择购买汽车
else if (item.equals("car"))
{
int num3 = itemMap.get("汽车").intValue();
//将汽车key对应的数量加1
itemMap.put("汽车" , num3 + 1);
}
}
//将itemMap对象放到设置成session范围的itemMap属性
session.setAttribute("itemMap" , itemMap);
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>购买的物品列表</TITLE>
</HEAD>
<BODY>
您所购买的物品:<br>
书籍:<%=itemMap.get("书籍")%>本<br>
电脑:<%=itemMap.get("电脑")%>台<br>
汽车:<%=itemMap.get("汽车")%>辆<p>
<a href="shop.jsp">再次购买</a>
</BODY>
</HTML>

上面页面中粗体字代码使用session来保证itemMap对象在一次会话中有效,这使得该购物车系统可以反复购买,只要浏览器不关闭,购买的物品信息就不会丢失,图2.31显示的是多次购买后的效果。

[转载]关于request和session详解
图2.31  利用session记录购物车信息
考虑session本身的目的,通常只应该把与用户会话状态相关的信息放入session范围内。不要仅仅为了2个页面之间交换信息,就将该信息放入session范围内。如果仅仅为了2个页面交换信息,可以将该信息放入request范围内,然后forward请求即可。

关于session还有一点需要指出,session机制通常用于保存客户端的状态信息,这些状态信息需要保存到Web服务器的硬盘上,所以要求session里的属性值必须是可序列化的,否则将会引发不可序列化的异常。

session的属性值可以是任何可序列化的Java对象。



9.3.1 单例模式

有些时候,允许自由创建某个类的实例没有意义,还可能造成系统性能下降(因为创建对象所带来的系统开销问题)。例如整个系统只有一个窗口管理器,只有一个假脱机打印设备;在Java EE应用中可能只需要一个数据库引擎访问点,Hibernate访问时只需要一个SessionFactory实例,如果在系统中为它们创建多个实例就没有太大的意义。

如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式就被称为单例模式。

对Spring框架而言,可以在配置Bean实例时指定scope="singleton"来配置单例模式。不仅如此,如果配置<bean .../>元素时没有指定scope属性,则该Bean实例默认是单例的行为方式。

Spring推荐将所有业务逻辑组件、DAO组件、数据源组件等配置成单例的行为方式,因为这些组件无须保存任何用户状态,故所有客户端都可共享这些业务逻辑组件、DAO组件,因此推荐将这些组件配置成单例模式的行为方式。

如果不借助Spring框架,我们也可手动实现单例模式。为了保证该类只能产生一个实例,程序不能允许自由创建该类的对象,而是只允许为该类创建一个对象。为了避免程序自由创建该类的实例,我们使用private修饰该类的构造器,从而将该类的构造器隐藏起来。

将该类的构造器隐藏起来,则需要提供一个public方法作为该类的访问点,用于创建该类的对象,且该方法必须使用static修饰(因为调用该方法之前还不存在对象,因此调用该方法的不可能是对象,只能是类)。

除此之外,该类还必须缓存已经创建的对象,否则该类无法知道是否曾经创建过实例,也就无法保证只创建一个实例。为此该类需要使用一个静态属性来保存曾经创建的实例,且该属性需要被静态方法访问,所以该属性也应使用static修饰。

基于上面的介绍,下面程序创建了一个单例类。

程序清单:codes99.3SingletonTestSingleton.java

class Singleton
{
//使用一个变量来缓存曾经创建的实例
private static Singleton instance;
//将构造器使用private修饰,隐藏该构造器
private Singleton(){}
//提供一个静态方法,用于返回Singleton实例
//该方法可以加入自定义的控制,保证只产生一个Singleton对象
public static Singleton getInstance()
{
//如果instance为null,表明还不曾创建Singleton对象
//如果instance不为null,则表明已经创建了Singleton对象,将不会执行该方法
if (instance == null)
{
//创建一个Singleton对象,并将其缓存起来
instance = new Singleton();
}
return instance;
}
}
public class TestSingleton
{
public static void main(String[] args)
{
//创建Singleton对象不能通过构造器,只能通过getInstance方法
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
//将输出true
System.out.println(s1 == s2);
}
}

上面程序中第一行粗体字代码使用了一个静态属性来保存已创建的Singleton实例,程序第二段粗体字代码用于判断系统是否已经创建过Singleton实例——如果已经创建过Singleton实例,则直接返回该Singleton实例即可。

正是通过上面第二段粗体字代码提供的控制逻辑,从而保证了Singleton类只能产生一个实例。所以在TestSingleton类的main方法中看到两次产生的Singleton对象实际上是同一个对象。

在Java EE应用中,单例模式是一种应用非常广泛的设计模式,应用中许多组件都只需要单个实例,下面介绍的工厂模式里的工厂也只需要单个实例……

使用单例模式主要有如下两个优势:

减少创建Java实例所带来的系统开销。

便于系统跟踪单个Java实例的生命周期、实例状态等。



1. Object getAttribute( String name ) ;
获取与指定名字相关联的session属性值。
2. Enumeration getAttributeNames() ;
取得session内所有属性的集合。

3. long getCreationTime() ;
返回session的创建时间,最小单位千分之一秒。

4. String getId() ;
取得session标识。

5. long getLastAccessedTime() ;
返回与当前session相关的客户端最后一次访问的时间,由1970-01-01算起,单位毫秒。

6. int getMaxInactiveInterval( int interval ) ;
返回总时间,以秒为单位,表示session的有效时间(session不活动时间)。-1为永不过期。

7. ServletContext getServletContext() ;
返回一个该JSP页面对应的ServletContext对象实例。

8. HttpSessionContext getSessionContext() ;


9. Object getValue( String name ) ;
取得指定名称的session变量值,不推荐使用。

10. String[] getValueNames() ;
取得所有session变量的名称的集合,不推荐使用。

11. void invalidate() ;
销毁这个session对象。

12. boolean isNew() ;
判断一个session是否由服务器产生,但是客户端并没有使用。

13. void pubValue( String name, Object value ) ;
添加一个session变量,不推荐使用。

14. void removeValue( String name ) ;
移除一个session变量的值,不推荐使用。

15. void setAttribute( String name, String value ) ;
设置指定名称的session属性值。

16. void setMaxInactiveInterval( int interval ) ;
设置session的有效期。

17. void removeAttribute( String name ) ;
移除指定名称的session属性。
分享到:
评论

相关推荐

    四个范围 pagecontext request session application

    四个范围代码详解 pagecontext request session application

    jsp全部内置对象详解

    jsp全部内置对象详解,out request response session application

    EL表达式 (详解)

    它们基本上就和JSP的pageContext、request、session和application一样; 在EL中,这四个隐含对象只能用来取得范围属性值,即getAttribute(String name),却不能取得 其他相关信息。 例如:我们要取得session中...

    对laravel的session获取与存取方法详解

    视图获取 session {{ Session::get('user_name') }} 一次性session(验证提示) ...以上这篇对laravel的session获取与存取方法详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支

    django框架cookie和session用法实例详解

    本文实例讲述了django框架cookie和session用法。分享给大家供大家参考,具体如下: 首先知道http协议 http协议它是无状态的协议,验证的信息不会保留 基于请求响应,短连接 cookie 指一段小信息,内部是一组组的键值...

    jsp基础精华详解

    HttpSession session = request.getSession(); session.setAttribute("name", "zhangsan"); session.setAttribute("pwd", "aaa"); String name = (String) session.getAttribute("name"); 2.cookie: //创建Cookie ...

    Python模拟登录requests.Session应用详解

    会话对象requests.Session能够跨请求地保持某些参数,比如cookies,即在同一个Session实例发出的所有请求都保持同一个cookies,而requests模块每次会自动处理cookies,这样就很方便地处理登录时的cookies问题。...

    JSP语法之隐式对象详解

    了解JSP 隐式对象的分类和组成 能够运用隐式对象进行JSP 编程 理解Page、Request、Session 和Application 范围的区别

    实例详解JSP内置对象

    实例详解JSP内置对象 jsp九种内置对象:request, reponse, out, session, application, config, pagecontext, page, exception.

    python中requests库session对象的妙用详解

    requests库的session对象能够帮我们跨请求保持某些参数,也会在同一个session实例发出的所有请求之间保持cookies。 举个栗子,跨请求保持cookies,在命令行上输入下面命令: # 创建一个session对象 s = requests....

    Struts_config.xml详解

    scope="request" //指定ActionForm Bean的存在范围,可选值为request和session。默认为session &gt;&gt;&gt;&gt; suffix="" // 指定填充当前 Action 的关联 FormBean 时,要添加到请求参数名称的后缀,因此,如果请求参数名为 ...

    看完这个系列所有爬虫都easy!(一)爬虫介绍与request库使用

    Response对象的属性和方法3.request的请求头详解4.post请求与json对象的接受5.在header中设置cookie5.在header中设置session 1:爬虫的流程介绍 确认需求:你需要什么东西?你需要美女的图片 寻找需求:哪里能找到...

    EL表达式详解关于web的问题

    好东西,希望对你有帮助 pageContext.getAttribute("username") -&gt; request.getAttribute("username") -&gt; session.getAttribute("username") -&gt; application.getAttribute("username")

    详解Python requests 超时和重试的方法

    超时又可分为连接超时和读取超时。 连接超时 连接超时指的是在你的客户端实现到远端机器端口的连接时(对应的是 connect() ),Request 等待的秒数。 import time import requests url = '...

    J2EE应用开发详解

    76 5.5.2 JavaBean动作 78 5.6 隐式对象 78 5.6.1 request对象 78 5.6.2 response对象 78 5.6.3 application对象 78 5.6.4 out对象 79 5.6.5 page对象 79 5.6.6 session对象 79 5.6.7 exception对象 80 5.6.8 ...

    Django框架设置cookies与获取cookies操作详解

    在Django里面,使用Cookie和Session看起来好像是一样的,使用的方式都是request.COOKIES[XXX]和request.session[XXX],其中XXX是您想要取得的东西的key, 很久以前,写过一篇 django怎么处理session 的文章:django ...

    python爬虫使用cookie登录详解

    Cookie,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的。那么我们可以利用...

    北大青鸟aspnet全教程课件

    北大青鸟 课件 北大青鸟全课程PPT PAGE对象详解 北大青鸟全课程PPT WEB response request详解 北大青鸟全课程PPT WEB 服务器控件详解 北大青鸟全课程PPTHTML控件...Application、Session和Cookie对象详解 北大青鸟课件

    对laravel的csrf 防御机制详解,及form中csrf_token()的存在介绍

    CSRF是Cross Site Request Forgery的缩写,看起来和XSS差不多的样子,但是其原理正好相反,XSS是利用合法用户获取其信息,而CSRF是伪造成合法用户发起请求。具体操作原理看google。。 二、Laravel的CSRF防御过程 ...

    详解django.contirb.auth-认证

    auth模块有两个middleware:AuthenticationMiddleware和SessionAuthenticationMiddleware。 AuthenticationMiddleware负责向request添加user属性 class AuthenticationMiddleware(object): def process_request...

Global site tag (gtag.js) - Google Analytics