What are cookies for?
Thinking Question 1 - Throwing bricks to attract jade
When you visit a certain website, can you see the time when you last logged in to the website, and what you should pay attention to is that the
last login time of different users must be different. How is this achieved?
Thinking Question 2 - Throwing Bricks to Induce Jade
When you visit a shopping website, can you see the products you have browsed before? The products browsed by different users must be different. How is this achieved?
The solution - cookie technology
Cookie (small cookie) is a client-side technology, and the server writes each user's data to the user's respective browser in the form of a cookie. When users use a browser to access web resources in the server, they will bring their own data. In this way, the web resource handles the user's own data. 【Simple diagram】
cookie introduction
Two said cookie
- Cookie is the server saving the user's information on the client side, such as login name, browsing history, etc., which can be saved in the form of cookie.
- Cookie information is like a cookie (cookie), the amount of data is not large, and the server can read it from the client browser when needed, which can be understood through the diagram.
What can cookies be used for?
- Save information such as last login time
- Save user name, password, no need to log in again for a certain period of time
- Personalization of the website, such as customizing the services and content of the website.
Cookies are saved in the local browser! ! !
Basic use of cookies
Documentation
https://docs.oracle.com/javaee/7/api/
Common methods of cookies
-
A cookie is a bit like a table (KV), divided into two columns, one is the name, the other is the value, and the data type is String, as shown in the figure
-
How to create a cookie (created on the server side)
Cookie c = new Cookie(String name,String val);
c.setMaxAge();//保存时间
- How to add a cookie to the client
response.addCookie(c);
- How to read cookies (read cookie information on the server side)
request.getCookies();
The underlying implementation mechanism of cookies - creating and reading cookies
Server-side creation of cookies
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @ClassName CreateCookie
* @Description TODO
* @Author zephyr
* @Date 2022/12/18 22:37
* @Version 1.0
*/
@WebServlet(name = "CreateCookie", value = "/createCookie")
public class CreateCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========CreateCookie被调用==========");
//1. 创建一个Cookie对象
/**
* 1) username 该cookie的名字,唯一的,可以理解成key
* 2) zephyr 该cookie的值
* 3) 可以创建多个cookie对象
* 4) 这是这个cookie在服务器端,还没有到浏览器
*/
Cookie cookie = new Cookie("username", "zephyr");
response.setContentType("text/html;charset=utf-8");
//2. 将cookie发送给浏览器,让浏览器将该cookie保存起来
response.addCookie(cookie);
PrintWriter writer = response.getWriter();
writer.println("<h1>创建cookie成功!<h1>");
writer.flush();
writer.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Server-side read cookie
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
* @ClassName ReadCookies
* @Description 演示:读取从客户端发送来的cookie信息
* @Author zephyr
* @Date 2022/12/19 10:47
* @Version 1.0
*/
@WebServlet(name = "ReadCookies", value = "/readCookies")
public class ReadCookies extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========CreateCookie被调用==========");
//1. 通过Request对象读取所有Cookie信息
Cookie[] cookies = request.getCookies();
//2. 遍历Cookie
if (cookies != null && cookies.length > 0){
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + " = " + cookie.getValue());
}
}
//Cookie: JSESSIONID=BA235330CCE65FE095ED5EFB37B3A113; username=zephyr
//3. 给浏览器返回信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h1>读取cookie信息成功<h1>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
What is the use of JSESSIONID?
session means session.
JSESSIONID is the unique identifier of the session.
Cookie application example
Read the specified cookie
Traverse through a tool class to find the specified cookie.
CookieUtils.java
package com.hspedu.cookie;
import javax.servlet.http.Cookie;
/**
* @ClassName CookieUtils
* @Description 对Cookie数组进行过滤
* @Author zephyr
* @Date 2022/12/19 11:40
* @Version 1.0
*/
public class CookieUtils {
public static Cookie readCookieByName(String cookieName, Cookie[] cookies) {
//如果传输参数不正确就返回null
if (cookieName == null || "".equals(cookieName) || cookies == null || cookies.length == 0) {
return null;
}
for (Cookie cookie : cookies
) {
if (cookieName.equals(cookie.getName())) {
return cookie;
}
}
//没找到就返回null
return null;
}
}
modify cookies
Requirement: Given a specified cookie, find the cookie, if found, modify the value to jyl-hi; if not found, prompt that the cookie cannot be found.
UpdateCookie.java
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
/**
* @ClassName UpdateCookie
* @Description TODO
* @Author zephyr
* @Date 2022/12/19 11:59
* @Version 1.0
*/
@WebServlet(name = "UpdateCookie", value = "/updateCookie")
public class UpdateCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========UpdateCookie被调用==========");
//1. 根据name,查找cookie
String cookieName = "email";
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName(cookieName, cookies);
if (cookie == null){
System.out.println("当前访问服务器的客户端没有该cookie");
} else {
cookie.setValue("jyl-hi");
//2. 遍历cookie查看值
for (Cookie cookie_ : cookies) {
System.out.println(cookie_.getName() + " = " + cookie_.getValue());
}
//3. cookie返回给浏览器
response.addCookie(cookie);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
After resetting the value of the cookie through setValue, be sure to
response.addCookie(cookie)
return the cookie!
If the newly created cookie has the same name as the browser's existing cookie, it will be overwritten.
Cookie life cycle
introduce
- The life cycle of cookies refers to how to manage when cookies are destroyed (deleted)
setMaxAge()
- Positive number, indicating to expire after the specified number of seconds
- A negative number means that the cookie will be deleted when the browser is closed (the default value is -1)
- 0, means delete the cookie immediately
Applications
Demonstrate the life cycle of cookies
System.out.println("==========CookieLive被调用==========");
//演示创建一个cookie,生命周期为60s
Cookie cookie = new Cookie("job", "java");
//1. 从创建该cookie开始计时,60s后就无效了
//2. 浏览器根据创建时间,计时到60s就认为该cookie无效
//3. 如果该cookie无效,那么浏览器在发出http请求时,就不在携带该cookie
cookie.setMaxAge(60);
response.addCookie(cookie);
Visit CookieLive, return Set-Cookie: job=java; Max-Age=20; Expires=Mon, 19-Dec-2022 04:51:49 GMT
. Tells the browser to invalidate (do not carry) this cookie after 60 seconds.
After 60 seconds, the browser sends an http request to the server without the job cookie.
Demo deletes a cookie
System.out.println("==========CookieLive被调用==========");
//演示删除一个cookie:username
//1. 先得到这个cookie
Cookie usernameCookie = CookieUtils.readCookieByName("username", request.getCookies());
//2. 将其的生命周期设置为0
usernameCookie.setMaxAge(0);
//3. 通知浏览器
response.addCookie(usernameCookie);
Capture packets on the browser side and you can see in the response header: Set-Cookie: username=zephyr; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT
.
Then you can see that the cookie in the browser has been deleted.
What happens if you don't set the lifecycle
However, if the life cycle is not set, the default setMaxAge(-1)
is a session-level life cycle, which means that the cookie will be deleted when the browser is closed.
effective cookie path
- Cookie effective path Path setting
- The path attribute of Cookie can effectively filter which Cookies can be sent to the server. Which ones are not posted. The path attribute is effectively filtered by the requested address
- The rules are as follows
Applications
System.out.println("==========CookiePath被调用==========");
//1. 创建2个cookie
Cookie bandCookie = new Cookie("band", "Gelneryus");
Cookie instrumentCookie = new Cookie("instrument", "Guitar");
//2. 设置不同的有效路径
bandCookie.setPath(request.getContextPath()); // ContextPath = /cs
// instrumentCookie的有效路径是 /cs/ins
instrumentCookie.setPath(request.getContextPath() + "/ins");
//3. 保存到浏览器
response.addCookie(bandCookie);
response.addCookie(instrumentCookie);
//4. 给浏览器返回信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h1>设置cookie路径成功<h1>");
Homework: Automatically fill in the login account
- If the user name is hspedu and the password is 123456, the user is considered legal and the login is successful, otherwise the login is invalid
- It is required to realize that if the login is successful, the user, who logs in within 3 days, can automatically fill in his login name
- The login page needs to be returned using a servlet, not html
Login login page (written as Servlet)
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @ClassName Login
* @Description TODO
* @Author zephyr
* @Date 2022/12/19 16:05
* @Version 1.0
*/
@WebServlet(name = "Login", value = "/login")
public class Login extends HttpServlet {
HttpServletRequest request = null;
HttpServletResponse response = null;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========Login被调用==========");
this.request = request;
this.response = response;
//先读取cookie,看看cookie里有没有username和pwd
Cookie[] cookies = request.getCookies();
Cookie usernameCookieRead = CookieUtils.readCookieByName("username", cookies);
Cookie pwdCookieRead = CookieUtils.readCookieByName("pwd", cookies);
if (usernameCookieRead != null && pwdCookieRead != null) {
//cookie存在
showLoginHtml(usernameCookieRead.getValue(), pwdCookieRead.getValue());
} else {
showLoginHtml("", "");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
public void showLoginHtml(String username, String pwd) throws ServletException, IOException{
String content = "<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <base href=\"/cs/\">\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>登录界面</title>\n" +
"</head>\n" +
"<body>\n" +
"<h1>用户登录界面</h1>\n" +
"<form action=\"loginServlet\" method=\"get\">\n" +
" 用户名:<input type=\"text\" name=\"username\" value=\""+username+"\"><br>\n" +
" 密码:<input type=\"text\" name=\"pwd\" value=\""+pwd+"\"><br>\n" +
" <input type=\"submit\" value=\"登录\">\n" +
"</form>\n" +
"\n" +
"</body>\n" +
"</html>";
if (request != null && response != null){
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println(content);
writer.flush();
writer.close();
}
}
}
LoginServlet
package com.hspedu.cookie;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @ClassName LoginServlet
* @Description TODO
* @Author zephyr
* @Date 2022/12/19 15:13
* @Version 1.0
*/
@WebServlet(name = "LoginServlet", value = "/loginServlet")
public class LoginServlet extends HttpServlet {
String correctUserName = "jingyl";
String correctPwd = "123456";
HttpServletRequest request = null;
HttpServletResponse response = null;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("==========LoginServlet被调用==========");
this.request = request;
this.response = response;
if (checkForm()){
showSuccess();
} else {
showFail();
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/**
* 返回登陆成功的信息
*/
public void showSuccess() throws ServletException, IOException {
//通知浏览器已经写入cookie
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>登录成功!<h1>");
}
/**
* 返回登陆失败的信息
*/
public void showFail() throws ServletException, IOException {
//通知浏览器已经写入cookie
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>登录失败!<h1>");
}
public boolean checkForm() throws ServletException, IOException {
//读取表单里的username和pwd
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
if (username.equals(correctUserName) && pwd.equals(correctPwd)) {
//如果账号密码正确则保存在浏览器的cookie
//创建cookie保存用户名和密码
Cookie usernameCookie = new Cookie("username", username);
Cookie pwdCookie = new Cookie("pwd", pwd);
//生命周期为3天
usernameCookie.setMaxAge(60 * 60 * 24 * 3);
pwdCookie.setMaxAge(60 * 60 * 24 * 3);
response.addCookie(usernameCookie);
response.addCookie(pwdCookie);
return true;
} else {
return false;
}
}
}
Cookie considerations and details
- A cookie can only identify one kind of information, and it contains at least a name (NAME) and setting value
(VALUE) to identify the information. - A WEB site can send multiple cookies to a browser, and a browser can also store cookies provided by multiple WEB sites.
- There is no limit to the total number of cookies, but there is a limit to the number of cookies for each domain name and the size of each cookie (different browsers have different restrictions, just know it), and cookies are not suitable for storing information with a large amount of data.
- Note that when deleting cookies, the paths must be consistent, otherwise they will not be deleted
- Solve the Chinese garbled characters of cookies in Java servlet [code demo EncoderCookie.java ReadCookie2.java]
It is not recommended to store Chinese cookie information, which may be garbled, which can be solved by url encoding and decoding.
Solve the Chinese cookie garbled problem
If you save the Chinese Cookie directly, an error will be reported
URLEncoder.encode()
Chinese can be encoded by
System.out.println("==========EncoderCookie被调用==========");
//1. 如果直接错放中文的cookie会报错
//2. 通过将中文编码成 URL 编码
String company = URLEncoder.encode("景风眠教育", "utf-8");
Cookie cookie = new Cookie("company", company);
response.addCookie(cookie);
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>EncoderCookie被成功调用[中文乱码测试]<h1>");
writer.flush();
writer.close();
URLDecoder.decode()
decoded by
System.out.println("==========EncoderCookie被调用==========");
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName("company", cookies);
System.out.println(cookie.getName() + " = " + cookie.getValue());
System.out.println("===========解码后===========");
String decode = URLDecoder.decode(cookie.getValue());
System.out.println(cookie.getName() + " = " + decode);
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("<h1>DecoderCookie被成功调用[中文解码测试]<h1>");
writer.flush();
writer.close();