9.20JavaWeb之ServletSession

9.20JavaWeb之ServletSession

什么是Session以及Session产生的过程

什么是Session?

  • 服务端会话技术

Session的产生过程:

  • 浏览器访问 Web 服务器的资源时,服务器可以为每个用户浏览器创建一个 Session 对象

  • 每个浏览器独占一个 Session 对象。

由于每个浏览器独占一个 Session,所以用户在访问服务器的资源时,可以把数据保存在各自的 Session 中。当用户再次访问该服务器中的其它资源时,其它资源可以从 Session 中取出数据,为用户服务。

Session工作原理

原理图:

 

过程分析:

  1. 客户端第一次请求会话对象时,服务端会创建一个Session对象,并分配一个SessionID给该对象

  2. 服务端将SessionID以Cookie的形式发送给客户端浏览器(Name:JESSIONID,value:SessionID)

  3. 浏览器再次发送请求的时候携带SessionID,服务端根据SessionID找到Session对象

注意:

  • 流程中的 Cookie 是容器自动生成的,它的 maxAge 属性取值为 -1,表示仅当前浏览器有效。

  • 浏览器关闭时,对应的 Session 并没有失效与此 Session 对应的 Cookie 已失效,导致浏览器无法再通过 Cookie 获取服务器端的 Session 对象。

  • 同一浏览器的不同窗口共享同一 Session 对象不同浏览器窗口之间不能共享 Session 对象。--->导致一个账号不能多个浏览器登录的根本原因

SessionAPI

HttpServletRequest.getSession() 方法获得 HttpSession 对象:

//获取session对象
HttpSession session = request.getSession();

HttpSession接口当中对Session对象操作的方法:

返回值类型方法描述
long getCreationTime() 返回创建 Session 的时间。
String getId() 返回获取 Seesion 的唯一的 ID。
long getLastAccessedTime() 返回客户端上一次发送与此 Session 关联的请求的时间。
int getMaxInactiveInterval() 返回在无任何操作的情况下,Session 失效的时间,以秒为单位。
ServletContext getServletContext() 返回 Session 所属的 ServletContext 对象。
void invalidate() 使 Session 失效。
void setMaxInactiveInterval(int interval) 指定在无任何操作的情况下,Session 失效的时间,以秒为单位。负数表示 Session 永远不会失效。--->Session 对象在服务器中驻留一段时间后没有被使用,就会被销毁,这个时间就是 Session 的过期时间。

Session与Cookie对比

不同点CookieSession
存储位置不同 Cookie 将数据存放在客户端浏览器内存中或硬盘上。 Session 将数据存储在服务器端。
大小和数量限制不同 浏览器对 Cookie 的大小和数量有限制。 Session 的大小和数量一般不受限制。
存放数据类型不同 Cookie 中保存的是字符串。 Session 中保存的是对象。
安全性不同 Cookie 明文传递,安全性低,他人可以分析存放在本地的 Cookie 并进行 Cookie 欺骗。 Session 存在服务器端,安全性较高。
对服务器造成的压力不同 Cookie 保存在客户端,不占用服务器资源。 Session 保存在服务端,每一个用户独占一个 Session。若并发访问的用户十分多,就会占用大量服务端资源。
跨域支持上不同 Cookie 支持跨域名访问。 Session 不支持跨域名访问。

设置Session过期时间的方法

  • <session-config>元素

  • setMaxInactiveInterval()方法


<session-config>元素

在web.xml当中进行配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   <!--设置session的过期时间-->
   <session-config>
       <session-timeout>10</session-timeout>
   </session-config>
</web-app>
  • <session-timeout>元素用来指定默认 Session 过期时间,以分钟为单位,该元素值必须为整数。

  • <session-timeout>元素的值为零或负数,表示 Session 永远不会过期。

调用setMaxInactiveInterval()方法
//设置会话的过期时间
request.getSession().setMaxInactiveInterval(100);

示例代码:

获取SessionID:

package com.example.HttpServletRequestDemo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* 记录上次访问的时间--->服务端生成Session
* @since JDK 1.8
* @date 2021/09/20
* @author Lucifer
*/
@WebServlet(name = "LoginTimeSessionServlet", value = "/LoginTimeSessionServlet")
public class LoginTimeSessionServlet extends HttpServlet {
   //设置UID
   private static final long serialVersionUID = 1L;

   //Get
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
       //设置响应字符集
       resp.setContentType("text/html;charset=UTF-8");
       PrintWriter writer = resp.getWriter();
       writer.write(
               "<h1>JunkingBoy</h1>"
               + "<h3>Jun Welcome!!!</h3>"
      );
       //记录当前时间--->Date类
       Date date = new Date();
       //设置时间格式
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       //获取会话创建时间
       Date CreationTime = new Date(req.getSession().getCreationTime());
       //会话上次关联的时间
       Date LastAccessedTime = new Date(req.getSession().getLastAccessedTime());
       //格式化时间
       String sDate = sdf.format(date);

       //将时间赋值到Session域对象当中
       req.getSession().setAttribute("lastTime", sDate);
       //设置会话失效时间--->s
       req.getSession().setMaxInactiveInterval(100);

       //将Session中的信息输出到界面
       writer.write(
       "<h3>当前时间:" + sDate + "</h3>"
           + "当前会话的SessionID: " + req.getSession().getId() + "<br/>"
           + "创建此会话的时间为:" + sdf.format(CreationTime) + "<br/>"
           + "Sesssion上次关联的时间为:" + sdf.format(LastAccessedTime) + "<br/>"
           + "话保持打开状态的最大时间间隔:" + req.getSession().getMaxInactiveInterval() + "<br/>"
      );
       //浏览器不支持COOKIE
       String url = resp.encodeURL("/HttpServletRequestDemo_war_exploded/SecondTimeServlet");
       writer.write("<a href=" + url + ">再次访问</a>");
  }
}

跳转连接:

package com.example.HttpServletRequestDemo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* 二次访问Servlet的类
* @since JDK 1.8
* @date 2021/09/20
* @author Lucifer
*/
@WebServlet(name = "SecondTimeServlet", value = "/SecondTimeServlet")
public class SecondTimeServlet extends HttpServlet {
   //设置UID
   private static final long serialVersionUID = 1L;

   //Get
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //设置响应字符集
       resp.setContentType("text/html;charset=UTF-8");
       //打印内容
       PrintWriter writer = resp.getWriter();
       //session当中获取上次访问的时间
       String value = (String) req.getSession().getAttribute("lastTime");
       //不是第一次访问
       writer.write(
       "<h1>JunkingBoy</h1>"
               + "<h3>Jun,欢迎您的归来</h3><h3>您上次的时间是" + value + "</h3>"
      );
       Date date = new Date();
       //时间的格式
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       //格式化
       String sDate = sdf.format(date);
       //将当前时间赋值到session域对象中
       req.getSession().setAttribute("lastTime", sDate);
  }

   //Post
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
  }
}

Session的生命周期

  • Session对象创建

  • Session对象销毁


Session对象创建

Servlet容器第一次调用request.getSession()方法时创建

注意:

  • 当客户端访问的 Web 资源是 HTML,CSS,图片等静态资源时,服务器不会创建 Session 对象。

Session对象销毁

Session对象销毁的情况:

  • Session 过期;

  • 调用 session.invalidate() 方法,手动销毁 Session;

  • 服务器关闭或者应用被卸载。

Session域对象

Session 对象也是一种域对象,它可以对属性进行操作,进而实现会话中请求之间的数据通讯和数据共享。

javax.servlet.http.HttpSession 接口中定义了一系列操作属性的方法:

返回值类型方法描述
void setAttribute(String name, Object o) 把一个 Java 对象与一个属性名绑定,并将它作为一个属性存放到 Session 对象中。 参数 name 为属性名,参数 object 为属性值。
Object getAttribute(String name) 根据指定的属性名 name,返回 Session 对象中对应的属性值。
void removeAttribute(String name) 从 Session 对象中移除属性名为 name 的属性。
Enumeration getAttributeNames() 用于返回 Session 对象中的所有属性名的枚举集合。

Servlet三大域

  • Session

  • request

  • ServletContext


不同requestSessionServletContext
类型 javax.servlet.http.HttpServletRequest javax.servlet.http.HttpSession javax.servlet.ServletContext
创建 客户端向容器发送请求时创建。 容器第一次调用 getSession() 方法时创建。 Servlet 容器启动时创建。
销毁 容器对这次请求做出响应后销毁。 Session 销毁的时机: 关闭服务器或应用被卸载。Session 过期,默认为 30 分钟。手动调用 session.invalidate() 方法进行销毁。 容器关闭或者 Web 应用被移除时销毁。
有效范围 只对当前请求涉及的 Servlet 有效。 Session 对本次会话期间的所有 Servlet 都有效。 对整个 Web 应用内的所有 Servlet 有效。
数量 Web 应用中的所有 Servlet 实例都可以有多个 request 对象。 Web 应用中可以有多个 Session,多个 Servet 实例可以共享同一 Session 对象。 在整个 Web 应用中只有一个 Context 对象。
数据共享 每一次请求都是一个新的 request 对象。 通过和请求转发的配合使用可以实现一次请求中 Web 组件之间共享的数据。 每一次会话都是一个新的 Session 对象。 通过 Session 域对象可以实现一次会话中的多个请求之间共享数据。 在一个应用中有且只有一个 Context 对象,作用于整个 Web 应用,可以实现多次会话之间的数据共享。

概括:

可以抽象的理解为:

  • 环境域(ServletContextPageContext域)

    • 请求域

    • 服务域

理解为类似的修饰符从:publiCprotectedpagecontext则是private

It's a lonely road!!!
原文地址:https://www.cnblogs.com/JunkingBoy/p/15315072.html