Servlet第五篇【介绍会话技术、Cookie的API、详解、应用】
来源:SegmentFault
2023-02-24 16:28:14
0浏览
收藏
对于一个数据库开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《Servlet第五篇【介绍会话技术、Cookie的API、详解、应用】》,主要介绍了MySQL、Java、spring、intellij-idea、tomcat,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了!
什么是会话技术
基本概念: 指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话.
为什么我们要使用会话技术?
会话跟踪技术可以解决我们很多很多问题。
- 在论坛登陆的时候,很多时候会有一个小框框问你是否要自动登陆,当你下次登陆的时候就不用输入密码了

- 根据我以前浏览过的商品,猜我喜欢什么商品

Cookie
会话跟踪技术有Cookie和Session,Cookie技术是先出现的。我们先讲Cookie技术吧。
什么是Cookie
Cookie是由W3C组织提出,最早由netscape社区发展的一种机制
- 网页之间的交互是通过HTTP协议传输数据的,而Http协议是无状态的协议。无状态的协议是什么意思呢?一旦数据提交完后,浏览器和服务器的连接就会关闭,再次交互的时候需要重新建立新的连接。
- 服务器无法确认用户的信息,于是乎,W3C就提出了:给每一个用户都发一个通行证,无论谁访问的时候都需要携带通行证,这样服务器就可以从通行证上确认用户的信息。通行证就是Cookie

Cookie的流程:浏览器访问服务器,如果服务器需要记录该用户的状态,就使用response向浏览器发送一个Cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的网址连同Cookie一同交给服务器。
Cookie API
- Cookie类用于创建一个Cookie对象
- response接口中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段
- request接口中定义了一个getCookies方法,它用于获取客户端提交的Cookie
常用的Cookie方法:
- public Cookie(String name,String value)
- setValue与getValue方法
- setMaxAge与getMaxAge方法
- setPath与getPath方法
- setDomain与getDomain方法
- getName方法
简单使用Cookie
- 创建Cookie对象,发送Cookie给浏览器、
//设置response的编码
response.setContentType("text/html;charset=UTF-8");
//创建Cookie对象,指定名称和值
Cookie cookie = new Cookie("username", "zhongfucheng");
//向浏览器给一个Cookie
response.addCookie(cookie);
response.getWriter().write("我已经向浏览器发送了一个Cookie");
- 浏览器本身没有任何Cookie

- 访问Servlet1,再回到文件夹中,还是没有发现Cookie,这是为什么呢?我明明向浏览器发送了一个Cookie的。
- 原来发送Cookie给浏览器是需要设置Cookie的时间的。在给浏览器之前,设置一下Cookie的时间
//设置Cookie的时间
cookie.setMaxAge(1000);
- 再次访问,已经发现文件夹中多了个Cookie的文本了

Cookie细节
Cookie不可跨域名性
- 很多人在初学的时候可能有一个疑问:在访问Servlet的时候浏览器是不是把所有的Cookie都带过去给服务器,会不会修改了别的网站的Cookie
- 答案是否定的。Cookie具有不可跨域名性。浏览器判断一个网站是否能操作另一个网站的Cookie的依据是域名。所以一般来说,当我访问baidu的时候,浏览器只会把baidu颁发的Cookie带过去,而不会带上google的Cookie。
Cookie保存中文
- 上面我们的例子保存的是英文字符,下面我们来看下保存中文字符会怎么样。
response.setContentType("text/html;charset=UTF-8");
PrintWriter printWriter = response.getWriter();
String name = "中国";
Cookie cookie = new Cookie("country", name);
cookie.setMaxAge(2000);
response.addCookie(cookie);
printWriter.write("我颁发了一个Cookie,值保存的是中文数据");
- 访问Servlet1,好吧。出异常了!

- 中文属于Unicode字符,英文数据ASCII字符,中文占4个字符或者3个字符,英文占2个字符。
- 解决:Cookie使用Unicode字符时需要对Unicode字符进行编码。
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
- 再次访问Servlet1,已经把Cookie成功颁发给浏览器了


- 我们发现Cookie保存在硬盘的中文数据是经过编码的,那么我们在取出Cookie的时候要对中文数据进行解码
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i
- 取出存进Cookie的值

Cookie的有效期
Cookie的有效期是通过setMaxAge()来设置的。
- 如果MaxAge为正数,浏览器会把Cookie写到硬盘中,只要还在MaxAge秒之前,登陆网站时该Cookie就有效【不论关闭了浏览器还是电脑】
- 如果MaxAge为负数,Cookie是临时性的,仅在本浏览器内有效,关闭浏览器Cookie就失效了,Cookie不会写到硬盘中。Cookie默认值就是-1。这也就为什么在我第一个例子中,如果我没设置Cookie的有效期,在硬盘中就找不到对应的文件。
- 如果MaxAge为0,则表示删除该Cookie。Cookie机制没有提供删除Cookie对应的方法,把MaxAge设置为0等同于删除Cookie
Cookie的修改和删除
- 上面我们已经知道了Cookie机制没有提供删除Cookie的方法。其实细心点我们可以发现,Cookie机制也没有提供修改Cookie的方法。那么我们怎么修改Cookie的值呢?
- Cookie存储的方式类似于Map集合,如下图所示

- Cookie的名称相同,通过response添加到浏览器中,会覆盖原来的Cookie。
- 以country为名保存的是%E4%B8%AD%E5%9B%BD,下面我再以country为名,把值改变一下。

String name = "看完博客就点赞";
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
- 再次查看Cookie的时候,值已经改变了,但是文件还是那一份

- 现在我要删除该Cookie,把MaxAge设置为0,并添加到浏览器中即可
String name = "看完博客就点赞";
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
//一定不要忘记添加到浏览器中
cookie.setMaxAge(0);
response.addCookie(cookie);
printWriter.write("我删除了该Cookie");
- 访问Servlet,在硬盘已经找不到Cookie的文件了!


- 注意:删除,修改Cookie时,新建的Cookie除了value、maxAge之外的所有属性都要与原Cookie相同。否则浏览器将视为不同的Cookie,不予覆盖,导致删除修改失败!
- 我们来试验一下把。
String name = "看完博客就点赞";
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
//一定不要忘记添加到浏览器中
cookie.setMaxAge(10000);
response.addCookie(cookie);

- 上面新建了一个Cookie,我修改下Cookie的其他属性,再删除,看能否把Cookie删除掉
//一定不要忘记添加到浏览器中
cookie.setPath("/ouzicheng");
cookie.setMaxAge(0);
response.addCookie(cookie);
printWriter.write("删除一个Cookie");
- 结果Cookie还在硬盘中

Cookie的域名
Cookie的domain属性决定运行访问Cookie的域名。domain的值规定为“.域名”
- Cookie的隐私安全机制决定Cookie是不可跨域名的。也就是说www.baidu.com和www.google.com之间的Cookie是互不交接的。即使是同一级域名,不同二级域名也不能交接,也就是说:www.goole.com和www.image.goole.com的Cookie也不能访问
- 我在本地上配置了3个虚拟主机,localhost,www.zhongfucheng.com,www.image.zhongfucheng.com【如果不知道怎么配置,在我Tomcat的博客有】


- 我用www.zhongfucheng.com域名发送了一个Cookie给浏览器
Cookie cookie = new Cookie("name", "zhongfucheng");
cookie.setMaxAge(1000);
response.addCookie(cookie);
printWriter.write("使用www.zhongfucheng.com域名添加了一个Cookie");

- 首先,证明了Cookie不可跨名性,localhost域名拿不到www.zhongfucheng.com颁发给浏览器的Cookie

- 再使用www.image.zhongfucheng.com域名访问,证明即使一级域名相同,二级域名不同,也不能获取到Cookie

- 当然,使用www.zhongfucheng.com当然能获取到Cookie,Cookie通过请求头带给服务器

- 现在我希望一级域名相同的网页Cookie之间可以相互访问。也就是说www.image.zhongfucheng.com可以获取到www.zhongfucheng.com的Cookie就需要使用到domain方法。
Cookie cookie = new Cookie("name", "ouzicheng");
cookie.setMaxAge(1000);
cookie.setDomain(".zhongfucheng.com");
response.addCookie(cookie);
printWriter.write("使用www.zhongfucheng.com域名添加了一个Cookie,只要一级是zhongfucheng.com即可访问");
- 使用www.zhongfucheng.com发布一个Cookie

- 使用www.image.zhongfucheng.com域名访问一下。发现可以获取到Cookie了

Cookie的路径
Cookie的path属性决定允许访问Cookie的路径
- 一般地,Cookie发布出来,整个网页的资源都可以使用。现在我只想Servlet1可以获取到Cookie,其他的资源不能获取。
- 使用Servlet2颁发一个Cookie给浏览器,设置路径为"/Servlet1"。
Cookie cookie = new Cookie("username", "java");
cookie.setPath("/Servlet1");
cookie.setMaxAge(1000);
response.addCookie(cookie);
printWriter.write("该Cookie只有Servlet1获取得到");
- 使用Servlet3访问服务器,看看浏览器是否把Cookie带上。显然,浏览器访问Servlet3并没有把Cookie带上。

- 使用Servlet1访问服务器,看看浏览器是否把Cookie带上。答案是肯定的!

Cookie的安全属性
- HTTP协议不仅仅是无状态的,而且是不安全的!如果不希望Cookie在非安全协议中传输,可以设置Cookie的secure属性为true,浏览器只会在HTTPS和SSL等安全协议中传输该Cookie。
- 当然了,设置secure属性不会将Cookie的内容加密。如果想要保证安全,最好使用md5算法加密【后面有】。
Cookie的应用
显示用户上次访问的时间
- 其实就是每次登陆的时候,取到Cookie保存的值,再更新下Cookie的值。
-
访问Serlvet有两种情况
- 第一次访问
- 已经访问过了
- 全部代码如下:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
response.setContentType("text/html;charset=UTF-8");
PrintWriter printWriter = response.getWriter();
//获取网页上所有的Cookie
Cookie[] cookies = request.getCookies();
//判断Cookie的值是否为空
String cookieValue = null;
for (int i = 0; cookies != null && i
- 按照正常的逻辑来写,程序流程应该是这样子的。先创建Cookie对象,回送Cookie给浏览器。再遍历Cookie,更新Cookie的值。

- 但是,按照上面的逻辑是做不到的!因为每次访问Servlet的时候都会覆盖原来的Cookie,取到Cookie的值永远都是当前时间,而不是上次保存的时间。
- 我们换一个逻辑写:先检查(遍历)所有Cookie有没有我要的,如果得不到我想要的Cookie,Cookie的值是null,那么就是第一次登陆,于是就有了上面的代码了。
- 我们来看下效果吧!当我第一次登陆的时候

- Cookie保存在硬盘中。

- 再次访问Servlet。明显地,取到的就是Cookie的值

显示上次浏览过商品
- 我就以书籍为例子了!首先设计Book对象
private String id ;
private String name ;
private String author;
public Book() {
}
public Book(String id, String name, String author) {
this.id = id;
this.name = name;
this.author = author;
}
...各种set、get方法
- 设计一个简单的数据库存储数据。就用LinkedHashMap集合【根据商品的id找书籍所以用Map,删改较多所以用Linked】
private static LinkedHashMap<string book> linkedHashMap = new LinkedHashMap();
//简化开发复杂度,book的id和商品的id相同
static {
linkedHashMap.put("1", new Book("1", "javaweb", "zhong"));
linkedHashMap.put("2", new Book("2", "java", "fu"));
linkedHashMap.put("3", new Book("3", "oracle", "cheng"));
linkedHashMap.put("4", new Book("4", "mysql", "ou"));
linkedHashMap.put("5", new Book("5", "ajax", "zi"));
}
//获取到所有书籍
public static LinkedHashMap getAll() {
return linkedHashMap;
}
</string>
- 显示网页上所有的书籍【首页】
printWriter.write("网页上所有的书籍:"+"<br>");
//拿到数据库所有的书
LinkedHashMap<string book> linkedHashMap = DB.getAll();
Set<map.entry book>> entry = linkedHashMap.entrySet();
//显示所有的书到网页上
for (Map.Entry<string book> stringBookEntry : entry) {
Book book = stringBookEntry.getValue();
printWriter.write(book.getId() +" "+ book.getName()+"<br>");
}
</string></map.entry></string>

- 接着,我们要做的就是给显示的书籍挂上一个超链接,当用户点击想看的书籍时,就跳转到该书籍的详细信息页面
- 超链接应该把书的id传递过去,不然处理页面是不知道用户想看的是哪一本书的!
//显示所有的书到网页上
for (Map.Entry<string book> stringBookEntry : entry) {
Book book = stringBookEntry.getValue();
printWriter.write("<a target='_blank' href='https://www.17golang.com/gourl/?redirect=MDAwMDAwMDAwML57hpSHp6VpkrqbYLx2eayza4KafaOkbLS3zqSBrJvPsa5_0Ia6sWuR4Juaq6t9nq6ycaaUkamovpXOpJafmtu5ZofdnNDcpZyqeV_DiYFtr42BqXqNgq-w3LuxgXmB28ZmpNmSlbppi72Bn62Fha2yfKucfaN6pLLNr6J9q4TPrWaD0Iany7CGrYVlsHmBrbKNnJmJs4JttKfRbI6GhJi9rn7ekre6o4bTfWU' rel='nofollow'>");
printWriter.write("<br>");
}
</a></string>

- 接收id,找到用户想要看哪一本书,输出该书的详细信息
String id = request.getParameter("id");
//由于book的id和商品的id是一致的。获取到用户点击的书
Book book = (Book) DB.getAll().get(id);
//输出书的详细信息
printWriter.write("书的编号是:" + book.getId()+"<br>");
printWriter.write("书的名称是:" + book.getName()+"<br>");
printWriter.write("书的作者是:" + book.getAuthor()+"<br>");
- 点击想要的书籍。

- 得到书籍的详细信息

- 既然用户点击了书籍,那么服务器就应该颁发Cookie给浏览器,记住用户点击了该书籍
- 现在问题来了,Cookie的值应该是什么呢?试想一下,待会还要把浏览过的书籍显示出来,所以用书籍的id是最好不过的。想到了用书籍的id作为Cookie的值,我们还要定义一些规则!
- 我们可能有非常多的书籍,不可能把用户浏览过的书籍都显示出来。所以我们定义只能显示3本浏览过的书籍
- 书籍的id都是数字,如果不做任何修改,存到Cookie里边可能就是231,345,123此类的数字,这样取出某一个id的时候就十分费劲并且后面还要判断该书是否存在Cookie里边了,所以我们要把存储到Cookie的书籍id分割起来。所以我们定义”_“作为分隔符
- 按上面的应用,我们的逻辑应该是:先遍历下Cookie,看下有没有我们想要的Cookie。如果找到想要的Cookie,那就取出Cookie的值
String bookHistory = null;
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i
-
取出了Cookie的值也分几种情况
- Cookie的值为null【直接把传入进来的id当做是Cookie的值】
- Cookie的值长度有3个了【把排在最后的id去掉,把传进来的id排在最前边】
- Cookie的值已经包含有传递进来的id了【把已经包含的id先去掉,再把id排在最前面】
- Cookie的值就只有1个或2个,直接把id排在最前边
if (bookHistory == null) {
return id;
}
//如果Cookie的值不是null的,那么就分解Cookie的得到之前的id。
String[] strings = bookHistory.split("\\_");
//为了增删容易并且还要判断id是否存在于该字符串内-----我们使用LinkedList集合装载分解出来的id
List list = Arrays.asList(strings);
LinkedList<string> linkedList = new LinkedList();
linkedList.addAll(list);
if (linkedList.contains(id)) {
linkedList.remove(id);
linkedList.addFirst(id);
}else {
if (linkedList.size() >= 3) {
linkedList.removeLast();
linkedList.addFirst(id);
} else {
linkedList.addFirst(id);
}
}
</string>
- 这么折腾完了,我们的Cookie值就在LinkedList集合里边了。接下来,我们要做的就是把集合中的值取出来,拼接成一个字符串
StringBuffer stringBuffer = new StringBuffer();
//遍历LinkedList集合,添加个下划线“_”
for (String s : linkedList) {
stringBuffer.append(s + "_");
}
//最后一个元素后面就不需要下划线了
return stringBuffer.deleteCharAt(stringBuffer.length() - 1).toString();
- 好的,我们现在已经完成了Cookie值了。接下来设置Cookie的生命周期,回送给浏览器即可
String bookHistory = makeHistory(request, id);
Cookie cookie = new Cookie("bookHistory", bookHistory);
cookie.setMaxAge(30000);
response.addCookie(cookie);
- 既然我们已经把Cookie回送给浏览器了。那么接下来我们就在首页上获取Cookie的值,显示用户浏览过什么商品就行了!
printWriter.write("您曾经浏览过的商品:");
printWriter.write("<br>");
//显示用户浏览过的商品
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i ");
}
break;
}
}
- 好的,我们来试验一下吧!!,第一次访问首页,并没有浏览过的商品

- 当我点击javaweb书籍再访问首页的时候

- 再点击ajax然后访问首页

- 再点击javaweb然后访问首页

- 点击oracle然后访问首页

- 好的,经过测试,该程序应该没有什么问题了!
如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,可以关注微信公众号:Java3y
终于介绍完啦!小伙伴们,这篇关于《Servlet第五篇【介绍会话技术、Cookie的API、详解、应用】》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布数据库相关知识,快来关注吧!
版本声明
本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
查看更多
最新文章
-
- 数据库 · MySQL | 1天前 |
- MySQL数值函数大全及使用技巧
- 117浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- 三种登录MySQL方法详解
- 411浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- MySQL数据备份方法与工具推荐
- 420浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- MySQL数据备份方法与工具推荐
- 264浏览 收藏
-
- 数据库 · MySQL | 4天前 |
- MySQL索引的作用是什么?
- 266浏览 收藏
-
- 数据库 · MySQL | 5天前 |
- MySQL排序原理与实战应用
- 392浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQLwhere条件查询技巧
- 333浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL常用数据类型有哪些?怎么选更合适?
- 234浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL常用命令大全管理员必学30条
- 448浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL高效批量插入数据方法大全
- 416浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL性能优化技巧大全
- 225浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL数据备份4种方法保障安全
- 145浏览 收藏
查看更多
课程推荐
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
查看更多
AI推荐
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3176次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3388次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3417次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4522次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3796次使用
查看更多
相关文章
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览

走进mysql基础
