Session是服务器端技术,服务器在运行时可以为每个用户的浏览器创建一个其独享的Session对象,由于Session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的资源放在各自的Session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的Session中取出数据为用户服务

Session基础知识

工作原理

Cookie类似于检查客户身上的“通行证”来确定客户身份的话,那么 Session 机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了

实现方式

通过 Cookie 实现

  1. Session 的实现需要使用Cookie作为识别标志。Session 不能依据 HTTP 连接判断是否为同一个客户,因此服务器向客户端发送一个名为JSESSIONID的 Cookie ,它的值为该Session的ID。Sessin依据该Cookie来识别是否为同一用户
  2. 这边的JSESSIONID只是个名字,可以随便修改的。配置服务器的设置
  3. 该Cookie 为服务器自动生成的,它的 maxAge属性一般为 -1,表示仅当前浏览器内有效(包括子窗口),关闭浏览器失效,各浏览器不共享
  4. 这会有一个问题,当你关闭浏览器,在重开,就会是另一个Cookie。解决办法:服务器在创建Session的时候回写一个同名的Cookie,并设置maxAge值即可,注意有path(见下图)
// 解决自动生成的cookie为临时性问题,回写一个同名Cookie回去  
Cookie cookie = new Cookie("JSESSIONID",session.getId());         
cookie.setMaxAge(session.getMaxInactiveInterval());  
cookie.setPath(this.getServletContext().getContextPath());  
response.addCookie(cookie); 
  1. 注意:第一次访问的时候,因为JSESSIONID是放在Cookie中,伴随浏览器访问传入,所以第一次访问的时候是没有的。request.getRequestedSessionId() 返回为空。(不同的浏览器实现也不一定一样。这点在Firefox试验是没问题的,但是Chrome中会有出入)

通过 URL 重写实现

  1. 针对客户端不支持Cookie的情况,可以通过 URL 重写实现Session
  2. response.encodeURL(String url) 实现 URL 地址的重写。如果重定向可以这么写:response.sendRedirect(response.encodeRedirectURL("/"))
// 通过 重写URL实现  
response.encodeURL("/");  
response.encodeRedirectURL("/");  
response.sendRedirect(response.encodeRedirectURL("/"));
  1. 可以在服务器配置,取消重写的功能。配置Tomcat 的即可

Session Api 操作

  1. Session 的创建:封装在 javax.servlet.http.HttpSession 对象中,可以通过 request.getSession() 获取
HttpSession session = request.getSession();//不存在,返回空  
HttpSession session = request.getSession(true);//不存在,新建一个 
  1. Session 的ID
String sessionId = session.getId();  
  1. Session 的时间
  • 有效期
// 3-1 有效期  
// get/set MaxInactiveInterval可以设置和获取session的有效期  单位为 秒  
// 也可以通过 <session-config>标签配置在web.xml中 ,单位为分钟  
// tomcat自身的config/web.xml 默认配置session有效期为 30 分钟  
// 如通过setMaxInactiveInterval设置过有效时间,这段代码注掉,时间还是不会改变。  
  
session.setMaxInactiveInterval(1000 * 5);  
int time = session.getMaxInactiveInterval(); 
  • 创建时间
// 3-2 创建时间  
long createTime = session.getCreationTime();//返回long  
Date createDate = new Date(createTime);  
logger.debug("Session创建的时间为 : " + formatDate(createDate)); 
  • 最近访问时间
// 3-3 最近访问时间  
// 客户端只要访问服务器,不管有没有读写session,服务器都会更新最近访问时间,并维护本session  
long accessedTime = session.getLastAccessedTime();//返回long  
Date accessedDate = new Date(accessedTime);  
logger.debug("Session最近访问的时间为 : " + formatDate(accessedDate));  
  1. Session路径
    Session 在客户端对应同一个窗口,没有路径访问问题,同一个servletContext 下的servlet/jsp共享同一个Session ,前提是同一个客户端窗口

Session 的生命周期

  1. Session在用户第一次访问服务器的时候自动创建。只有访问JSP、Servlet等程序才会创建Session(是访问到getSession()代码时), 只访问 HTML、 等静态资源并不会创建Session。 如果尚未生成Session ,也可以使用request.getSession(true)强制生成

  2. Session生成后,只要用户继续访问,服务器就会更新Session 的最后访问时间,并维护该 Session 。用户每访问服务器一次,无论是否读写 Session ,服务器都认为该用户的 Session “活跃(active)”了一次

  3. 关闭浏览器,不会让 Session 结束,Session 是服务器管理的,只有当 session.invalidate() 代码或者配置好的有效时间到了,Session 才会结束

Session的常用方法

Servlet笔记(7):Session详解

测试代码如下

public class SessionServlet extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
//
        boolean isValid = request.isRequestedSessionIdValid();
        System.out.println("请求带过来的session是否有效 : " + isValid);

        // 第一次访问的时候 firefox 为空,而chrome 确是有值的,但是和下面创建的session不是同一个
        String requestedSessionId = request.getRequestedSessionId();
        System.out.println("request获取的SessionID : " + requestedSessionId);

        boolean isFromCookie = request.isRequestedSessionIdFromCookie();
        boolean isFromUrl = request.isRequestedSessionIdFromURL();
        System.out.println("是否是通过Cookie实现: " + isFromCookie + " | 是否是通过URL实现: " + isFromUrl);


        // 1-Session的创建
        //不存在,返回空
        HttpSession session = request.getSession();
        //不存在,新建一个
        session = request.getSession(true);

        System.out.println("获取到的Session 为 : " + session.getClass().getName());

        // 2-Session的ID
        String sessionId = session.getId();
        System.out.println("创建的 Session的ID 为 : " + sessionId);

        // 3-session的时间:三个时间构成了session 的生命周期

        // 3-1 有效期
        // get/set MaxInactiveInterval可以设置和获取session的有效期  单位为 秒
        // 也可以通过 <session-config>标签配置在web.xml中 ,单位为分钟
        // tomcat自身的config/web.xml 默认配置session有效期为 30 分钟
        // 如通过setMaxInactiveInterval设置过有效时间,这段代码注掉,时间还是不会改变。

        session.setMaxInactiveInterval(1000 * 5);
        int time = session.getMaxInactiveInterval();
        System.out.println("Session的有效期 为 : " + time);


        // 3-2 创建时间
        long createTime = session.getCreationTime();
        Date createDate = new Date(createTime);
        System.out.println("Session创建的时间为 : " + formatDate(createDate));

        // 3-3 最近访问时间
        // 客户端只要访问服务器,不管有没有读写session,服务器都会更新最近访问时间,并维护本session
        long accessedTime = session.getLastAccessedTime();
        Date accessedDate = new Date(accessedTime);
        System.out.println("Session最近访问的时间为 : " + formatDate(accessedDate));


        // 4-常用方法

        // 4-1设置 Attribute 是key-value类型
        // key为String 类型, value为 Object 。可以放置javaBean。比Cookie强大。

        session.setAttribute("user", "Sam");
        String userName = (String) session.getAttribute("user");
        System.out.println("Session中放置的数据   : " + userName);

        session.removeAttribute("user");

        // 4-2 让session失效
        session.invalidate();

//      // 通过 重写URL实现
//      response.encodeURL("/");
//      response.encodeRedirectURL("/");
//      response.sendRedirect(response.encodeRedirectURL("/"));
    }

    /**
     * 简单转换时间
     *
     * @param date
     * @return
     */
    private String formatDate(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String strDate = format.format(date);
        return strDate;

    }
}

Session 和 Cookie 的比较

  1. 从存取方式上比较
  • Cookie 中只能存ASCII字符串,其他需要编码。不能直接存 java 对象
  • Session 中可以存取任何类型的数据,直接保存JavaBean
  1. 从隐私安全上比较
  • Cookie存储在客户端,会存在风险。所以一般一些敏感信息,如密码等尽量不要放入 Cookie,并且对Cookie 信息加密。提交到服务器在解密,保证安全性
  • Session 存储在服务器,安全多了
  1. 从有效期上比较
  • Cookie 的有效期只要设置Cookie 的maxAge即可
  • Session 如果设置的有效期过长,会导致服务器累计的 Session 过多,导致内存溢出
  1. 从对服务器负担上比较
  • Cookie无负担,所以比如大型的网站,电商等都会使用Cookie 追踪客户会话
  • Session 过多就会影响服务器了

参考

  1. 源码地址
  2. Servlet学习笔记(七):Session详解

Servlet笔记(7):Session详解

相关文章: