HttpSession接口实现数据共享

简介: HttpSession接口实现数据共享

介绍完了cookie,不得不介绍我们的HttpSession接口


一.介绍

1)HttpSession接口来自于Servlet规范下一个接口。存在于Tomcat中servlet-api.jar,其实现类由Http服务器提供。Tomcat提供实现类存在于servlet-api.jar


2.png


2)如果两个Servlet来自于同一个网站,并且为同一个浏览器/用户提供服务,此时便可以借助于HttpSession对象进行数据共享。


3)开发人员习惯于将HttpSession接口修饰对象称为【会话作用域对象】


二.HttpSession 与  Cookie 区别:【面试题】

(1)存储位置:  一个在天上,一个在地下

Cookie:        存放在客户端计算机(浏览器内存/硬盘)

HttpSession:存放在服务端计算机内存

(2)数据类型

Cookie对象存储共享数据类型只能是String

HttpSession对象可以存储任意类型的共享数据Object


(3) 数据数量

一个Cookie对象只能存储一个共享数据,所以这也是为什么当我们去创建Cookie类型的变量的时候,变量名必须不一样。

HttpSession是使用map集合存储共享数据,所以可以存储任意数量共享数据,所以只需要使用会话域对象调用setAttribute方法即可。

(4)参照物

Cookie相当于客户在服务端【会员卡】

HttpSession相当于客户在服务端【私人保险柜】,放的比cookie多

三.代码实现

此处我们还是拿OneServelet和TwoServlet来举例:


同一个网站(myWeb)下OneServlet将数据传递给TwoServlet


首先在OneServlet中将数据存入到我们的session中

public class OneServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        //1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
        HttpSession session = request.getSession();
         //2.将数据添加到用户私人储物柜
        session.setAttribute("key1", 10);
    }
}

浏览器访问/myWeb中T的woServlet,在TwoServlet中编写代码来获取我们的数据。

public class TwoServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        //1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
        HttpSession session = request.getSession();
        //2.从会话作用域对象得到OneServlet提供的共享数据
        Integer num = session.getAttribute("key1");
        System.out.println("获取到的共享数据值为="+num);
    }
}

当然假如我们的用户在获取共享数据的时候不想去使用包装类强转,想使用我们的基本数据类型强转也可以,此时就需要用到一个方法叫做getAttributeNames方法,这个方法可以获取到我们session中使用map集合存储共享数据时的key值,下面来看具体的代码实现吧:此处只需要重写我们TwoServlet中的代码即可。

public class TwoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
        HttpSession session = req.getSession();
        //2.从会话作用域对象得到OneServlet提供的共享数据
        Enumeration keynames=session.getAttributeNames();
        while(keynames.hasMoreElements()){
            //获取到map集合中的每一个key值
            String eachkeyname=(String)keynames.nextElement();
            int eachvalue=(int)session.getAttribute("key1");
            System.out.println("key值为"+eachkeyname+"value值为"+eachvalue);
        }
    }
}

注意事项:

1:当我们使用getAttributeNames获取我们存入到map集合中的所有数据的时候,这个方法的返回值是一个枚举对象,所以需要将我们所获取的所有key值赋给我们的枚举对象。

        2:当获取到所有的key值时,下一步需要使用while循环来遍历我们的枚举对象,方法为hasMoreElements()。

        3:循环内部首先需要获取每一个具体的key值,那么就需要使用我们的nextElements()方法来获取,注意nextElements()方法的返回值为Object,所以此处涉及到我们的强转,假设之前我们的key值类型为String,那么此处的强转类型便为String.

        4:当获取到我们的key值后,此时就需要获取我们的value值,获取方式还是使用我们的Httpsession对象的属性getAttribute方法,getAttribute方法的返回值仍为Object,所以此时获取我们的value值时仍然涉及到我们的强转,因为在OneServlet中我们存储的时候的value值为整形,所以此处的强转类型为int即可。

🆗,说到这里,一个问题戛然而生,之前我们在使用getAttribute方法获取整形类型的共享数据的时候,我们的强转类型为Integer,为什么当我们使用getAttributeNames方法后,此处当我们获取到我们的整型类型的共享数据的时候,我们的强转类型就变为了int呢?

首先先来看之前我们没有使用getAttributeNames的时候,此时假如用户给我们的key1赋了一个null值,然后在另一端接收的时候用户并不知道这个数据是否为null,假如此时不使用包装类进行强转,使用基本类型去进行强转,就会发生空指针异常,因为基本数据的默认值例如int为0,而其包装类Integer的话默认值为null,所以此时使用int进行强转的话,就相当于将null赋值给基本数据类型int,那么就会发生空指针异常,但是包装类就不会发生,因为其是可以存储null的。

一般在实际开发中我们都会拿包装类来进行传参,因为是可以进行

当我们使用getAttributeNames后,此时就相当于一个一个的从Map集合中将key值取出来,此时的key值都是有明确的value值与之对应的,所以不会发生空指针异常,那么即使在获取整形的value值时使用了基本数据类型进行强转也不会发生任何异常。


四.Http服务器如何将用户与HttpSession关联起来?

 答案当然是使用cookie来进行连接,下面我们来看一张图来进行理解:


2.png

当用户第一次访问OneServlet的时候,会在OneServlet中使用请求对象代替Tomcat索要当前的HttpSession对象,在服务器端内部,我们的Tomcat会自动为每一个HttpSession对象设置一个编号(箱号),名为JSESSIONID,当我们在OneServlet中使用setAttribute方法存储数据到我们的HttpSession对象后,此时我们的HttpSession对象便会直接放在我们的Http服务器端,然后将我们的编号JSESSIONID放入到我们的cookie当中,再将我们的cookie放入到http响应协议包的响应头中返回给我们的浏览器,存在我们浏览器的缓存中,如上图所示。

当同一用户在同一网站下第二次访问TwoServlet时,此时发给TwoServlet的请求协议包中便会放入我们之前所收到的来自服务器端的cookie,这个cookie被放入了请求协议包中的请求头中,然后此时服务器端接收到我们的浏览器请求后,tomcat会根据cookie当中的JSESSIONID来判断当前用户是否之前索要到了HttpSession对象以及哪个HttpSession对象是当前这个用户的,从而就找到了之前这个用户第一次请求时在session中用于存储的数据HttpSession对象,然后就可以使用getAttribute方法来获取到数据了。



五.getSession()  与  getSession(false)的区别

1.getSession()

如果当前用户在服务端已经拥有了自己的私人储物柜.要求tomcat将这个私人储物柜进行返回.

如果当前用户在服务端尚未拥有自己的私人储物柜,要求tocmat为当前用户创建一个全新的私人储物柜.


2.getSession(false)

如果当前用户在服务端已经拥有了自己的私人储物柜.要求tomcat将这个私人储物柜进行返回

如果当前用户在服务端尚未拥有自己的私人储物柜,此时Tomcat将返回null


六.HttpSession销毁时机

1.用户与HttpSession关联时使用的Cookie只能存放在浏览器缓存中.

2.在浏览器关闭时,意味着用户与他的HttpSession关系被切断

3.由于Tomcat无法检测浏览器何时关闭,因此在浏览器关闭时并不会导致Tomcat将浏览器关联的HttpSession进行销毁

4.为了解决这个问题,Tomcat为每一个HttpSession对象设置【空闲时间】

   这个空闲时间默认30分钟,如果当前HttpSession对象空闲时间达到30分钟

   此时Tomcat认为用户已经放弃了自己的HttpSession,此时Tomcat就会销毁掉这个HttpSession


七.HttpSession对象空闲时间手动设置

在当前网站/web/WEB-INF/web.xml
                <session-config>
                       <session-timeout>5</session-timeout> <!--当前网站中每一个session最大空闲时间5分钟-->
                </session-config>


相关文章
|
7月前
|
Java Apache
远程调用工具HttpClient工具类封装
java远程调用工具HttpClient工具类类封装
|
7月前
SpringMVC之域对象共享数据
SpringMVC之域对象共享数据
|
7月前
|
缓存 NoSQL Apache
Shiro - 缓存管理与CacheManagerAware接口
Shiro - 缓存管理与CacheManagerAware接口
125 0
|
7月前
|
Java 应用服务中间件 API
Request继承体系及获取请求数据
Request继承体系及获取请求数据
61 0
SpringMVC学习(五):向request域对象共享数据的五种方法
SpringMVC学习(五):向request域对象共享数据的五种方法
140 0
SpringMVC学习(五):向request域对象共享数据的五种方法
|
存储
HttpServletRequest接口实现数据共享
HttpServletRequest接口实现数据共享
162 1
|
存储 应用服务中间件
ServletContext接口实现数据共享
ServletContext接口实现数据共享
162 0
ServletContext接口实现数据共享
|
存储 资源调度 Java
Java Web——Servlet的数据共享方案:HttpSession接口(会话作用域对象)
Java Web——Servlet的数据共享方案:HttpSession接口(会话作用域对象)
Java Web——Servlet的数据共享方案:HttpSession接口(会话作用域对象)
多个Servlet之间实现数据共享
多个Servlet之间实现数据共享
165 0