Java中Session详解

1、什么是 Session

HTTP协议 ( http://www.w3.org/Protocols/ )是“一次性单向”协议。

服务端不能主动连接客户端,只能被动等待并答复客户端请求。客户端连接服务端,发出一个HTTP Request,服务端处理请求,并且返回一个HTTP Response给客户端,本次HTTP Request-Response Cycle结束。

我们看到,HTTP协议本身并不能支持服务端保存客户端的状态信息。于是,Web Server中引入了session的概念,用来保存客户端的状态信息。

这里用一个形象的比喻来解释session的工作方式。假设Web Server是一个商场的存包处,HTTP Request是一个顾客,第一次来到存包处,管理员把顾客的物品存放在某一个柜子里面(这个柜子就相当于Session),然后把一个号码牌交给这个顾客,作为取包凭证(这个号码牌就是Session ID)。顾客(HTTP Request)下一次来的时候,就要把号码牌(Session ID)交给存包处(Web Server)的管理员。管理员根据号码牌(Session ID)找到相应的柜子(Session),根据顾客(HTTP Request)的请求,Web Server可以取出、更换、添加柜子(Session)中的物品,Web Server也可以让顾客(HTTP Request)的号码牌和号码牌对应的柜子(Session)失效。顾客(HTTP Request)的忘性很大,管理员在顾客回去的时候(HTTP Response)都要重新提醒顾客记住自己的号码牌(Session ID)。这样,顾客(HTTP Request)下次来的时候,就又带着号码牌回来了。

我们可以看到,Session ID实际上是在客户端和服务端之间通过HTTP Request和HTTP Response传来传去的。

我们看到,号码牌(Session ID)必须包含在HTTP Request里面。关于HTTP Request的具体格式,请参见HTTP协议(http://www.w3.org/Protocols/ )。这里只做一个简单的介绍。
Java Web Server(即Servlet/JSP Server)中,Session ID用jsessionid表示(请参见Servlet规范)。

 

2、HttpSession 的常用方法

String getId()    用于返回当前 HttpSession 对象关联的会话标识号

long getCreationTime()    返回 Session 创建的时间,时间戳形式

long getLastAcessTime()    返回客户端上一次发送 Session 相关请求的时间,也是时间戳

void setMaxInactiveInterval(int interval)    设置当前会话的超时时间

boolean isNew()    判断当前 HttpSession是否是新创建的

void invalidate()    用于强制使 Session 无效

ServletContext getServletContext()    返回当前Web程序的 ServletContext 对象

void setAttribute(String name,Object value)    将一个名称和一个对象 关联存储到 HttpSession 中

String getAttribute()    用于从当前 HttpSession 对象中返回指定属性对象

void removeAttribute(String name)    用于从当前 HttpSession 中删除指定名称的属性

 

3、Session 超时管理

在一定时间内,当用户客户端一直没有请求访问,那么服务器就会认为客户端已经结束请求。并且将客户端会话所对应的 HttpSession 对象变成垃圾,等待垃圾收集器将其从内存中彻底清除。反之,如果浏览器超时后,再次向服务器发起请求,那么,服务器则会创建一个新的 HttpSession 对象,并为其分配一个新的 ID 属性。

我们可以在 web.xml 里设置这个超时时间,其默认有 Servlet 容器定义。在<tomcat 安装目录> \conf\web.xml 文件中(大概 576 行),可以找到如下段配置信息

  1. <session-config>
  2.      <session-timeout>30</session-timeout>
  3.  </session-config>

在上面的信息中,设置的时间是以分钟为单位的,即 Tomcat 服务器的默认会话超时时间是 30 分钟。如果设置会话超时时间是 0 或一个负数,则永不超时(这样会产生大量垃圾)。

如果需要单独设置,可以在对应项目下的 web.xml 里添加配置。

需要注意的是,除了等待会话超时外,可以通过 invalidate() 方法强制使会话失效。

 

4、Session案例(1)——实现用户登录

老规矩,新建 web 项目 ServletTest ,src下新建 com.liuyanzhao 包

(1)新建 Login.html

在 WebContent 下新建 Login.html , 代码如下

  1. <form action="/ServletTest/LoginServlet" method="post">
  2.         用户名:<input type="text" name="username" /> <br />
  3.         密 码:<input type="password" name="password" /> <br />
  4.         <input type="submit" value="提交" id="sub" />
  5. </form>

(2)新建 LoginServlet 类

在 com.liuyanzhao 包下新建 LoginServlet.java ,代码如下

  1. package com.liuyanzhao;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. /*
  9.  * @author LiuYanzhao
  10.  */
  11. public class LoginServlet extends HttpServlet{
  12.     @Override
  13.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14.         //防止乱码
  15.         resp.setContentType("text/html;charset=utf-8");
  16.         String username = req.getParameter("username");
  17.         String password = req.getParameter("password");
  18.         PrintWriter out = resp.getWriter();
  19.         //假设正确的账号是admin,密码是123456
  20.         if("admin".equals(username)&&"123456".equals(password)) {
  21.             User user = new User();
  22.             user.setUsername(username);
  23.             user.setPassword(password);
  24.             req.getSession().setAttribute("user", user);
  25.             resp.sendRedirect("/ServletTest/IndexServlet");
  26.         } else {
  27.             out.print("用户名和密码错误,登录失败!");
  28.         }
  29.     }
  30.     @Override
  31.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  32.         doGet(req, resp);
  33.     }
  34. }

(3)新建 IndexServlet 类

在 com.liuyanzhao 包下新建 IndexServlet.java,代码如下

  1. package com.liuyanzhao;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.Cookie;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import javax.servlet.http.HttpSession;
  10. /*
  11.  * @author LiuYanzhao
  12.  */
  13. public class IndexServlet extends HttpServlet{
  14.     @Override
  15.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  16.         //解决乱码问题
  17.         resp.setContentType("text/html;charset=utf-8");
  18.         PrintWriter out = resp.getWriter();
  19.         //创建或者获取保存用户信息的Session对象
  20.         HttpSession session = req.getSession();
  21.         User user = (User)session.getAttribute("user");
  22.         if(user==null) {
  23.             out.print("您还没有登录,请<a href='/ServletTest/Login.html'>登录</a>");
  24.         } else {
  25.             out.print("您已登录,欢迎你,"+user.getUsername()+"<br/>");
  26.             out.print("<a href='/ServletTest/LogoutServlet'>退出</a>");
  27.             //创建 Cookie 存放 Session 的标识号
  28.             Cookie cookie = new Cookie("JSESSIONID", session.getId());
  29.             cookie.setMaxAge(60*30); //30分钟
  30.             cookie.setPath("/ServletTest");
  31.             resp.addCookie(cookie);
  32.         }
  33.     }
  34.     @Override
  35.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  36.         doGet(req, resp);
  37.     }
  38. }

(4)新建 LogoutServlet 类

在 com.liuyanzhao 包下新建 LogoutServlet.java,代码如下

  1. package com.liuyanzhao;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.Cookie;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import javax.servlet.http.HttpSession;
  10. import org.apache.catalina.User;
  11. /*
  12.  * @author LiuYanzhao
  13.  */
  14. public class LogoutServlet extends HttpServlet{
  15.     @Override
  16.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  17.         //将Session对象中的 User 对象移除
  18.         req.getSession().removeAttribute("user");
  19.         resp.sendRedirect("/ServletTest/IndexServlet");
  20.     }
  21.     @Override
  22.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  23.         doGet(req, resp);
  24.     }
  25. }

(5)在 web.xml 添加映射

  1.  <servlet>
  2.      <servlet-name>LoginServlet</servlet-name>
  3.      <servlet-class>com.liuyanzhao.LoginServlet</servlet-class>
  4.  </servlet>
  5.  <servlet-mapping>
  6.      <!-- 映射为 LoginServlet -->
  7.      <servlet-name>LoginServlet</servlet-name>
  8.      <url-pattern>/LoginServlet</url-pattern>
  9.  </servlet-mapping>
  10.  <servlet>
  11.      <servlet-name>LogoutServlet</servlet-name>
  12.      <servlet-class>com.liuyanzhao.LogoutServlet</servlet-class>
  13.  </servlet>
  14.  <servlet-mapping>
  15.      <!-- 映射为 LogoutServlet -->
  16.      <servlet-name>LogoutServlet</servlet-name>
  17.      <url-pattern>/LogoutServlet</url-pattern>
  18.  </servlet-mapping>
  19. <servlet>
  20.      <servlet-name>IndexServlet</servlet-name>
  21.      <servlet-class>com.liuyanzhao.IndexServlet</servlet-class>
  22.  </servlet>
  23.  <servlet-mapping>
  24.      <!-- 映射为 IndexServlet -->
  25.      <servlet-name>IndexServlet</servlet-name>
  26.      <url-pattern>/IndexServlet</url-pattern>
  27.  </servlet-mapping>

(6)重启 Tomcat ,打开浏览器

首先,可以直接输入localhost:8080/ServletTest/IndexServlet ,这里会直接显示未登录如 ③ ,这里不截图了

① 在地址栏输入url:http://localhost:8080/ServletTest/Login.html

Java中Session详解

② 点击提交

Java中Session详解

登录成功,能显示用户名

③点击退出

Java中Session详解

销毁了 session,退到了登录页面

 

 

本文链接:https://liuyanzhao.com/4915.html

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
言曌

发表评论

:?::razz::sad::evil::!::smile::oops::grin::eek::shock::???::cool::lol::mad::twisted::roll::wink::idea::arrow::neutral::cry::mrgreen: