文章目录
Session是服务器端技术,服务器在运行时可以为每个用户的浏览器创建一个其独享的Session对象,由于Session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的资源放在各自的Session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的Session中取出数据为用户服务
Session基础知识
工作原理
Cookie类似于检查客户身上的“通行证”来确定客户身份的话,那么 Session 机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了
实现方式
通过 Cookie 实现
- Session 的实现需要使用Cookie作为识别标志。Session 不能依据 HTTP 连接判断是否为同一个客户,因此服务器向客户端发送一个名为JSESSIONID的 Cookie ,它的值为该Session的ID。Sessin依据该Cookie来识别是否为同一用户
- 这边的JSESSIONID只是个名字,可以随便修改的。配置服务器的设置
- 该Cookie 为服务器自动生成的,它的 maxAge属性一般为 -1,表示仅当前浏览器内有效(包括子窗口),关闭浏览器失效,各浏览器不共享
- 这会有一个问题,当你关闭浏览器,在重开,就会是另一个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);
- 注意:第一次访问的时候,因为JSESSIONID是放在Cookie中,伴随浏览器访问传入,所以第一次访问的时候是没有的。request.getRequestedSessionId() 返回为空。(不同的浏览器实现也不一定一样。这点在Firefox试验是没问题的,但是Chrome中会有出入)
通过 URL 重写实现
- 针对客户端不支持Cookie的情况,可以通过 URL 重写实现Session
- response.encodeURL(String url) 实现 URL 地址的重写。如果重定向可以这么写:response.sendRedirect(response.encodeRedirectURL("/"))
// 通过 重写URL实现
response.encodeURL("/");
response.encodeRedirectURL("/");
response.sendRedirect(response.encodeRedirectURL("/"));
- 可以在服务器配置,取消重写的功能。配置Tomcat 的即可
Session Api 操作
- Session 的创建:封装在
javax.servlet.http.HttpSession对象中,可以通过request.getSession()获取
HttpSession session = request.getSession();//不存在,返回空
HttpSession session = request.getSession(true);//不存在,新建一个
- Session 的ID
String sessionId = session.getId();
- 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));
- Session路径
Session 在客户端对应同一个窗口,没有路径访问问题,同一个servletContext 下的servlet/jsp共享同一个Session ,前提是同一个客户端窗口
Session 的生命周期
-
Session在用户第一次访问服务器的时候自动创建。只有访问JSP、Servlet等程序才会创建Session(是访问到getSession()代码时), 只访问 HTML、 等静态资源并不会创建Session。 如果尚未生成Session ,也可以使用request.getSession(true)强制生成
-
Session生成后,只要用户继续访问,服务器就会更新Session 的最后访问时间,并维护该 Session 。用户每访问服务器一次,无论是否读写 Session ,服务器都认为该用户的 Session “活跃(active)”了一次
-
关闭浏览器,不会让 Session 结束,Session 是服务器管理的,只有当 session.invalidate() 代码或者配置好的有效时间到了,Session 才会结束
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 的比较
- 从存取方式上比较
- Cookie 中只能存ASCII字符串,其他需要编码。不能直接存 java 对象
- Session 中可以存取任何类型的数据,直接保存JavaBean
- 从隐私安全上比较
- Cookie存储在客户端,会存在风险。所以一般一些敏感信息,如密码等尽量不要放入 Cookie,并且对Cookie 信息加密。提交到服务器在解密,保证安全性
- Session 存储在服务器,安全多了
- 从有效期上比较
- Cookie 的有效期只要设置Cookie 的maxAge即可
- Session 如果设置的有效期过长,会导致服务器累计的 Session 过多,导致内存溢出
- 从对服务器负担上比较
- Cookie无负担,所以比如大型的网站,电商等都会使用Cookie 追踪客户会话
- Session 过多就会影响服务器了