`

关于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属性。
分享到:
评论

相关推荐

    Cookie与session机制详解

    ### Cookie与Session机制详解 #### 一、Cookie与Session的概念及区别 在Web开发中,为了保持用户的状态信息,通常会用到两种技术:Cookie和Session。这两种技术都是用来跟踪用户的浏览活动,但它们的工作原理有所...

    jsp页面间通过request/session传值

    ### JSP 页面间通过 Request/Session 传值详解 #### 一、背景介绍 在 Web 开发中,尤其是在 JavaServer Pages (JSP) 技术中,数据在不同页面之间的传递是一项基本且重要的功能。本篇文章将详细介绍如何利用 JSP 的 ...

    struts2访问request,session,application作用域

    ### Struts2 访问 Request、Session 和 Application 作用域详解 #### 一、引言 Struts2 是一个基于 Java 的开源 Web 开发框架,它继承了 Struts1 的优秀特性并进行了改进,提供了更加灵活和强大的功能。在 Struts2...

    ASP.NET的 Session 详解

    ASP.NET 的 Session 详解 Session 模型简介 Session 是什么呢?简单来说就是服务器给客户端的一个编号。当一台 WWW 服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站。 当每个用户首次与这台 WWW ...

    jsp中session的用法详解

    "jsp中session的用法详解" jsp 中 session 的使用方法可以帮助开发者追踪用户的操作过程,而不需要担心追踪的实现细节。Session 是一种服务器端的机制,用于存储用户的信息,以便在多个页面之间共享数据。 在 jsp ...

    SIP(Session Initiation Protocol )详解

    **SIP(Session Initiation Protocol)详解** SIP(Session Initiation Protocol)是一种应用层控制协议,用于发起、管理和终止多媒体通信会话,如语音通话、视频会议、即时消息等。它在互联网协议(IP)网络上运行...

    详解SpringBoot中Session超时原理说明

    在 SpringBoot 中,Session 的超时时间可以通过 `request.getSession().getMaxInactiveInterval()` 方法来获取当前 Session 的超时时间。如果当前 Session 的超时时间超过了设置的值,那么 Session 就会超时失效。 ...

    经典收藏Cookie和Session

    ### 经典收藏:Cookie与Session机制详解 #### 一、Cookie机制与Session机制的区别 在Web开发中,为了维持用户的会话状态,通常有两种常用的技术:Cookie与Session。这两种技术各有特点,适用于不同的场景。 - **...

    Cookie与Session机制

    【Cookie与Session机制详解】 在Web开发中,为了在用户的不同请求之间保持状态,Cookie和Session成为了关键的技术手段。它们都是用于实现会话跟踪(Session Tracking),确保用户在整个会话期间的操作能够被正确...

    Django中的session用法详解

    【Django中的Session用法详解】 一、Session的概念 ...总之,Django的Session机制是构建Web应用程序中处理用户会话的关键工具,理解并正确配置和使用Session能够帮助开发出更安全、高效的Web应用。

    JSP获取HTTP header信息(request)例子

    ### JSP获取HTTP Header信息(Request)详解 在Web开发中,了解如何获取HTTP请求头信息是非常重要的,因为这些信息能够帮助我们更好地理解客户端环境、优化响应策略以及进行安全性检查等。下面将详细介绍JSP中如何...

    用 Jsp 的 Session 机制编写的购物车程序.txt

    ### 使用JSP的Session机制编写的购物车程序详解 #### 一、背景介绍 在现代Web应用开发中,用户状态管理是一项重要的功能。对于需要跟踪用户活动或存储用户特定信息的应用来说,`Session`机制提供了非常实用的支持。...

    JAVA之cookie与session

    ### JAVA之cookie与session #### 一、Cookie与Session的概念 **Cookie** 与 **Session** 是两种...在实际开发过程中,合理利用 Cookie 和 Session 的特性,可以有效提升用户体验,同时确保应用程序的安全性和稳定性。

    关于jsp中的JSP详解

    4. **JSP内置对象**:JSP提供了九个内置对象,如`request`, `response`, `session`, `pageContext`, `out`, `exception`等,它们提供了对HTTP请求、响应、会话和异常处理的直接访问。 5. **EL(Expression Language...

    django项目搭建与Session使用详解

    以下是对Django项目搭建与Session使用详解的详细介绍: 1. **Django 项目创建** - 使用 `django-admin startproject` 命令创建一个新的Django项目,例如 `django-admin startproject djangocommon`。 - 在项目...

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

    ### Django框架中Cookie和Session的用法详解 #### 1. Django框架中Cookie和Session的基本概念 在Django框架中,Cookie和Session是实现Web应用程序用户状态管理的重要机制。它们广泛应用于用户身份验证、页面个性化...

    ASP网络开发详解完全手册

    接着,手册深入讲解了ASP的核心组件,如Request对象、Response对象、Session对象和Application对象。Request对象用于获取来自客户端的数据,如表单提交的信息;Response对象则负责向客户端发送响应,如HTML代码;...

Global site tag (gtag.js) - Google Analytics