Java web session失效时间配置及详解

一 关于session

1 session机制

在web程序中使用session来记录客户端状态,是服务器端使用的一种记录客户端状态的机制。

session技术则是服务端的解决方案,通过服务器保持状态的。

session通常被翻译成会话,通常大家把客户端(浏览器)与服务器之间的一系列交互动作称为一个session。基于此,会提到session持续的时间以及session过程中进行了什么操作等。

另外session也指服务端为客户端开辟的存储空间,在其中保存的信息就是用于保存状态。基于此,会提到向session中存放了什么内容以及会根据键值从session中匹配的内容等。

通常来讲,要使用session必须要先创建session,具体来说是在服务器端运行的过程中创建的,在Java web中通过调用HttpServletRequest的getSession()方法(使用true作为参数)创建的。创建session的同时,服务器会为该session生成一个唯一的session id,这个session id 在随后的请求中会被用来重新获取已经创建的session。

当然,在创建session后,就能往session中添加内容了,但这些内容只会保存在服务器中,发送到客户端的只有session id。当客户端再次发送请求的时候,会将这个session id带上(通过session id 辨别是哪个客户端),服务器接受到请求之后就会根据session id 找到对应的session,从而再次使用。这样的交互过程使得用户的状态能够保持。

2 什么是session

1)session是不同于cookie的一种记录客户状态的机制,保存在服务端(cookie客户端)。

2)客户端浏览器在访问服务端的时候,服务器把客户端信息以某种形式记录在服务器上,这就是session。

3 实现用户登陆

在Java中session对应的类为Javax.servlet.HttpSession类。每个访问者对应一个session对象,所有该客户的状态信息都保存在这个session对象中。session对象是在客户端第一次请求服务器的时候创建的。session是一种key-value的属性对,通过getAttribute(StringKey)和setAttribute(String key,Object value)方法读写客户状态信息。

在servlet(action、controller等)可以通过request.getSession()方法获取该客户的session:

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

    session.setAttribute("loginTime", new Date()); // 设置Session中的属性

    System.out.println("登录时间为:" +(Date)session.getAttribute("loginTime")); // 获取Session属性

request还可通过getSession(boolean create)来获取session,区别在于如该客户的session不存在,request.getSession()方法会返回null,而getSession(true)会创建session再将session返回。

在servlet中必须使用request来编程式获取HttpSession对象,而Jsp中内置了Session隐藏对象,可以直接使用。当声明了<%@page session="false">,则session隐藏对象不可以使用。

Person.java


 

package test.session.bean;

import java.io.Serializable;
import java.util.Date;

public class Person implements Serializable{
    private String username;
    private String password;
    private int age;
    private Date birthday;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Person(String username, String password, int age) {
        super();
        this.username = username;
        this.password = password;
        this.age = age;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public Person(String username, String password, int age, Date birthday) {
        super();
        this.username = username;
        this.password = password;
        this.age = age;
        this.birthday = birthday;
    }
}
 


index.jsp


 

<%@ page language="java" pageEncoding="UTF-8"%>
<jsp:directive.page import="test.session.bean.Person"/>
<jsp:directive.page import="java.text.SimpleDateFormat"/>
<jsp:directive.page import="java.text.DateFormat"/>
<jsp:directive.page import="java.util.Date"/>
<%!
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");         // 日期格式化器
%>
<%
    response.setCharacterEncoding("UTF-8");        // 设置request编码
    Person[] persons =
    {           
       // 基础数据,保存三个人的信息
        new Person("zhangsan","zhangsan", 34, dateFormat.parse
        ("1982-01-01")),
        new Person("lisi","lisi", 23, dateFormat.parse
        ("1984-02-21")),
        new Person("wangmazi", "wangmazi",23, dateFormat.parse
        ("1994-09-12"))
     };

    String message = "";                      // 要显示的消息

    if(request.getMethod().equals("POST"))
    { 
        // 如果是POST登录       
        for(Person person :persons)
        {           
           // 遍历基础数据,验证账号、密码
           // 如果用户名正确且密码正确
           if(person.getUsername().equalsIgnoreCase(request.getParameter("username"))&&person.getPassword().equals(request.getParameter("password")))
           {              
               // 登录成功,设置将用户的信息以及登录时间保存到Session
               session.setAttribute("person", person);                   // 保存登录的Person
               session.setAttribute("loginTime", new Date());          // 保存登录的时间              
               response.sendRedirect(request.getContextPath() + "/welcome.jsp");
               return;
            }
        }      
        message = "用户名密码不匹配,登录失败。";       // 登录失败
    }
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">
<html>

 <form action="session.jsp" method="post">
    <label>用户名</label> <input type="text" value="" name="username"><br>
    <label>密   码</label><input  type="password" value="" name="password">
    <input type="submit" value="登陆">
 </form>
</html>


welcome.jsp


<%@ page language="java" pageEncoding="UTF-8"%>
<jsp:directive.page import="test.session.bean.Person"/>
<jsp:directive.page import="java.text.SimpleDateFormat"/>
<jsp:directive.page import="java.text.DateFormat"/>
<jsp:directive.page import="java.util.Date"/>
<%!
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");         // 日期格式化器
%>
<%
    Person person =(Person)session.getAttribute("person");                       // 获取登录的person
    Date loginTime =(Date)session.getAttribute("loginTime");                     // 获取登录时间
%>
            <table>
               <tr><td>您的姓名:</td>
                   <td><%= person.getUsername()%></td>
               </tr>
               <tr><td>登录时间:</td>
                   <td><%= loginTime%></td>
               </tr>
               <tr><td>您的年龄:</td>
                   <td><%= person.getAge()%></td>
               </tr>
               <tr><td>您的生日:</td>
                   <td><%=dateFormat.format(person.getBirthday()) %></td>
               </tr>
            </table>


ps: 当多个客户端执行程序时,服务器会保存多个客户端的Session。获取Session的时候也不需要声明获取谁的Session。Session机制决定了当前客户只会获取到自己的Session,而不会获取到别人的Session。各客户的Session也彼此独立,互不可见。

虽然session的使用比cookie方便,但过多的session存储在服务器的内存中,会对服务器造成压力。

3 session的生命周期

session保存在服务器端,为求响应速度,一般被存放在内存中。每个访问的用户都有一个独立的session,为避免内存溢出,session内容应该精简。

session在用户第一次访问服务器时创建,只有访问jsp、servlet等程序时才会创建session,如果只访问html、image等静态资源并不会创建session。如果尚未生成session,也可以使用request.getSession(true)强制生成session。

session生成后,如若用户继续访问,服务器就会更新session的最后访问时间,并维护该session。用户每访问一次服务端(无论读写),服务端都认为该用户的session活跃(active)了一次。

4 session有效期

因用户访问服务器越来越多造成session越来越多,未防止内存溢出,服务器会把长时间没有活跃的session从内存中删除,这个时间点就是session的超时时间。如超过了超时时间没有访问服务器,那么session自动失效

session的超时时间为maxInactiveInterval属性,可通过对应的getMaxInactiveInterval()获取,通过setMaxInactiveInterval(long interval)修改。

5 session的常用方法

session中包括了很多方法,常用如下:

1)void setAttribute(String attribute,Object value):设置session属性。value参数可以为任何Java Object。一般为Java bean。value信息一般不宜过大。

2)String getAttribute(String attribute):返回session属性

3)Enumeration getAttributeNames(): 返回session中存在的session属性名称

4) void removeAttribute(String attribute):移除session属性

5) String getId():返回session id,该id由服务器自动创建,不会重复

6)long getCreationTime():返回session的创建日期,返回类型为long,常被转换成Date类型。

7)long getLastAccessedTime():返回session的最后活跃时间,返回类型为long

8) int getMaxInactiveInterval():返回session的超时时间,单位为秒。超过该时间没有访问,服务器认为session失效

9)void setMaxInactiveInterval(int second):设置session的超时时间,单位为秒

10)void putValue(String attribute,Object value):不推荐,已经被setAttribute(String attribute, Object Value)替代

11)Object getValue(String attribute):不被推荐的方法。已经被getAttribute(String attr)替代

12)boolean isNew():返回该Session是否是>新创建的

13)void invalidate():使该Session失效

6 session与浏览器

session需要客户端浏览器的支持,毕竟session需要使用cookie作为标志。鉴于http协议无状态,session不能根据http连接判断是否为同一客户,服务器需向浏览器发送一个名为JSESSIONID的Cookie,其值为该session的id。session根据该cookie来识别是否为同一用户。

该cookie为服务器自动生成,它的maxAge属性一般为-1,表示只在当前浏览器中有效,且各浏览器窗口间不共享,关闭浏览器就会失效

即在同一计算机的两个浏览器窗口访问服务时,会生成两个不同的session,但由浏览器窗口内的链接、脚本等打开的新窗口(也就是说不是双击桌面浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的cookie,因此会共享一个session。

PS:新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择“在新窗口中打开”时,子窗口便可以访问父窗口的Session。

如果客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另一种解决方案:URL地址重写。

7 URL地址重写

URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。HttpServletResponse类提供了encodeURL(Stringurl)实现URL地址重写,例如:


 

<td> <a href="<%=response.encodeURL("index.jsp?c=1&wd=Java") %>"> Homepage</a> </td>


该方法会自动判断客户端是否支持Cookie。如果客户端支持Cookie,会将URL原封不动地输出来。如果客户端不支持Cookie,则会将用户Session的id重写到URL中。重写后的输出可能是这样的:


<td> <a href="index.jsp;jsessionid=0CCD096E7F8D97B0BE608AFDC3E1931E?c=1&wd=Java">Homepage</a> </td>


即在文件名的后面,在URL参数的前面添加了字符串“;jsessionid=XXX”。其中XXX为Session的id。分析一下可以知道,增添的jsessionid字符串既不会影响请求的文件名,也不会影响提交的地址栏参数。用户单击这个链接的时候会把Session的id通过URL提交到服务器上,服务器通过解析URL地址获得Session的id。

二 Java 设置session超时(失效)的时间

tomcat中session的默认超时时间是30分钟,可以通过三种方法设置失效时间。

1 在web容器中设置(如tomcat)

在tomcat-7.0\conf\web.xml中设置:

可以根据需要修改,负数或者0表示不限制session失效时间,一般取值在1-1440(一分钟到一天)。这个session的设置时间是根据服务器来计算,不是根据客户端计算。调试的时候应该修改服务端时间测试,而不是客户端。

2 在项目的web.xml中设置

这里是1440分钟失效

3 通过Java代码设置

session.setMaxInactiveInterval(30*60);//以秒为单位,即在没有活动30分钟后,session将失效

4 优先级

三种方式中:1<2<3

三 怎么动态监控session

写一个监听器,实现HttpSessionListener, HttpSessionAttributeListener两个接口,然后放在web.xml

四 session过期演示

 

1  演示案例

1.1 配置session过期时间 4分钟

1.2 实体类UserInfo.java


package test.session.bean;

public class UserInfo {
    private int id;
    private String username;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public UserInfo() {
        super();
    }
    public UserInfo(int id, String username) {
        super();
        this.id = id;
        this.username = username;
    }
}


1.3 请求类 UserServlet


package test.session.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import test.session.bean.UserInfo;

public class UserServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    public UserServlet() {
        super();
        
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setUsername("风间净琉璃");
        
        request.getSession().setAttribute("userInfo", userInfo);
        request.getSession().setAttribute("loginMessage", "用户登陆成功");
        
        request.getRequestDispatcher("showUserInfo.jsp").forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
    }

}


1.4 session监听器 SessionListener


package test.session.listener;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class SessionListener implements HttpSessionListener,HttpSessionAttributeListener{

    private  long attributeAddTime;
    @Override
    public void attributeAdded(HttpSessionBindingEvent event) {
        System.out.println("添加属性:"+event.getName());
        attributeAddTime = System.currentTimeMillis();
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent event) {
        System.out.println("移除属性"+event.getName());
        long attributeRemoveTime = System.currentTimeMillis();
        long attributeSaveTime=(attributeRemoveTime-attributeAddTime)/1000;
        System.out.println("数据保存时间"+attributeSaveTime+"秒");
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent event) {
        System.out.println("更改属性:"+event.getName());
    }

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("session 创建 ");
        System.out.println("session id: "+session.getId());
        System.out.println("session 创建时间: "+session.getCreationTime());
        System.out.println("session 最后活跃时间:"+session.getLastAccessedTime());
        System.out.println("session 最大过期时间 :"+session.getMaxInactiveInterval());
        System.out.println("session 中的所有属性值"+session.getAttributeNames());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("session 销毁:"+session.getId()+"||"+session.getCreationTime()+"||"+session.getLastAccessedTime()+"||"+session.getMaxInactiveInterval()+" "+session.getAttributeNames());
    }   

}


1.4 展示用户页面 showUserInfo.jsp


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" isELIgnored="false" pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>展示用户信息页面</title>
</head>
<body>
<form action="http://127.0.0.1:8080/sessiontest/UserServlet" method="post">
    <input type="submit" value="登陆">
</form>
<h6>用户名:</h6>${userInfo.username}
<h6>登陆信息:</h6>${loginMessage}
</body>
</html>


1.5 演示

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值