会话技术
-
概述
- 会话是浏览器和服务器之间的多次请求和响应。
- 也就是说,从浏览器访问服务器开始,到访问服务器结束,浏览器关闭为止的这段时间内容产生的多次请求和响应,合起来叫做浏览器和服务器之间的一次会话。
-
功能
-
实际上会话问题解决的还是客户端与服务器之间的通信问题,通过一些会话技术,可以将每个用户的数据以例如cookie/session的形式存储,方便以后用户访问web资源的时候使用
-
例如:
假定场景:A和B两人在某个网上购物商场登陆账号后,A买了一个HHKB的键盘,而B则购买了一把民谣吉他,这些信息都会被保存下来 用途是:保存账户信息,登录时询问日后是否自动登录,或者根据之前浏览,购买过的商品,分析用户喜欢什么类型的商品,做出精准推送
-
-
会话维持的方式
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
Cookie 快速入门
-
使用步骤
-
创建Cookie对象,绑定数据
new Cookie(String name, String value)
-
发送Cookie对象
response.addCookie(Cookie cookie)
-
获取Cookie,拿到数据
Cookie[] request.getCookies()
-
-
实现
-
创建一个类,用来将数据绑定到Cookie对象上
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("/cookieDemo01") public class CookieDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 创建 Cookie 对象 Cookie cookie = new Cookie("massage", "HelloCookie"); // 发送 Cookie response.addCookie(cookie); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
创建一个类,用来获取Cookie对象中绑定到的数据
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("/cookieDemo02") public class CookieDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取 Cookie Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { System.out.println(cookie.getName() + ":" + cookie.getValue()); } } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
启动服务器,浏览器访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo01,绑定数据到Cookie对象
-
然后再访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo02,控制台输出:
-
Cookie 技术
-
概述:
Cookies 可以简单的理解为服务器暂存在你浏览器中的一些信息文件,它将你在网站上所输入的一些内容,或者一些选项记录下来,当下一次你访问同一个网站的时候,服务器就会主动去查询这个cookie资料,如果存在的话,将会根据其中的内容,提供一些特别的功能,例如记住账号密码等。
-
具体流程
浏览器访问服务器,如果服务器需要记录该用户的状态,就用response向浏览器发送一个cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的网址以及Cookie一同提交给服务器。
Cookie 的操作规则以及常用API
一次发送多个 Cookie
创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
举例:
-
创建一个类,用来将数据绑定到Cookie对象上
@WebServlet("/cookieDemo03") public class CookieDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { // 创建 Cookie 对象 Cookie cookie1 = new Cookie("massage1", "HelloCookie1"); Cookie cookie2 = new Cookie("massage2", "HelloCookie2"); // 发送 Cookie response.addCookie(cookie1); response.addCookie(cookie2); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { this.doGet(request, response); } }
-
创建一个类,用来获取Cookie对象中绑定到的数据
@WebServlet("/cookieDemo04") public class CookieDemo04 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { // 获取 Cookie Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { System.out.println(cookie.getName() + ":" + cookie.getValue()); } } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { this.doGet(request, response); } }
-
启动服务器,浏览器访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo03,绑定数据到Cookie对象
-
然后再访问:http://localhost:8080/CookieStudy_war_exploded/cookieDemo02
-
控制台输出:
-
cookie 的生命周期
-
默认情况下,当浏览器关闭后,Cookie数据被销毁
-
不过我们可以将Cookie存储到硬盘中,实现持久化存储
方法:
setMaxAge(int seconds)
- seconds 为正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
- seconds 为负数:当浏览器关闭后,Cookie数据被销毁(默认值)
- seconds 为零:删除cookie信息
-
就用上面
一次发送多个 Cookie
的例子。当我们访问 /cookieDemo03 后,再访问 /cookieDemo04,这个时候cookie是还没有没销毁的,因为我们没有关闭浏览器(Cookie存在内存中)。一旦我们关闭浏览器(释放内存)之前的cookie就会被删除。那么我们这时候,不去访问 /cookieDemo03 ,直接去访问 /cookieDemo04 ,控制台是不会输出CookieDemo03.java
对应的 cookie 绑定到的数据的。假如想要cookie的有效时间更长,可以通过在绑定数据到Cookie对象的时候,设置Cookie可以存在硬盘中的时间。如:
@WebServlet("/cookieDemo05") public class CookieDemo05 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { // 创建 Cookie 对象 Cookie cookie = new Cookie("massage", "HelloCookie"); // 设置 Cookie 的存在时间(实现 Cookie 的持久化存储) cookie.setMaxAge(30); // 发送 Cookie response.addCookie(cookie); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { this.doGet(request, response); } }
关于 cookie 存储中文数据问题
-
在tomcat 8 之前 cookie中不能直接存储中文数据。
需要将中文数据转码---一般采用URL编码(如:%E3)
-
在tomcat 8 之后,cookie支持中文数据。
特殊字符还是不支持,建议使用URL编码存储,URL解码解析
cookie 共享问题
假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中 cookie 默认情况下是不能共享的。
可以通过设置,来实现在同一个tomcat服务器、不同web项目中的 cookie 共享。
setPath(String path)
// 设置cookie的获取范围。默认情况下,设置当前的虚拟目录
如:/CookieStudy01_war_exploded 项目虚拟路径和 /CookieStudy02_war_exploded项目虚拟路径,他们的cookie是不能共享的,如果想要实现共享,可以设置cookie的虚拟目录为这两个虚拟目录的公共目录(这里的是:/
)
不同的tomcat服务器间cookie共享问题(了解)
setDomain(String path)
// 如果设置一级域名相同,那么多个服务器之间 cookie 可以共享
// 举例如:setDomain(".baidu.com"),那么 tieba.baidu.com 和 news.baidu.com 中 cookie 可以共享
Cookie 的特点
- cookie 存储数据在客户端浏览器
- 浏览器对于单个 cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
- cookie一般用于存出少量的不太敏感的数据。
- 在不登录的情况下,完成服务器对客户端的身份识别。
Cookie 的使用案例
-
需求:记住用户上一次访问时间
-
访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
-
如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
-
-
分析:
-
在服务器中的Servlet判断是否有一个名为lastTime的cookie
-
用户不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:20XX年XX月XX日XX:XX:XX
- 写回Cookie当前访问时间:lastTime=20XX年XX月XX日XX:XX:XX
-
用户是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie当前访问时间:lastTime=20XX年XX月XX日XX:XX:XX
-
-
-
实现:
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.net.URLDecoder; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.Date; @WebServlet("/cookieTest") public class CookieTest extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // 设置响应的消息体的数据格式以及编码 response.setContentType("text/html;charset=utf-8"); // 获取所有Cookie Cookie[] cookies = request.getCookies(); // 默认没有cookie为lastTime boolean flag = false; // 遍历cookie数组 if(cookies != null && cookies.length > 0) { for (Cookie cookie : cookies) { // 获取cookie的名称 String name = cookie.getName(); // 判断名称是否是:lastTime if("lastTime".equals(name)) { // 有cookie为lastTime,不是第一次访问 flag = true; // 获取当前时间的字符串 Date date = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String stringDate = simpleDateFormat.format(date); // 由于stringDate字符串中存在特殊字符(空格),需要URL编码 String encodeCookie = URLEncoder.encode(stringDate, "utf-8"); // 重新设置Cookie的值 cookie.setValue(encodeCookie); // 设置cookie的存活时间:存活一个小时 cookie.setMaxAge(60 * 60); // 在响应对象中添加该设置的cookie response.addCookie(cookie); // 响应数据 // 获取Cookie的value(时间) String value = cookie.getValue(); // 对获取到的cookie值进行URL解码 String decodeValue = URLDecoder.decode(value, "utf-8"); response.getWriter().write("<h1>欢迎回来,您上次访问时间为:" + decodeValue + "</h1>"); // 已经完成了需求 break; } } } // 假如上面遍历了所有的cookie,都没有cookie为lastTime,或者用户的请求中没有cookie,说明用户是第一次访问 if(cookies == null || cookies.length == 0 || flag == false) { // 获取当前时间的字符串 Date date = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String stringDate = simpleDateFormat.format(date); // 由于stringDate字符串中存在特殊字符(空格),需要URL编码 stringDate = URLEncoder.encode(stringDate, "utf-8"); // 重新设置Cookie的值 Cookie cookie = new Cookie("lastTime", stringDate); // 设置cookie的存活时间 cookie.setMaxAge(60 * 60); // 重新发送cookie response.addCookie(cookie); response.getWriter().write("<h1>您好,欢迎您首次访问!</h1>"); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { this.doGet(request, response); } }
-
启动服务器,首次访问:http://localhost:8080/CookieStudy_war_exploded/cookieTest
-
再次访问:http://localhost:8080/CookieStudy_war_exploded/cookieTest