JWeb之Session

本文详细阐述了Session的工作原理,包括其在服务器端的存储机制、生命周期管理及与cookie的关系。探讨了Session的获取方法、常见问题及解决方案,如Session持久化、Session丢失的假象及其应对策略。

session是域对象,作用范围默认是一次会话

只要浏览器不关闭,客户端请求服务器中的任何一个资源session域对象均有效

一.预习(Session持久化):

这里有些知识点需要提前强调下,我们知道session是服务器端技术,用于在服务器端存储对象,其活跃周期为一次会话

一次会话指客户端浏览器是否被关闭掉

浏览器一旦关闭,服务器端session不会消失,但是客户端浏览器与服务器端的session联系便被取缔

浏览器在此访问服务器还会认识之前的那个session吗?

不会!

所以session有了以下的持久化规则:

  • 每个session域对象创建时都携带有唯一的编号,称为sessionID
  • session域对象创建后,需要将sessionID存储于cookie中并响应会客户端
  • 浏览器在此请求服务器时会携带存储sessionID的cookie,并将此ID与服务器中sessionID对比

1.测试前准备:

  • session设置程序:SetSession.java
  • session校验程序:VerifySession.java

2.代码展示:

***SetSession.java

package controller.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

/**
 * @Author weihuanwen
 * @Date 2019/7/29 8:07
 * @Version 1.0
 */
@WebServlet(urlPatterns = "/ss")
public class SetSession extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        String jessionId = session.getId();
        System.out.println("JSESSIONID ::: "+jessionId);
        Cookie cookie = new Cookie("JSESSIONID",jsessionId);
        cookie.setMaxAge(10*60);
        resp.addCookie(cookie);
    }

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

***VerifySession.java

package controller.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

/**
 * @Author weihuanwen
 * @Date 2019/7/29 8:07
 * @Version 1.0
 */
@WebServlet(urlPatterns = "/vs")
public class VerifySession extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取session
        HttpSession session = req.getSession();
        //获取sessionId
        String jessionId = session.getId();
        System.out.println("JSESSIONID ::: "+jsessionId);
        //执行session手动销毁
        session.invalidate();
    }

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

3.测试

①访问请求路径:http://localhost:8080/sr/ss

前端cookie展示:

 控制台输出展示:

JSESSIONID ::: AE35E1AA194D6BAD0D0E47F8BA8C7AD7

②访问请求路径: http://localhost:8080/sr/vs

前端cookie展示:

 控制台输出展示:

JSESSIONID ::: AE35E1AA194D6BAD0D0E47F8BA8C7AD7

此过程中执行了一次session的手动清除 

③访问请求路径:http://localhost:8080/sr/ss

前端cookie展示:

控制台输出展示:

JSESSIONID ::: 5FEB295741BD9C8439947DE7EFC1C464

④访问请求路径:http://localhost:8080/sr/vs

前端cookie展示:

 控制台输出展示:

JSESSIONID ::: 5FEB295741BD9C8439947DE7EFC1C464

4.总结:

cookie中携带的JSESSIONID指定的session在服务器端下落不明时

①getSession()会生成新的Session对象 

②同时会将新的Session的SessionID响应回前端作为JSESSIONID

二.session的获取

方法描述
HttpSession getSession()获取对应的HttpSession对象
HttpSession getSession(boolean create)获取对应的HttpSession对象

1.HpSession getSession()的内部执行流程

  • 获取名称为"JESSIONID"的cookie
  • cookie==null,创建新的HttpSession对象sessionNew,分配唯一sessionId,并将"JsessionId=sessionID"存入cookie
  • cookie!=null,依据获取SessionId在内存找寻HttpSession对象sessionExist
  • sessionExist==null,创建新的HttpSession对象sessionNew,分配唯一sessionId,并将"JsessionId=sessionID"存入cookie
  • sessionExist!=null,返回sessionExist

2.HttpSession getSession(boolean create)介绍

当create==true时,功能如同getSession()

当create==false时

  • 获取名称为"JESSIONID"的cookie
  • cookie==null,返回null
  • cookie!=null,依据获取SessionId在内存找寻HttpSession对象sessionExist
  • sessionExist==null,返回null
  • sessionExist!=null,返回sessionExist

3.关于网上所谓session获取时的陷阱的个人理解

归结为下面的问题:

"当因为某种原因session被销毁(invalidate)或者自销毁(TimeOut)后,服务器端如何得知其已经被销毁?"

此时需要如下判断:

HttpSession session = req.getSession(false);
if (session != null){
    String jessionId = session.getId();
    System.out.println("JSESSIONID ::: "+jessionId);
}

当需要对session操作且发现session不存在时,是否需要创建新的session已经成为一种需求的问题了!

三.session的其他方法介绍

方法描述
setAttribute(String var1, Object var2)设置session值
setMaxInactiveInterval(int var1)

设置当前会话时间

(session的存货时间)

(单位:秒,设置为负数|0时为永久不超时)

ServletContext getServletContext()获取Servlet上下文对象
long getLastAccessedTime()最后一次成功获取session属性值的时间(EP:1564369071060)
String getId()获取session的唯一编号-->前端的JSESSIONID
long getCreationTime()获取session的创建时间(1970-1-1至创建时的毫秒值)
removeAttribute(String var1)移除session的属性
void invalidate()将session设置失效(tomcat中session默认存活时间为30min)

四."session遗失"的假象

现实中有些用户存在禁止cookie的行为,导致服务器端session"失效"

原因:

用户禁止了cookie后,服务器端接收到请求后获取不到cookie数据

自然解析不到JSESSIONID,所以也就找不到对应的session对象了

解决的方案如下:

  • 客户端提示用户不要禁止cookie
  • url重写

这里着重解释下url重写!

实现方法:

方法描述
HttpServletResponse.encodeURL(String url)用于对表单action和超链接的url地址进行重写
HttpServletResponse.encodeRedirectURL(String url)用于对sendRedirect方法后的url地址进行重写

1.测试前准备:

  • url重写程序:LoseSession.java
  • 重定向目标程序:TargetSession.java
  • 测试标准:重定向前后session的ID一致即可

2.代码展示:

***LoseSession.java

package controller.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

/**
 * @Author weihuanwen
 * @Date 2019/7/29 10:21
 * @Version 1.0
 */
@WebServlet(urlPatterns = "/ls")
public class LoseSession extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //进行url重写
        String sessionID = req.getSession().getId();
        System.out.println("url重写前,LoseSession [sessionID ::: "+sessionID);
        String path = resp.encodeRedirectURL(req.getContextPath()+"/target");
        resp.sendRedirect(path);
    }

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

***TargetSession.java

package controller.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

/**
 * @Author weihuanwen
 * @Date 2019/7/29 11:58
 * @Version 1.0
 */
@WebServlet(urlPatterns = "/target")
public class TargetSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
            主要是确定这里是否会生成新的session对象
            目标:
                这里不会产生新的session对象,而是同url重写前一致
         */
        HttpSession session = req.getSession();
        String sessionID = session.getId();
        System.out.println("url重写后,TargetSession [sessionID ::: "+sessionID);
    }

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

3.测试

①清除客户端浏览器cookie

②访问请求路径:http://localhost:8080/sr/ls

③请求后前端地址栏地址:http://localhost:8080/sr/target

④控制台输出如下:

url重写前,LoseSession [sessionID ::: CBA491CF87C7DD9CFEB51A0D004C563C
url重写后,TargetSession [sessionID ::: CBA491CF87C7DD9CFEB51A0D004C563C

⑤重复②控制台输出如下:

url重写前,LoseSession [sessionID ::: CBA491CF87C7DD9CFEB51A0D004C563C
url重写后,TargetSession [sessionID ::: CBA491CF87C7DD9CFEB51A0D004C563C

4.总结:

使用url重写避免了每次无cookie访问服务时都会生成新session的问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值