一。会话:
什么是会话:
日常生活中:从拨通电话到挂断电话之间的一连串你问我答的过程就是一个会话。
B/S架构中:从浏览器第一次给服务器发送请求时,建立会话;直到有一方断开,会话结束。
一次会话:包含多次请求响应。
会话技术
Http是一个无状态协议,同一个会话的连续两个请求相互独立,彼此并不了解
用于==存储==浏览器与服务器在请求和响应过程中产生的==数据==
例如,用户甲和乙分别登录了购物网站,甲购买了一个 Nokia 手机,乙购买了一个 Ipad ,当这两个用户结账时, Web 服务器需要对用户甲和乙的信息分别进行保存。在前面章节讲解的域对象中, HttpServletRequest 对象和 ServletContext 对象都可以对数据进行保存,但是这两个对象都不可行,具体原因如下:( 1 )客户端请求 Web 服务器时,针对每次 HTTP 请求, Web 服务器都会创建一个 HttpServletRequest 对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的数据将会丢失。( 2 )使用 ServletContext 对象保存数据时,由于同一个 Web 应用共享的是同一个 ServletContext 对象,因此,当用户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结算,这显然也是不可行的。( 3 )为了保存会话过程中产生的数据,在 Servlet 技术中,提供了两个用于保存会话数据的对象,分别是 Cookie 和Session 。
客户端会话技术:cookie
服务器端会话技术:session
注意:
Servlet的会话技术主要有cookie与session两种 。
二。Cookie
1. 记住用户名2. 自动登录(记住用户名和密码)3. 记录用户上次访问时间4. 浏览器商品记录
Cookie:
Cookie(String name, String value)
创建cookie对象
String getName()
获取cookie的名称
String getValue()
获取cookie的值
void setPath(String uri)
设置cookie的路径——浏览器根据这个路径判断那些cookie要发送给服务器
HttpServletResponse:
void addCookie(Cookie cookie)
将cookie发送给浏览器
HttpServletRequest:
Cookie[] getCookies()
获取浏览器发送的cookie
1. 设置数据到cookie中
// 1.创建cookie对象,设置数据
Cookie cookie = new Cookie(String name,String value);
// 2.通过response,响应(返回)cookie
response.addCookie(cookie);
2. 从cookie中获取数据
// 1.通过request对象,接收cookie数组
Cookie[] cookies = request.getCookies();
@WebServlet("/SetServlet")
public class SetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.创建cookie对象,设置数据
Cookie cookie = new Cookie("name","ack");
// 2.通过response,响应(返回)cookie
response.addCookie(cookie);
}
}
@WebServlet("/GetServlet")
public class GetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通过request对象,接收cookie数组
Cookie[] cookies = request.getCookies();
// 2.遍历数组
if(cookies!=null){
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
System.out.println(name + " : " + value);
}
}
}
}
3.工作原理
4.Cookie细节
(1)服务器发送多个cookie
是可以的
// 1. 创建多个cookie对象
Cookie cookie1 = new Cookie("name","lucy");
Cookie cookie2 = new Cookie("age","18");
// 2. 通过response响应多个
response.addCookie(cookie1);
response.addCookie(cookie2);
@WebServlet("/MultipleCookie")
public class MultipleCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建多个cookie对象
Cookie cookie1 = new Cookie("name","lucy");
Cookie cookie2 = new Cookie("age","18");
// 2. 通过response响应多个
response.addCookie(cookie1);
response.addCookie(cookie2);
}
}
(2)Cookie在浏览器保存时间
* 默认情况下
浏览器关闭(会话结束),cookie销毁(内存)
* 设置cookie的存活时间
cookie.setMaxAge(int second); -- 单位是秒
正数:指定存活时间,持久化浏览器的磁盘中,到期后自动销毁
负数:默认浏览器关闭,cookie销毁
零:立即销毁void setMaxAge(int expiry)设置cookie的最大生存时间(单位:秒),超过了该时间后Cookie会自动销毁注意 : 当时间为0的时候 , 意思为立即删除此Cookie(前提:path和name必须一致)。
@WebServlet("/MaxAgeCookie")
public class MaxAgeCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.创建cookie对象
Cookie cookie = new Cookie("product", "xiaomi");
// 2.设置cookie存活时间
// cookie.setMaxAge(-1); // 默认值,浏览器关闭自动销毁
// cookie.setMaxAge(60);// 存活30秒,到期自动销毁
cookie.setMaxAge(0); // 立即销毁...
//3. response响应cookie
response.addCookie(cookie);
}
}
(3)Cookie是否可以存储中文
* tomcat8之前的版本,不支持中文
URLEncoder 编码
URLDecoder 解码* tomcat8以后的版本,支持中文...
Rfc6265Cookie规范,不允许使用 分号、空格、逗号等一些特殊符号...
java.lang.IllegalArgumentException:An invalid character [32] was present in the Cookie value那么如果我们一定要保存非法数据在 cookie 中,该如何操作呢?答: cookie 对于基本符号、数字、和字母是可以存储的,因此,我们只需要将非法数据转换成符号、数字、和字母形式存储,要使用的时候再转换成正常的数据(解码)即可。
API介绍:
(1) URLEncoder类: static String encode(String s, String enc)
将指定的字符串,按指定的编码表编码
(2)URLDecoder类: static String decode(String s, String enc)
将指定的字符串,按指定的编码表解码
@WebServlet("/EncodeCookie")
public class EncodeCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String product = "华为荣耀";
product= URLEncoder.encode(product, "UTF-8");
// 1.创建cookie对象
Cookie cookie = new Cookie("product", product);
// 2.response响应cookie
response.addCookie(cookie);
}
}
@WebServlet("/GetServlet")
public class GetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通过request对象,接收cookie数组
Cookie[] cookies = request.getCookies();
// 2.遍历数组
if(cookies!=null){
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
// 解码
value = URLDecoder.decode(value, "UTF-8");
System.out.println(name + " : " + value);
}
}
}
}
(4)Cookie共享数据的范围?
在一个tomca服务器中,部署了多个web项目,那么这些web项目的Cookie能否共享?**
* 默认情况下不可以
默认cookie的携带路径,是当前设置cookie的serlvet父路径。。。。
设置cookie:http://localhost:8080/dcookie/EncodeCookie
默认携带路径:http://localhost:8080/dcookie
* 指定cookie的携带路径
cookie.setPath(String path);
举例:
cookie.setPath("/");
/ 相当于 http://localhost:8080/
此cookie携带路径
访问
http://localhost:8080/dcookie
http://localhost:8080/dresponse
* 注意
cookie的携带路径不同,名称可以重复....
=======================================================================
=======================================================================
设置cookie
http://localhost:8080/dcookie/aa/SetCookie
接收cookie
http://localhost:8080/dcookie/bb/GetCookie
默认情况下,是否能获取aa目录下的cookie数据?
是不可以....
在当前项目下共享cookie
cookie.setPath("/项目名")
@WebServlet("/PathCookie")
public class PathCookie extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String product = "小米";
product = URLEncoder.encode(product, "UTF-8");
// 1.创建cookie对象
Cookie cookie = new Cookie("product", product);
// 2.设置cookie的携带路径
cookie.setPath("/");
// 3.response响应cookie
response.addCookie(cookie);
}
}
不同tomcat服务器之间Cookie能否共享
* 默认情况下不可以
* 多个服务器之间的数据共享cookie,需要在同一个一级域名下
cookie.setDomain(".jd.com")
五。Cookie特点
1. cookie存储数据都在客户端(浏览器)
2. cookie的存储数据只能是字符串
3. cookie单个大小不能超过4KB
4. 同一个域名下cookie数量不能超过50个
5. cookie路径不同,可以重名出现
6. cookie存储的数据不太安全
三,案例
1.访问上次记录
@WebServlet("/LastTimeServlet")
public class LastTimeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 1.接收cookie数组,取出指定名称cookie对象
Cookie cookie = CookieUtils.findByName("last_time", request.getCookies());
// 2.判断
if (cookie == null) {
// 不存在
response.getWriter().write("<h1>欢迎您,首次访问....</h1>");
} else {
// 存在
String value = cookie.getValue();
response.getWriter().write("<h1>欢迎回来,您上次访问时间:" + value + "</h1>");
}
// 3.创建cookie对象,记录本次访问时间
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日-HH:mm:ss");
String currentTime = simpleDateFormat.format(new Date());
cookie = new Cookie("last_time", currentTime);
// 4.设置cookie存活1年
cookie.setMaxAge(60 * 60 * 24 * 365);
// 5.response响应cookie
response.addCookie(cookie);
}
}
public class CookieUtils {
/*
根据指定名称,查找cookie对象
*/
public static Cookie findByName(String name, Cookie[] cookies) {
// 非空判断
if (cookies != null && cookies.length > 0) {
// 遍历
for (Cookie cookie : cookies) {
// 判断是否有指定名称的cookie
if (name.equals(cookie.getName())) {
return cookie;
}
}
}
// 没找到返回null
return null;
}
}
关于JSP:
Java服务器端页面(Java Server Pages)
简单来说:一个特殊的页面,即可定义html标签,又可以定义java代码
作用:简化书写,展示动态页面
本质:是servlet
* 脚本:Jsp通过脚本方式来定义java代码
<% java代码 %> 就相当于servlet中service方法...
* 内置对象:在Jsp页面中不需要获取和创建,可以直接使用的对象
request
response
out
注意:在jsp响应内容,使用out
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>demo</title>
</head>
<body>
<h3>我是标题</h3>
<table border="1" width="200" align="center">
<tr>
<td>我是静态资源...</td>
</tr>
</table>
<%
System.out.println("我是jsp哈哈哈...");
request.getServletContext();
out.write("out输出的hehe");
// response.getWriter().write("hehe");
%>
</body>
</html>
2.商品浏览记录
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>商品目录</title>
</head>
<style type="text/css">
a{
font-size: 20px;
}
</style>
<body>
<h1>商品列表</h1>
<ul>
<li><a href="/d18/GoodsInfoServlet?name=小米10">小米10</a></li>
<li><a href="/d18/GoodsInfoServlet?name=华为mate">华为mate</a></li>
<li><a href="/d418/GoodsInfoServlet?name=oppo">oppo</a></li>
<li><a href="/d18/GoodsInfoServlet?name=iphone">iphone</a></li>
<li><a href="/d418/GoodsInfoServlet?name=锤子">锤子</a></li>
<li><a href="/d418/GoodsInfoServlet?name=一加">一加</a></li>
</ul>
</body>
</html>
<%@ page import="com.wsl.zy.CookieUtils" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.List" %><%--
Created by IntelliJ IDEA.
User: apple
Date: 2020/4/18
Time: 19:05
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>浏览历史</title>
</head>
<body>
<%
Cookie[] cookies = request.getCookies();
String value = CookieUtils.findByName("goodsname", cookies).getValue();
System.out.println("浏览历史:"+value);
if (value==null){
response.getWriter().write("<h1>浏览历史为空</h1>");
}else {
List<String> strings = Arrays.asList(value.split("-"));
out.write("浏览历史:<br><ul>");
for (String string : strings) {
out.write("<li>"+string+"</li>");
}
out.write("</ul>");
}
%>
</body>
</html>
package com.wsl.zy;
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.Arrays;
import java.util.List;
@WebServlet("/GoodsInfoServlet")
public class GoodsInfoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String name = request.getParameter("name");
response.getWriter().write("<h2>您当前浏览的产品为:"+name+"</h2>");
Cookie cookie = CookieUtils.findByName("goodsname", request.getCookies());
if (cookie==null){
cookie = new Cookie("goodsname",name);
}else{
String value = cookie.getValue();
List<String> strings = Arrays.asList(value.split("-"));
if (!strings.contains(name)){
value=value+"-"+name;
}
cookie = new Cookie("goodsname",value);
}
cookie.setMaxAge(60*60*24*365);
response.addCookie(cookie);
response.getWriter().write("<br><h2><a href=\"/d18/goods.html\">继续浏览</a></h2>");
response.getWriter().write("<br><h2><a href=\"/d18/history.jsp\">浏览历史</a></h2>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
优化:
package cn.itcast.g_goods;
import cn.itcast.f_lasttime.CookieUtils;
import javafx.scene.shape.VLineTo;
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.Arrays;
import java.util.LinkedList;
import java.util.List;
@WebServlet("/GoodsInfoServlet")
public class GoodsInfoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); // 请求解码
response.setContentType("text/html;charset=utf-8"); // 响应编码
// 1.获取请求参数 name 华为P
String product = request.getParameter("name");
// 2.展示当前商品详情
response.getWriter().write("您当前浏览的商品为:" + product);
// 3.获取指定名称cookie对象
Cookie cookie = CookieUtils.findByName("goods_name", request.getCookies());
// 4.判断是否存在...
if (cookie == null) {
// 5.如果不存在,将当前商品设置到cookie对象中...
cookie = new Cookie("goods_name", product);
} else {
// 6.如果有,将浏览记录取出,格式:小米
String value = cookie.getValue();
// 将字符串转为数组,转为list集合
String[] array = value.split("-");
// List<String> list = Arrays.asList(array); // 此list集合有坑,只能查询不能添加....
// list.add(0, product);
LinkedList<String> list = new LinkedList<>();
for (String s : array) {
list.add(s); // 这里应该是按照顺序添加..
}
// 7.判断当前商品是否在此cookie中
if (list.contains(product)) {
// 如果包含,删除
list.remove(product);
}
// 8.追加list 压入最上方
list.push(product);
// 将list转为 字符串 格式:华为-小米-锤子
value = String.join("-",list);
// 9.将value,重置到cookie中
cookie = new Cookie("goods_name", value);
/* // 7.判断当前商品是否在此cookie中
List<String> list = Arrays.asList(value.split("-"));
// 8.如果不包含,追加
if (!list.contains(product)) {
value = value + "-" + product; // 格式:小米10-华为P40
}
// 9.将value,重置到cookie中
cookie = new Cookie("goods_name", value);*/
}
// 10.通过response响应到浏览器
// 设置存活时间 为1年
cookie.setMaxAge(60 * 60 * 24 * 365);
response.addCookie(cookie);
// 11.制作a标签,实现记录浏览商品功能
response.getWriter().write("<br><a href='/d18cookie/goods.html'>继续浏览</a>");
// 12.制作a标签,实现查看浏览记录功能
response.getWriter().write("<br><a href='/d18cookie/history.jsp'>浏览记录</a>");
}
}
总结:
资料: