第一章:Cookie
1.1 Cookie简介
1.1.1 为什么需要Cookie?
- HTTP是无状态的协议,服务器不能记录浏览器的访问记录,也就是说服务器不能区分两次请求是否由一个客户端发出。这样的设计严重阻碍了Web程序的发展,如:我们在进行网购的时候,买了一台电脑,又买了一部手机,由于HTTP协议是无状态的,如果不通过其他手段,服务器就不能知道用户到底买了什么,而Cookie就是解决方案之一。
1.1.2 Cookie是什么?
- Cookie,翻译是小饼干的意思,实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求的时候都会同时携带该信息并发送给服务器,服务器接收到请求之后,就可以根据该信息处理请求。
- 例如:我们上文说的网上商城,当用户向购物车中添加一个商品的时候,服务器会将这条信息封装成一个Cookie发送给浏览器,浏览器收到Cookie,会将其保存在内存中(
注意
:这里的内存是客户的浏览器的内存,而不是服务器的内存),之后每次向服务器发送请求,浏览器都会携带该Cookie来判断用户到底买了哪些商品,当用户进行结账操作的时候,服务器就可以根据Cookie的信息来做结算了。 - Cookie的用途:
- ① 网上商城的购物车。
- ② 保持用户的登录状态。
- 总而言之,Cookie是一种服务器告诉浏览器以键值对形式存储的少量信息的技术。
1.1.3 Cookie的工作原理
- 总的来看,Cookie像是服务器发送给浏览器的一张
“会员卡”
,浏览器每次向服务器发送请求的时候,都会带着这张“会员卡”
,当服务器看到这张“会员卡”
就可以识别浏览器的身份,换言之,就是客户的身份。 - 实际上,这个所谓的
“会员卡”
就是服务器发送的一个响应头:
- 如上图所示,Set-Cookie这个响应头就是服务器向浏览器发送的
“会员卡”
,这个响应头的名字是Set-Cookie,后面的JSESSIONID=95A92EC1D7CCB4ADFC24584CB316382E和Path=/Test_cookie,是两组键值对的结构即服务器为这个“会员卡”
设置的信息。浏览器收到该信息后会将其保存在内存或硬盘中。 - 当浏览器再次向服务器发送请求的时候就会携带这个Cookie信息:
- 这是浏览器发送的请求报文,中间画红框的就是Cookie的信息,这里可以理解为浏览器这次带有
“会员卡”
再次访问浏览器。 - 于是,浏览器就可以根据Cookie的信息来判断浏览器的状态了。
1.2 Cookie的使用
1.2.1 Cookie的创建和设置
- ① 在Servlet中创建Cookie对象,并添加到Response中。
- ② 打开浏览器访问Servlet程序,服务器将Cookie信息发送给浏览器。
③ 浏览器收到Cookie后会自动保存,那么我们可以在下次浏览器发送请求的时候读取Cookie信息。
示例:
- pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
- index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/app/test1">test1</a>
</body>
</html>
- ViewBaseServlet.java
package com.example.javaweb2;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ViewBaseServlet extends HttpServlet {
private TemplateEngine templateEngine;
@Override
public void init() throws ServletException {
// 获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 创建Thymeleaf解析器对象
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// 给解析器设置参数
// ①HTML是默认模式,明确设置是为了代码更容易理解
templateResolver.setTemplateMode(TemplateMode.HTML);
// ②设置前缀
templateResolver.setPrefix(servletContext.getInitParameter("view-prefix"));
// ③设置后缀
templateResolver.setSuffix(servletContext.getInitParameter("view-suffix"));
// ④设置缓存过期时间(毫秒)
templateResolver.setCacheTTLMs(60000L);
// ⑤设置是否缓存
templateResolver.setCacheable(true);
// ⑥设置服务器端编码方式
templateResolver.setCharacterEncoding("utf-8");
// 创建模板引擎
this.templateEngine = new TemplateEngine();
// 给模板引擎设置模板解析器
this.templateEngine.setTemplateResolver(templateResolver);
}
protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
// 1.设置响应体内容类型和字符集
resp.setContentType("text/html;charset=UTF-8");
// 2.创建WebContext对象
WebContext webContext = new WebContext(req, resp, this.getServletContext());
// 3.处理模板数据
this.templateEngine.process(templateName, webContext, resp.getWriter());
}
}
- Test1.java
package com.example.javaweb2;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author 许大仙
* @version 1.0
* @since 2021-10-22 10:31
*/
@WebServlet(value = "/test1")
public class Test1 extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建Cookie
Cookie cookie1 = new Cookie("cookie-name","cookie-Value");
Cookie cookie2 = new Cookie("cookie-name2","cookie-Value2");
// 响应给客户端
response.addCookie(cookie1);
response.addCookie(cookie2);
this.processTemplate("demo", request, response);
}
}
1.2.2 Cookie的读取
- Cookie的读取就是读取浏览器中携带的Cookie请求头。
- ① 服务器端获取浏览器传递过来的Cookie的代码:
request.getCookies()
。 ② 遍历Cookie数组,获取所有的Cookie信息。
示例:
- pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
- index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/app/test1">test1</a>
</body>
</html>
- Test1.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 许大仙
* @version 1.0
* @since 2021-10-22 10:31
*/
@WebServlet(value = "/test1")
public class Test1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建Cookie
Cookie cookie1 = new Cookie("cookie-name", "cookie-Value");
Cookie cookie2 = new Cookie("cookie-name2", "cookie-Value2");
// 响应给客户端
response.addCookie(cookie1);
response.addCookie(cookie2);
response.sendRedirect(request.getContextPath() + "/test2");
}
}
- Test2.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
/**
* @author 许大仙
* @version 1.0
* @since 2021-10-22 10:31
*/
@WebServlet(value = "/test2")
public class Test2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
Optional.ofNullable(cookies).ifPresent(c -> {
for (Cookie cookie : c) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println("name:" + name + ",value:" + value);
}
});
}
}
1.2.3 Cookie值的修改
- ① 服务器端获取浏览器传递过来的Cookie的代码:
request.getCookies()
。 - ② 遍历Cookie数组,获取所有的Cookie信息。
- ③ 根据指定的Cookie的名称修改Cookie的值。
④ 通知浏览器保存修改的Cookie。
示例:
- index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/app/test1">test1</a>
</body>
</html>
- Test1.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 许大仙
* @version 1.0
* @since 2021-10-22 10:31
*/
@WebServlet(value = "/test1")
public class Test1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建Cookie
Cookie cookie1 = new Cookie("cookie-name", "cookie-Value");
Cookie cookie2 = new Cookie("cookie-name2", "cookie-Value2");
// 响应给客户端
response.addCookie(cookie1);
response.addCookie(cookie2);
response.sendRedirect(request.getContextPath() + "/test2");
}
}
- Test2.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
/**
* @author 许大仙
* @version 1.0
* @since 2021-10-22 10:31
*/
@WebServlet(value = "/test2")
public class Test2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 修改Cookie信息
Cookie[] cookies = request.getCookies();
Optional.ofNullable(cookies).ifPresent(c -> {
for (Cookie cookie : c) {
String name = cookie.getName();
if("cookie-name".equals(name)){
cookie.setValue("cookie-Value1");
// 通知浏览器保存修改
response.addCookie(cookie);
}
}
});
response.sendRedirect(request.getContextPath()+"/test3");
}
}
- Test3.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
@WebServlet( value = "/test3")
public class Test3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
Optional.ofNullable(cookies).ifPresent(c -> {
for (Cookie cookie : c) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println("name:" + name + ",value:" + value);
}
});
}
}
1.2.4 Cookie的有效时间
- 经过上面的介绍,我们知道Cookie是保存在浏览器端的,但是浏览器不可能永远保存一个Cookie,所以我们需要为一个Cookie设置一个有效时间。
- Cookie默认是会话级别的,一旦关闭浏览器,Cookie会失效。
- Cookie的实例方法
setMaxAge()
控制Cookie的存活时间,接收一个int类型的参数,单位是秒。
public void setMaxAge(int expiry)
- 参数设置为0,Cookie立即失效。
- 参数设置大于0,Cookie在设置的参数秒后失效。
参数设置小于0,Cookie恢复会话级别。
示例:
- index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/app/test1">test1</a>
</body>
</html>
- Test1.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(value = "/test1")
public class Test1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建Cookie
Cookie cookie = new Cookie("cookie-name", "cookie-Value");
// 设置Cookie在5秒后失效
cookie.setMaxAge(5);
// 响应给客户端
response.addCookie(cookie);
response.sendRedirect(request.getContextPath() + "/test2");
}
}
- Test2.java
package com.example.javaweb2;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Optional;
@WebServlet(value = "/test2")
public class Test2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
Optional.ofNullable(cookies).ifPresent(c -> {
for (Cookie cookie : c) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println("name:" + name + ",value:" + value);
}
});
}
}
1.2.5 Cookie的路径
- Cookie的路径会保存浏览器访问那些地址应该携带该Cookie,我们知道浏览器会保存不同网站的Cookie,如:百度的Cookie、新浪的Cookie、腾讯的Cookie,但是我们不能访问百度的时候携带腾信的Cookie,也不可能访问每个网站的时候都带上所有的Cookie,这很明显不现实,所以我们通常会为Cookie设置一个Path属性,告诉浏览器何时携带该Cookie。
我们可以通过Cookie的实例方法
setPath()
,来设置Cookie的Path的路径,这个路径是由浏览器解析的。/
:代表服务器的根目录。- 如果设置的有效路径是
/demo/abc
,那么/demo/abc
,能访问到Cookie。/demo/abc.xxx
,不能访问到Cookie。/demo/abc/xxx.xxx
,能访问到Cookie。/demo/abc/a/b/c
,能访问到Cookie。
- 如果不设置,默认会在访问
/项目名
的资源的时候携带,如:/项目名/abc.html
。
示例:
- index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/app/test1">test1</a>
</body>
</html>
- Test1.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 许大仙
* @version 1.0
* @since 2021-10-22 10:31
*/
@WebServlet(value = "/test1")
public class Test1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建Cookie
Cookie cookie = new Cookie("cookie-name", "cookie-Value");
// 设置Cookie的路径
cookie.setPath(request.getContextPath() + "/abc");
// 响应给客户端
response.addCookie(cookie);
response.sendRedirect(request.getContextPath() + "/test2");
}
}
- Test2.java
package com.example.javaweb2;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Optional;
@WebServlet(value = "/test2")
public class Test2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
Optional.ofNullable(cookies).ifPresent(c -> {
for (Cookie cookie : c) {
String name = cookie.getName();
String value = cookie.getValue();
String path = cookie.getPath();
System.out.println("name:" + name + ",value:" + value + ",path:" + path);
}
});
}
}
1.3 Cookie的弊端
- ① Cookie的value是String类型,存储不灵活(实际开发中,可能需要存储对象)。
- ② Cookie数量过多,会浪费数据流量,但是浏览器对Cookie数量有限制,限制数据大小为
200~500
个,容量为2kb~5kb
。 - ③ Cookie存储在浏览器端,相对不安全。
第二章:Session
2.1 Session的简介
2.1.1 为什么需要Session?
- 使用Cookie有一个非常大的局限,就是如果Cookie很多,则无形的增加了客户端与服务端的数据传输量,而且由于浏览器对Cookie数量的限制,注定我们不能再Cookie中保存过多的信息,于是Session出现。
- Session的作用就是在服务器端保存一些用户的数据,然后传递给用户一个名字为JSESSIONID的Cookie,这个JESSIONID对应这个服务器中的一个Session对象,通过它就可以获取到保存用户信息的Session。
2.1.2 Session是什么?
- Session是一个域对象,同时也是Thymeleaf或JSP中的内置对象。
- Session是在服务器端保存用户数据的一种技术,并且Session是基于Cookie的。
2.1.3 Session的工作原理
- 前提:浏览器能正常访问服务器。
- 服务器端没有调用
request.getSession()
方法,则什么都不会发生。 - 服务器端调用了
request.getSession()
方法,服务器端会检查当前请求中是否携带了JSESSIONID的Cookie:- 如果有,根据JSESSIONID在服务器端查找对应的HttpSession对象,如果找到,将找到的HttpSession对象作为
request.getSession()
方法的返回值返回;如果没有找到,则服务器端创建一个HttpSession对象作为request.getSession()
方法的返回值返回。 - 如果没有,服务器创建一个HttpSession对象作为
request.getSession()
方法的返回值返回。
- 如果有,根据JSESSIONID在服务器端查找对应的HttpSession对象,如果找到,将找到的HttpSession对象作为
2.2 Session的使用
2.2.1 Session的创建和获取
- Session的创建时机是在request.getSession()方法第一次调用的时候。
- Session被创建后,同时还会有一个JSESSIONID的Cookie被创建。
这个Cookie的默认时效就是当前会话。
示例:
- pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
- index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/app/test1">test1</a>
</body>
</html>
- ViewBaseServlet.java
package com.example.javaweb2;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ViewBaseServlet extends HttpServlet {
private TemplateEngine templateEngine;
@Override
public void init() throws ServletException {
// 获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 创建Thymeleaf解析器对象
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// 给解析器设置参数
// ①HTML是默认模式,明确设置是为了代码更容易理解
templateResolver.setTemplateMode(TemplateMode.HTML);
// ②设置前缀
templateResolver.setPrefix(servletContext.getInitParameter("view-prefix"));
// ③设置后缀
templateResolver.setSuffix(servletContext.getInitParameter("view-suffix"));
// ④设置缓存过期时间(毫秒)
templateResolver.setCacheTTLMs(60000L);
// ⑤设置是否缓存
templateResolver.setCacheable(true);
// ⑥设置服务器端编码方式
templateResolver.setCharacterEncoding("utf-8");
// 创建模板引擎
this.templateEngine = new TemplateEngine();
// 给模板引擎设置模板解析器
this.templateEngine.setTemplateResolver(templateResolver);
}
protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
// 1.设置响应体内容类型和字符集
resp.setContentType("text/html;charset=UTF-8");
// 2.创建WebContext对象
WebContext webContext = new WebContext(req, resp, this.getServletContext());
// 3.处理模板数据
this.templateEngine.process(templateName, webContext, resp.getWriter());
}
}
- Test1.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet(value = "/test1")
public class Test1 extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String id = session.getId();
System.out.println("id = " + id);
this.processTemplate("demo", request, response);
}
}
- /WEB-INF/view/demo.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text="${#session.id}"></p>
</body>
</html>
2.2.2 Session数据的存取
- 向Session对象域中存储数据:
public void setAttribute(String name, Object value);
- 从Session对象域中获取数据:
public Object getAttribute(String name);
- 示例:
- index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/app/test1">test1</a>
</body>
</html>
- Test1.java
package com.example.javaweb2;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(value = "/test1")
public class Test1Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
// 存储数据
session.setAttribute("abc", "123");
response.sendRedirect(request.getContextPath() + "/test2");
}
}
- Test2.java
package com.example.javaweb2;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet(value = "/test2")
public class Test2Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
// 获取数据
Object abc = session.getAttribute("abc");
System.out.println("abc = " + abc);
}
}
2.2.3 Session的有效时间(空闲时间)
- Session的有效时间:Session对象在服务器端是不能长期保存的,它是有时间限制的,超过一定时间没有被访问过的Session对象就应该被释放掉,以节省其内存,所以Session的有效时间并不是从创建对象开始计时的,到指定时间后释放;而是
从最后一次访问开始计时
,统计其空闲的时间
。 - 默认有效时间(Tomcat的web.xml):全局
<!-- ==================== Default Session Configuration ================= -->
<!-- You can set the default session timeout (in minutes) for all newly -->
<!-- created sessions by modifying the value below. -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
Session对象的默认有效时间是30分钟。
- 手动设置(在工程的web.xml中配置Session的超时时间):全局
<!-- 设置Session默认的过期时间 -->
<session-config>
<!-- 以分钟为单位。10分钟超时 -->
<session-timeout>10</session-timeout>
</session-config>
手动设置:局部
获取超时时间,单位是秒
public int getMaxInactiveInterval();
设置用户多久时间没有操作就会Session过期,单位为秒
// 如果是正数,则表示用户在指定的时间内没有任何操作,Session就会过期失效 // 如果是负数,则表示Session永不过期 public void setMaxInactiveInterval(int interval);
强制失效:
public void invalidate();
2.3 Session对象的失效情况
- Session对象空闲时间达到了目标设置的最大值,自动释放。
- Session对象被强制失效。
- Web应用卸载。
- 服务器进程停止。
2.4 Session的活化和钝化
- Session机制很好的解决了Cookie的不足,但是当访问应用的用户很多时,服务器上就会创建非常多的Session对象,如果不对这些Session对象进行处理,那么在Session失效之前,这些Session一直都会在服务器的内存中存在,此时,就出现了Session活化和钝化的机制。
Session钝化
:Session在一段时间内没有被使用或关闭服务器时,会将当前存在的Session对象及Session对象中的数据从内存序列化到磁盘的过程,称之为钝化。Session活化
:Session被钝化后,服务器再次调用Session对象或重启服务器时,将Session对象及Session对象中的数据从磁盘反序列化到内存的过程,称之为活化。- 如果希望Session域中的对象也能够随Session钝化过程一起序列化到磁盘上,则对象的实现类也必须实现java.io.Serializable接口。不仅如此,如果对象中还包含其他对象的引用,则被关联的对象也必须支持序列化,否则会抛出异常:java.io.NotSerializableException。
2.5 浏览器和Session关联的技术内幕
- 我们发现一旦浏览器关闭之后,我们再去获取Session对象就会创建一个新的Session对象,这是为什么?
- 当浏览器关闭之后,因为浏览器无法再通知服务器,之前创建的session的id是多少,所以服务器也没办法找到对应的Session对象,就以为是第一次访问,就创建了新的Session对象并返回。