Session 是服务器与浏览器之间维持状态的一种机制。Session 相当于是一份记录,当客户端和服务器之间建立起连接时,服务器会创建一个 Session,并生成一个类似于 SessionID 的标识符,用来唯一标识这个 Session。当客户端请求到达服务器时,服务器会通过这个标识符找到对应的 Session,进而获取会话数据。
Session 可以存储用户状态信息,帮助我们在不同请求之间维持某些状态,例如登录状态、购物车信息等。而对于开发人员来说,Session.getAttribute 方法则是常常使用的。在这篇文章中将介绍 Session 以及如何使用 Session.getAttribute 方法来获取 Web 应用程序中的值。
## Session 的工作原理
Session 的工作原理可以简单概括为以下几个步骤:
1. 用户打开浏览器,请求连接服务器;
2. 服务器建立与客户端的连接时,创建一个 Session,并为 Session 分配一个唯一的 ID;
3. 服务器在响应中返回响应头设置 Set-Cookie,其中包含了该 Session 的 ID;
4. 第二次请求时,浏览器会将保存在 Cookie 中的 Session ID 发送给服务器;
5. 服务器通过 Session ID 获取到对应的 Session,从而访问到 Session 中的数据。
小提示:在使用 Session 时,需要慎重考虑存储的数据量,如果存储过多,将会影响应用程序的性能。
## Session 的创建与维护
在 Java Web 应用程序中,创建 Session 是通过调用 HttpServletRequest.getSession 方法实现的。该方法会先在请求头中查找是否存在 Session ID,如果存在,则返回该 ID 对应的 Session,否则会新建一个 Session 并为其分配一个新的 ID。
```java
public HttpSession getSession(boolean create) {
HttpSession s = doGetSession(false);
if (s == null && create) {
s = createSession();
if (s == null) {
throw new IllegalStateException(sm.getString("request.getSession.createFail"));
}
setSession(s);
}
return s;
}
```
当客户端首次访问我们的应用程序,Servlet 容器会为其创建一个新的 Session,然后将这个 Session 返回给客户端。在得到该 Session 后,应用程序可以将一些数据存储在该 Session 中,例如保存用户名、登录状态等信息。当客户端再一次发送请求到服务器时,Session ID 会以 Cookie 的形式被携带过去,从而服务器会通过这个 Session ID 获取到客户端之前设置的 Session 数据,实现维持状态的目的。
## Session 数据的存储与获取
通过 HttpSession 对象,我们可以存储任意类型的数据,当需要获取某一个属性或者值时,只需要调用 HttpSession.getAttribute(String key) 方法即可,其中 key 为属性名。
```java
// 存储值
session.setAttribute("key", "value");
// 获取值
Object value = session.getAttribute("key");
```
在存储数据时,需要注意值的类型,存储的值必须是可序列化的。可以是 String、Integer、Boolean 或者自定义的实体类等等。
例如,我们将用户登录状态存储在 Session 中,实现记录用户的登录与退出。
```java
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
User user = new User("xxx", "xxx@qq.com");
session.setAttribute("user", user);
// 跳转到首页
resp.sendRedirect("/index.jsp");
}
}
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("user");
// 跳转到登录页面
resp.sendRedirect("/login.jsp");
}
}
```
在 LoginServlet 中,我们将 User 对象存储到 Session 中;在 LogoutServlet 中,我们从 Session 中移除该对象,从而实现用户的退出。
## Attribute 生命期和过期时间
在 Web 应用程序中,Session 类似于一个黑盒子,在内部存储了众多的属性值,这些属性值的生命周期和过期时间是值得关注的问题。
Session 属性的生命周期一般随着该 Session 的存活时间而被一直存在。而在默认情况下,Servlet 容器会在任何一个 Session 上进行操作时自动设置过期时间。若在该过期时间内,该 Session 未进行过任何一次操作,该 Session 就会被销毁。
当然,我们也可以通过 Session 的 setMaxInactiveInterval() 方法,手动设置 Session 在没有访问的情况下的过期时间。该方法接受一个以秒为单位的整数参数。例如,设置 Session 在一小时未被使用时过期。
```java
session.setMaxInactiveInterval(60 * 60);
```
同样地,setAttribute 方法也可以设置生命周期。例如,我们需要将一个数据存储在 Session 中,但是只想让其在本次请求和下一次请求中生效。
```java
public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
// 存储值,限定生命周期
session.setAttribute("key", "value", HttpSessionContext.DEBUG | HttpSessionContext.SESSION_SCOPE);
// 获取值
Object value = session.getAttribute("key");
// 移除值
session.removeAttribute("key");
// 马上过期并移除所有属性
session.invalidate();
}
}
```
setAttribute 方法除了可以设置值和键外,还可以接受一个 int 类型的参数,用于指定属性的生命周期和作用域,其中:
1. HttpSessionContext.APPLICATION_SCOPE:生命周期为当前的应用程序。
2. HttpSessionContext.SESSION_SCOPE:生命周期为当前的 Session。
3. HttpSessionContext.DEBUG:调试模式开启。
例如,我们在上面的代码中,将 Session 进行了本次请求和下一次请求的生命周期限制。
## 如何使用 Session.getAttribute 方法获取值
在我们开发一个 Web 应用程序时,最常用的操作之一就是从 Session 中获取值。Session.getAttribute 方法就是用于获取 Session 中的值的。
```java
Object value = session.getAttribute("key");
```
该方法接受一个 String 类型参数 key,表示要获取的值的键名。如果当前 Session 中已经存在值,则返回该值;否则返回空。
在获取值时,需要注意类型转换的问题。根据我们之前的介绍,Session 可以存储任意类类型的数据,因此需要根据实际存储的值来进行类型转换。例如,我们从 Session 中获取登录用户信息时,需要将其转换成对应的实体类。
```java
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
User user = (User)session.getAttribute("user");
// 将 User 对象传递给渲染页面的代码
req.setAttribute("user", user);
// 转发到首页
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
}
```
在上述代码中,我们通过 (User)session.getAttribute("user") 进行了类型转换,将从 Session 中获取到的 Object 类型的值 user 转换成了 User 类型。这样便可以将值传递给下一个页面或者数据访问层。
## 小结
通过本文的介绍,我们了解了 Session 的工作原理、创建与维护,以及如何存储与获取 Session 数据。在使用 Session 时,需要慎重考虑存储的数据量和类型,以及对应的生命周期和过期时间。使用 Session.getAttribute 方法可以方便地获取 Web 应用程序中的值,需要注意类型转换的问题。通过合理地使用 Session,可以帮助我们维持应用程序中一系列的状态信息。