Cookieとセッション(セッションテクノロジー)
1. クッキー
1. クッキーの概要
1.1. Cookie の概要
- セッションのデータをユーザーのブラウザに保存します。
- サーバーはクライアントにレターを送信し、クライアントは次回サーバーにアクセスするときにそのレターを持参するだけで済みます。
- クライアントテクノロジー (応答、要求)
- ユーザーがブラウザを開き、多数のハイパーリンクをクリックし、複数の Web リソースにアクセスし、ブラウザを閉じるこのプロセスをセッション (Cookie) と呼ぶことができます。
- Cookie は 1 つの情報のみを保存できます。
- Web サイトは複数の Cookie をブラウザに送信し、最大 20 個の Cookie を保存できます。
- Cookie のサイズは 4kb に制限されています。
- ブラウザの Cookie の制限は 300 です。
- セッションには複数のリクエストとレスポンスを含めることができます。
1.2. Cookie の使用シナリオ
- 初回ログインかどうかの判断によく使われます。次回ログイン不要の場合は2回目から直接ログインします!
1.3. Cookie の基本原理
2. Cookieの基本的な使い方
- Cookie(name,value): Cookie 構築メソッド。キーと値のペアの形式で保存されます。
- addCookie(cookie):添加Cookie
- getCookies(): リクエストの送信時に Cookie オブジェクトの配列を取得します。
- getName(): Cookie名(キー)を取得します。
- getValue(): Cookieの値を取得します。
- setMaxAge(int expiry): Cookie の有効期間を秒単位で設定します。永久に存続する場合はデフォルトで -1 (ただし、ブラウザを閉じると削除されます)、0 の場合は削除されます。
- RegistServlet.java
@WebServlet(name = "RegistServlet", value = "/registServlet")
public class RegistServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
// 获取前端传来的参数
String username = request.getParameter("username");
String password = request.getParameter("password");
// 判断输入的账号和密码是否正确
if (username.equals("root") && password.equals("111")){
// 创建Cookie对象,键值对形式存放
Cookie cookie1 = new Cookie("username", username);
Cookie cookie2 = new Cookie("password", password);
// 设置cookie的存活时间
cookie2.setMaxAge(10); // 以秒为单位,默认为-1永久存活(但是会在浏览器关闭时被删除),0为删除
// 在响应时添加cookie
response.addCookie(cookie1);
response.addCookie(cookie2);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- レジスト.jsp
<%@ page import="java.util.Arrays" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<%--编写 jsp 小脚本--%>
<%
// getCookies():获取请求发送时的Cookie对象的数组
Cookie[] cookies = request.getCookies();
// 定义变量用于value的显示
String username = "", password = "";
// 判断获取来的cookie是否为空,不为空执行
if (cookies != null) {
// 遍历cookie数组里的数据
for (Cookie cookie : cookies) {
/* System.out.println(cookie.getName());
System.out.println(cookie.getValue());*/
// getName():获取Cookie名称(键),等于前端传来的username的值
if (cookie.getName().equals("username")) {
// getValue():获取Cookie的值,将值赋给变量username,用于后面value的显示
username = cookie.getValue();
}
if (cookie.getName().equals("password")) {
password = cookie.getValue();
}
}
}
%>
<form action="registServlet" method="post">
<%-- =变量名:JSP中的语法,获取变量的值,显示到前端 --%>
用户名:<input type="text" name="username" value="<%=username%>"> <br>
密码:<input type="password" name="password" value="<%=password%>"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
3. Cookieの実装により、ユーザーの最終訪問時刻が表示されます
- LastServlet.java
@WebServlet(name = "LastServlet", value = "/LastServlet")
public class LastServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
Cookie[] cookies = request.getCookies(); // 获取所有cookie
boolean flag = false; // 判断cookies是否为空
// 访问过,cookies中会有时间
if (cookies.length > 0 && cookies != null) {
//遍历cookie数组
for (Cookie cookie : cookies) {
String name = cookie.getName();
// 判断名称是否是lastTime
if ("lastTime".equals(name)) {
// 有该cookie不是第一次访问
flag = true;
// 响应数据与解码
String value = cookie.getValue();
value = URLDecoder.decode(value, "utf-8");
response.getWriter().write("欢迎回来,您上次访问的时间为:" + value);
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
break;
}
}
if (cookies == null || cookies.length == 0 || flag == false) {
// 获取系统时间与编码
String str_date = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date());
str_date = URLEncoder.encode(str_date, "utf-8");
// 设置cookie的value
Cookie cookie = new Cookie("lastTime", str_date);
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
response.getWriter().write("您好,欢迎您首次访问");
}
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
4. Cookie のエンコードとデコード
Cookie は中国語をサポートしていないため、エンコードおよびデコードする必要があります。
URLEncoder.encode("沈公子","utf-8"); // 编码
URLDecoder.decode(cookie.getValue(),"utf-8"); // 解码
5. クッキーの概要
- クッキー機能
- ユーザーが初めてログインしたかどうかはCookieによって判断され、初回の場合はログインする必要があり、2回目以降は直接アクセスすることになります。
- Cookieの有効期間 setMaxAge();
- 有効期限を設定せずにブラウザを閉じると、Cookie は削除されます。
- 有効期間を0に設定し、Cookieを削除します。
- 有効期間を設定します。有効期限が切れると Cookie は削除されます。
- クッキーの保存方法
- Cookie は 1 つの情報のみを保存できます
- Cookieはブラウザによって保存されます
二、Session
1. セッション概要
1.1. セッションの概要
- セッション オブジェクトはサーバーによって保存されます。
- Session はセッション追跡テクノロジーです。
- セッションはCookieに基づいて実装されます。
- サーバーはあなたが来たことを登録します。次回あなたが来たときに私がマッチングします。
- 情報を保存し、SessionID を介してアクセスします。SessionID はブラウザを開いた瞬間に存在します。
- サーバーはユーザー (ブラウザー) ごとに Session オブジェクトを作成します。
- セッションはブラウザを占有し、ブラウザが閉じられない限り、このセッションは存在します。
- ユーザーがログインすると、Web サイト全体にアクセスできるようになり、ユーザーの情報が保存され、ショッピング カートの情報が保存されます。
- 同じセッション内の複数のリクエスト間でデータを共有します。
10. サーバーがシャットダウンされると、Tomcat は自動的に Seesion データをハードディスク ファイルに書き込み、サーバーを再起動した後、ファイルからセッションにデータをロードします。
1.2. セッションの使用シナリオ
- ログインユーザーの情報を保存する
- ショッピングカート情報
- ウェブサイト全体で頻繁に使用されるデータはセッションに保存されます
1.3. セッションの基本原理
2. セッションの基本的な使い方
- getSession(): セッションを取得
- setAttribute(): セッションのキーと値のペアのデータを設定します
- getAttribute(): キーを介してセッション内の値を取得します。
- RemoveAttribute(): キーによってセッション内の値を削除します
- getId(): セッションIDを取得します。
- validate(): セッションが無効です。再度入力すると、セッションの値がリセットされます。
- web.xml はセッションの有効期限を設定します
<!-- 设置Session默认的失效时间 -->
<session-config>
<!-- 1分钟后Session自动失效,再次进入会重置Session的值,以分钟为单位 -->
<session-timeout>1</session-timeout>
</session-config>
- テスト1
@WebServlet(name = "SessionDemo01", value = "/SessionDemo01")
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
// 获取session
HttpSession session = request.getSession();
// 给session设置键值对数据
session.setAttribute("name", "沈公子222");
// 获取session的id (JSESSIONID=D2EBCA814B8FC3249BCA47C96374A2F8)
String sessionId = session.getId();
// 判断session是否已存在
if (session.isNew()) {
response.getWriter().write("session创建成功,ID:" + sessionId);
} else {
response.getWriter().write("session已经在服务器中存在,ID:" + sessionId);
}
// Session创建的时候做了什么事情,在响应中显示Cookie的值
Cookie cookie = new Cookie("JSESSIONID", sessionId);
response.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- テスト2
@WebServlet(name = "SessionDemo02", value = "/SessionDemo02")
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
// 获取session
HttpSession session = request.getSession();
// 通过键获取session中的值
Object name = session.getAttribute("name");
response.getWriter().print(name);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- テスト 3
@WebServlet(name = "SessionDemo03", value = "/SessionDemo03")
public class SessionDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
// 获取session
HttpSession session = request.getSession();
// 通过键移除session中的值
session.removeAttribute("name");
// session失效,再次进入会重置Session的值
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
3. セッションログインの場合
- ログイン.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="LoginServlet" method="post">
用户名: <input type="text" name="username"><br/>
密码: <input type="password" name="password"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
- ユーザー.java
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- LoginServlet.java
@WebServlet(name = "LoginServlet", value = "/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String username = request.getParameter("username");
String password = request.getParameter("password");
if (("root").equals(username) && ("123123").equals(password)) {
User user = new User();
user.setUsername(username);
user.setPassword(password);
// 请求时获取Session,并将数据绑定进来
request.getSession().setAttribute("user", user);
response.sendRedirect(request.getContextPath() + "/IndexServlet"); // /demo06_3/IndexServlet
} else {
out.print("用户名或密码错误,登录失败,请重新登录<a href='/demo06_3/login.html'>返回登录</a>");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- IndexServlet.java
@WebServlet(name = "IndexServlet", value = "/IndexServlet")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 创建或者获取保存用户信息的Session对象
HttpSession session = request.getSession();
// 获取传递的数据
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
out.print("您还没有登录,请<a href='/demo06_3/login.html'>登录</a>");
} else {
out.print("您已登录,欢迎你," + user.getUsername() + "!");
out.print("<a href='/demo06_3/LogoutServlet'>退出</a>");
// 创建Cookie存放Session的标识号
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60*30); // 30分钟,session过期,需要重新登录
// 设置Cookie的有效目录路径
cookie.setPath(request.getContextPath()); // /demo06_3
response.addCookie(cookie);
// Set-Cookie: JSESSIONID=315710819A1A3518B0CCDCDC061BBD64; Max-Age=60; Expires=Wed, 22 Mar 2023 03:24:40 GMT; Path=/demo06_3
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- LogoutServlet.java
@WebServlet(name = "LogoutServlet", value = "/LogoutServlet")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
// 获取Session时将Session对象中的User对象移除,并不是把Session的标识号给移除
request.getSession().removeAttribute("user");
response.sendRedirect(request.getContextPath()+"/IndexServlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
4. セッションショッピングケース
- ケーキ.java
public class Cake {
private String id;
private String name;
public Cake() {
}
public Cake(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- CakeDB.java
public class CakeDB {
private static Map<String,Cake> cake = new LinkedHashMap<>();
static {
cake.put("1",new Cake("1","A类蛋糕"));
cake.put("2",new Cake("2","B类蛋糕"));
cake.put("3",new Cake("3","C类蛋糕"));
cake.put("4",new Cake("4","D类蛋糕"));
cake.put("5",new Cake("5","E类蛋糕"));
}
// 获取所有的蛋糕
public static Collection<Cake> getAll(){
return cake.values();
}
// 根据指定的id获取蛋糕
public static Cake getCake(String id){
return cake.get(id);
}
}
- ListCakeServlet.java
@WebServlet(name = "ListCakeServlet", value = "/ListCakeServlet")
public class ListCakeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 获取所有蛋糕
Collection<Cake> cakes = CakeDB.getAll();
out.write("本站提供的蛋糕有:<br>");
// 遍历输出所有蛋糕
for (Cake cake : cakes) {
// 获取蛋糕的id
String url = "PurchaseServlet?id=" + cake.getId();
// 获取蛋糕的名字和id,并跳转到 PurchaseServlet
out.write(cake.getName() + "<a href='" + url + "'>点击购买</a><br>");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- PurchaseServlet.java
@WebServlet(name = "PurchaseServlet", value = "/PurchaseServlet")
public class PurchaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
// 这个 Servlet 起到中转的作用,用来判断是否购买蛋糕,根据情况来重定向
String id = request.getParameter("id");
// 如果id为空,将重定向到 ListCakeServlet
if (id == null) {
response.sendRedirect("ListCakeServlet");
return;
}
Cake cake = CakeDB.getCake(id); // 根据id获取蛋糕
HttpSession session = request.getSession(); // 获取session
List<Cake> cart = (List<Cake>) session.getAttribute("cart"); // 通过键获取session里的值
// 如果session中的键的值为空,就创建列表,设置session数据
if (cart == null) {
cart = new ArrayList<>();
session.setAttribute("cart", cart);
}
cart.add(cake); // 不等于空添加数据
// session的设置
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60 * 30);
cookie.setPath("/Servlet");
response.addCookie(cookie);
response.sendRedirect("CartServlet"); // 有蛋糕会重定向 CarServlet
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- CartServlet.java
@WebServlet(name = "CartServlet", value = "/CartServlet")
public class CartServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
List<Cake> cart = null;
boolean purFlag = true; // 定义标识
HttpSession session = request.getSession(false);
// 如果session为空,标识为假
if (session == null) {
purFlag = false;
} else {
// session不为空
// 通过键获取session里的值
cart = (List<Cake>) session.getAttribute("cart");
// 如果session中的键的值为空,标识为假
if (cart == null) {
purFlag = false;
}
}
// 如果标识为假
if (!purFlag) {
out.write("对不起,您还没有购买任何商品!<br>");
}else {
// 否则标识为真
out.write("您购买的蛋糕有:<br>");
// 遍历输出蛋糕名称
for (Cake cake : cart) {
out.write(cake.getName()+"<br>");
}
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
5. セッションの概要
- セッションの役割
- ユーザー情報やショッピングカート情報などを保存します。
- セッション有効期間
- SessionID はブラウザを開いた瞬間から存在し、ブラウザを閉じると無効になります。
- セッションの有効期限を設定可能
- セッションを保存する方法
- セッションはサーバーによってデータを保存します
- セッションはデータを保存および取得できます
3. セッションとクッキーの違い
同じ:
- Cookie とセッションは両方とも、セッション内の複数のリクエスト間でデータを共有するために使用されます。
違う:
- 保存場所: Cookie はクライアント側に保存され、Session はサーバー側に保存されます。
- セキュリティ: Cookie は安全ではありませんが、セッションは安全です
- データサイズ: Cookie 最大 3KB、セッションのサイズ制限なし
- 保存時間: Cookie は長期間保存でき、セッションのデフォルトは 30 分です。
- サーバーのパフォーマンス: Cookie はサーバー リソースを占有せず、セッションはサーバー リソースを占有します。