目录
2.Session 域的生命周期
2.1 Session 的创建
2.2 Session 的销毁
3. 那么, session 被销毁后, 其中存放的属性不就都访问不到了吗, 有何良策?
3.1 Cookie 与 session 的相伴相生
3.2 Session 活化钝化自力更生
最后
? 在 java 中 Session 域对象能将数据存储在服务器端, 它可以存放各种类别的数据, 相比只能存储字符串的 cookie, 能给开发人员存储数据提供很大的便利, 是一名优秀的后端开发人员必须掌握的技术. 此次, 我将先介绍一下 Session 域的生命周期, 再结合一个 cookie 和 session 的例子, 讲一讲他们互相配合的大致使用方式, 还有 session 活化, 钝化的使用.
2.Session 域的生命周期
2.1 Session 的创建
? 前面提到, session 域是将数据存储在服务器端的, 于是, Session 在用户第一次访问服务器, 即第一次访问 jsp 页面或 servlet 时会被创建. 而数据存储在服务器中, 是不是会产生无法和客户端一一对应的情况呢? 有 2 个用户访问你的服务器, 你在 Session 中给他们分别创建了一个名为 "user" 的属性, 那么你怎么知道哪个 "user" 对应哪个用户呢? 所以, 其实在 Session 被创建的同时, 浏览器中就会被添加一个 cookie, 他的名字叫 "JSESSIONID", 是一个很长的随机字符串, 而服务器就可以用这个 cookie 作为标识, 精确地访问到对应用户. 比如用户 1 的 "JSESSIONID" 可能为 "E39BB9C...", 而用户 2 的 "JSESSIONID" 为 "78DD984...".
2.2 Session 的销毁
? 现在, 我们已经知道 session 是如何产生的了, 但是, 不弄明白他什么时候被销毁, 相信大家也不敢轻易使用的. 服务器会把长时间不用的 session 清除掉, 默认这个时间是 30 分钟, 可以在 web.xml 中设置标签里的标签, 单位是分钟, 比如设为 60, 他的默认销毁时间就会变成 1 小时. 还有一种情况, 就是调用 session 的 invalidate 方法强制销毁. 这也就导致关闭服务器的时候会销毁 session, 因为关闭服务器的时候服务器会自动调用 invalidate 方法清除所有 session.
3. 那么, session 被销毁后, 其中存放的属性不就都访问不到了吗, 有何良策?
? 将 session 的标签设为 10080(60247), 即 7 天后销毁? 此为下策, 虽然在不关闭服务器的情况下, 勉强可以产生类似 cookie 的长时间保存数据的效果. 但是, 要知道 session 的数据是存储在服务器内存中的, 随着用户的增加, session 域对象势必会迅猛增加, 而它们存储的数据将是海量的, 如此你还敢把 session 在服务器中存放 7 天?
? 有两种方法可以避免这种情况. 一, 不给 session 设置 7 天的有效期, 而是用 cookie 来存储那 7 天有效期. 因为 cookie 是存放在客户端的, 不会对服务器造成太大的压力, 每次通过 cookie 存储一些关键数据, 并通过数据库查找到完整数据, 并存放在已经失效的 session 中, 就成了一条可达之路. 二, 可以设置 session 的活化钝化, 这样 session 在 30 分钟后不会消除, 而是会钝化到硬盘中, 在 session 被使用的时候, 就又将钝化后的文件活化到内存中供调用. 下面, 我将对这两种方法通过实例进行详细地讲解.
3.1 Cookie 与 session 的相伴相生
? 首先, 我们需要一个记住密码的选项:
<input type="checkbox" name="remember" value="rememberMe" checked="checked"/> 记住我
? 然后在 servlet 中获取这个参数, 并且在判断用户名和密码都正确之后, 将账号和密码用 #隔开存在 cookie 中, 并设置有效期 7 天, 这个 cookie 是在客户端的, 不用担心服务器压力太大.
- String rememberMe = request.getParameter("remember");
- if(用户名密码正确){
- if(rememberMe.equals("rememberMe")) {
- Cookie cookie = new Cookie("user",username+"#"+password);
- cookie.setMaxAge(7*24*60*60);
- cookie.setPath(request.getContextPath());
- response.addCookie(cookie);
- }
- }
? 再之后写 filter, 先写注解, 然后写内容: 1. 先将 requset 和 response 转化成 http 模式的, 然后获取 session.2. 判断如果 session 中没有 user 这个属性了, 从 cookie 中查找 user 这个 cookie, 如果找到了, 获取用户名和密码, 然后用 userService 根据用户名和密码在数据库中查找对应的 UserBean 对象, 并再次存放到 session 中, 最后放行.
- @WebFilter(filterName="UserFilter",urlPatterns="/client/*",dispatcherTypes= {
- DispatcherType.REQUEST,
- DispatcherType.FORWARD,
- DispatcherType.INCLUDE
- })
- public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest) req;
- HttpServletResponse response = (HttpServletResponse) resp;
- HttpSession session = request.getSession();
- if(session.getAttribute("user")==null) {
- Cookie[] cookies = request.getCookies();
- Cookie cookie = CookieUtil.findCookieByName(cookies, "user");
- if(cookie!=null) {
- String[] userinfo = cookie.getValue().split("#");
- String username = userinfo[0];
- String password = userinfo[1];
- UserService userService = new UserServiceImpl();
- try {
- User user = (User)userService.login(username, password);
- session.setAttribute("user", user);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- chain.doFilter(request, response);
- }
? 如此, 便通过 cookie 和 session 的巧妙合作, 完成了一次长达 7 天的自动登录功能.
3.2 Session 活化钝化自力更生
? 首先, 要实现这么操作, 需要先去配置文件里走一遭, 因为虽然默认 session 的活化是开启的, 但钝化是关闭的. 考虑尽量不影响别的使用这个 tomcat 的项目的正常使用的情况下, 我们只针对这个 Web 项目开启钝化. 这需要在 / WebRoot/META-INF 目录下创建 context.xml 文件, 在里面写下以下内容:
- <?xml version="1.0" encoding="UTF-8"?>
- <Context>
- <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
- <Store className="org.apache.catalina.session.FileStore" directory="zhangA" />
- </Manager>
- </Context>
? 这样, 就可以让 session 在 1 分钟没有操作后被钝化到 tomcat 工作路径的 zhangA 文件夹下. 我们可以先找一找, 或者写一个监听器来验证验证. 那么我是先去工作路径找了, 果然, 在 TomCat8.5\work\Catalina\localhost\bookstore 下出现了一个名为 zhangA 的文件夹, 而其中, 正是我们刚刚钝化掉的 session 文件. 那么再测试下监听吧, 首先我们让 User 实现 HttpSessionActivationListener 和 Serializable 这两个接口. 接着, 在 sessionDidActivate 方法中输出 "我被活化了", 在另一个方法中输出 "我被钝化了". 然后重启服务器, 再次登录观察输出. 一分钟后, 看到控制台输出 "我被钝化了" 了, 我们再次刷新网页. 因为之前 filter 没删的原因, 在 client 下的网页每次运行都会检测 session 中有没有 user 这个属性, 所以控制台立刻输出了 "我被活化了". 至此, 活化钝化测试完美收官.
- // 部分代码
- import java.io.Serializable;
- import javax.servlet.http.HttpSessionActivationListener;
- import javax.servlet.http.HttpSessionEvent;
- public class User implements HttpSessionActivationListener,Serializable{
- @Override
- public void sessionDidActivate(HttpSessionEvent arg0) {
- // TODO Auto-generated method stub
- System.out.println("我被活化了");
- }
- @Override
- public void sessionWillPassivate(HttpSessionEvent arg0) {
- // TODO Auto-generated method stub
- System.out.println("我被钝化了");
- }
- }
最后
希望这篇文章能帮到大家更加了解 session.
来源: http://www.bubuko.com/infodetail-3101380.html