7

day20-web开发会话技术02 - 一刀一个小西瓜

 1 year ago
source link: https://www.cnblogs.com/liyuelian/p/16913461.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

WEB开发会话技术02

6.Cookie的生命周期

默认情况下,Cookie只在浏览器的内存中存活,也就是说,当你关闭浏览器后,Cookie就会消失。但是也可以通过方法设置cookie的生存时间。

cookie的生命周期指的是如何管理cookie,什么时候cookie被销毁。

  • setMaxAge(int expiry):设置 cookie 的最大生存时间,以秒为单位
    • 整数:表示在指定的秒数后过期
    • 负数:表示浏览器关闭,cookie就会被删除(默认值是-1)
    • 0,表示马上删除cookie

6.1cookie生命周期expiry>0

CookieLive:

package com.li.cookie; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;import java.io.PrintWriter; @WebServlet(urlPatterns = {"/CookieLive"})public class CookieLive extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("CookieLive doPost被调用..."); //创建一个cookie,生命周期为 60s Cookie cookie = new Cookie("job", "java"); //1.从创建改cookie开始计时,60秒后就无效 //2.由浏览器来根据创建的时间来开始计时,到时间后就认为该cookie无效 //3.如果该cookie无效了,那么浏览器在发出HTTP请求时,就不会带上该cookie cookie.setMaxAge(60); //将cookie保存到浏览器 response.addCookie(cookie); //给浏览器返回信息 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.print("<h1>设置cookie生命周期成功</h1>"); writer.flush(); writer.close(); }}
  1. 在浏览器中访问该servlet:

    image-20221120221656177
  2. 可以看到该cookie的创建于: "Sun, 20 Nov 2022 14:15:39 GMT"

    真实时间为上述时间再加八小时

    image-20221120221755132
  3. 超过60s后,再去访问Tomcat服务器:

    image-20221120222222568

    可以看到在浏览器发送的HTTP请求中的Cookie字段已经没有了设置的cookie:

    image-20221120222535236.png

说明:由浏览器来根据创建的时间来开始计时,到时间后就认为该cookie无效。如果该cookie无效了,那么浏览器在发出HTTP请求时,就不会带上该cookie。

但是此时cookie没有被删除,在关闭浏览器的时候才会被删除。

6.2演示删除cookie(expiry=0)

删除下图名为username的cookie

image-20221121162351398
package com.li.cookie; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;import java.io.PrintWriter; @WebServlet(urlPatterns = {"/cookieLive"})public class CookieLive extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //演示删除一个cookie //1.先得到usernameCookie Cookie[] cookies = request.getCookies(); Cookie usernameCookie = CookieUtils.readCookieByName("username", cookies); if (usernameCookie != null) { //2.将其生命周期设置为0 usernameCookie.setMaxAge(0); //3.重新保存该cookie,因为你将其生命周期设置为0,就等价于让浏览器删除该cookie response.addCookie(usernameCookie);//在响应体的Set-Cookie } else { System.out.println("没有找到该cookie"); } //给浏览器返回信息 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.print("<h1>设置cookie生命周期成功</h1>"); writer.flush(); writer.close(); }}

redeployTomcat,浏览器访问该servlet,点击查看HTTP响应包:可以看到响应包中设置了该cookie的过期时间为1970年,这意味着浏览器将立即删除该cookie。

  1. Set-Cookie: username=jack; Expires=Thu, 01-Jan-1970 00:00:10 GMT

    image-20221121163544953
  2. 点击查看cookie存储,可以发现该cookie已经被删除了

    image-20221121163639913

说明:setMaxAge()方法设置参数为零时,当浏览器接收到服务器的响应包时,会立即删除该cookie。

6.3默认生命周期(expiry<0)

如果没有设置setMaxAge,或者setMaxAge的设置参数为负数,那么默认创建的cookie是会话级别的(即关闭浏览器就销毁了)

如下,MaxAge的默认设置值为-1

image-20221121164922368

7.Cookie的有效路径

image-20221121165341353

cookie有效路径Path的设置:

  1. Cookie的path属性,可以有效地过滤哪些Cookie可以发送给服务器,哪些不发。path属性是通过请求的URL地址来进行有效地过滤

  2. 规则如下:

    cookie1.setPath=/工程路径 cookie2.setPath=/工程路径/aaa

    1. 若请求地址为:http://ip:port/工程路径/资源
      cookie1发送给服务器
      cookie2不会发送给服务器
    2. 若请求地址为:http://ip:port/工程路径/aaa/资源
      cookie1发送给服务器
      cookie2发送给服务器

    即如果请求的url的地址包含了cookie设置的有效路径,则这个cookie就会被发送给服务器。

    说明:如果没有设置cookie的有效路径,默认就是 /工程路径

演示Cookie的有效路径的使用

package com.li.cookie; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;import java.io.PrintWriter; @WebServlet(urlPatterns = {"/cookiePath"})public class CookiePath extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("cookiePath doPost被调用"); //1.创建两个cookie Cookie cookie = new Cookie("address", "beijing"); Cookie cookie2 = new Cookie("salary", "20000"); //2.设置不同的有效路径 //request.getContextPath()=/application context cookie.setPath(request.getContextPath());//有效路径=/cs cookie2.setPath(request.getContextPath() + "/aaa");//有效路径=/cs/aaa //3.保存到浏览器 response.addCookie(cookie); response.addCookie(cookie2); //4.给浏览器回送提示信息 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.print("<h1>设置cookie有效路径成功</h1>"); writer.flush(); writer.close(); }}

如下,访问http://localhost:8080/cs/cookiePath,创建了address和salary两个cookie并设置了不同的有效路径

image-20221121172033653

现在来访问http://localhost:8080/cs/xxx,抓包如下:

image-20221121172428294

在来访问http://localhost:8080/cs/aaa/xxx

image-20221121172527454

完成自动填写登录账户案例,如果用户登录成功,则下次登录自动填写登录账户。

  1. 如果用户名是olien,密码是1234。则认为该用户合法,登录成功,否则失败。
  2. 要求实现:如果登录成功,则该用户在三天内登录可以自动填写其登录名。
%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%86%99%E7%99%BB%E5%BD%95%E8%B4%A6%E5%8F%B7%E5%88%86%E6%9E%90.png

CookieUtils:

package com.li.cookie; import javax.servlet.http.Cookie; public class CookieUtils { //编写一个方法,返回指定名字的cookie值 public static Cookie readCookieByName(String name, Cookie[] cookies) { //判断传入的参数是否正确 if (name == null || "".equals(name) || cookies == null || cookies.length == 0) { return null; } //否则,就遍历cookies for (Cookie cookie : cookies) { if (name.equals(cookie.getName())) { return cookie; } } return null; }}

loginServlet:

package com.li.cookie; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;import java.io.PrintWriter; @WebServlet(urlPatterns = {"/login"})public class Login extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("login doPost被调用..."); //编写servlet(以实现自动填写登录名和密码) String usernameVal = ""; String pwdVal = ""; //访问servlet时,首先获取浏览器的cookie数组 Cookie[] cookies = request.getCookies(); //判断得到的cookie数组是否存在 if (cookies != null && cookies.length != 0) {//如果存在,且长度不为0 //获取cookie的值 Cookie usernameCookie = CookieUtils.readCookieByName("username", cookies); Cookie pwdCookie = CookieUtils.readCookieByName("pwd", cookies); if (usernameCookie != null && pwdCookie != null) {//如果存在指定的cookie //获取指定的cookie的值 usernameVal = usernameCookie.getValue(); pwdVal = pwdCookie.getValue(); } } //绘制html页面 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); if (usernameVal != null && pwdVal != null) { writer.print("<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + "<head>\n" + " <meta charset=\"UTF-8\">\n" + " <title>登录页面</title>\n" + "</head>\n" + "<body>\n" + "<form action=\"/cs/loginSuccess\" method=\"post\">\n" + " 用户名:<input type=\"text\" name=\"username\" value=\"" + usernameVal + "\"/><br/>\n" + " 密码:<input type=\"password\" name=\"pwd\" value=\"" + pwdVal + "\"/><br/>\n" + " <input type=\"submit\" value=\"登录\"/>\n" + "</form>\n" + "</body>\n" + "</html>"); } writer.flush(); writer.close(); }}

LoginSuccess:

package com.li.cookie; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;import java.io.PrintWriter; /** * 接收用户输入,判断该用户是否合法,并返回提示信息 */@WebServlet(urlPatterns = {"/loginSuccess"})public class LoginSuccess extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("loginServlet doPost 被调用..."); //1.接收表单用户名和密码 String username = request.getParameter("username"); String pwd = request.getParameter("pwd"); //给浏览器返回提示信息 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); //2.判断数据是否合法 if ("olien".equals(username) && "1234".equals(pwd)) {//合法 //将登陆成功的用户名和密码以cookie形式保存到浏览器中 //根据用户名和密码创建cookie Cookie usernameCookie = new Cookie("username", "olien"); Cookie pwdCookie = new Cookie("pwd", "1234"); //设置cookie生命周期 usernameCookie.setMaxAge(60 * 60 * 24 * 3);//3天 pwdCookie.setMaxAge(60 * 60 * 24 * 3);//3天 //给浏览器返回cookie response.addCookie(usernameCookie); response.addCookie(pwdCookie); //给浏览器返回提示信息 writer.print("<h1>登录OK</h1>"); } else {//不合法 writer.print("<h1>登录失败,请重新登录</h1>"); } writer.flush(); writer.close(); }}

redeployTomcat,在浏览器中访问http://localhost:8080/cs/login。 输入正确的用户名密码,成功跳转。

image-20221121204334606
image-20221121204414669

此时,再次访问该页面,可以看到登录页面自动填写登录名:

%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95%E5%A1%AB%E5%86%99%E8%B4%A6%E5%8F%B7%E5%AF%86%E7%A0%81.gif

9.Cookie注意事项和细节

  1. 一个cookie只能标识一种信息,它至少含有一个标识该信息的名称(name)和设置值(value)
  2. 一个web站点可以给一个浏览器发送多个cookie,一个浏览器也可以存储多个web站点提供的cookie
  3. cookie的总数量没有限制,但是每个域名的cookie数量和每个cookie的大小是有限制的(不同的浏览器限制不同),因此cookie不适合存放数据量大的信息
  4. 注意:删除cookie时,path必须一致,否则不会删除
  5. Java Servlet中cookie中文乱码解决。如果cookie存放中文,默认会报错,但可以通过URL编码和解码来解决(尽量不要使用cookie保存中文信息)

例子:解决cookie中文乱码

package com.li.cookie; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;import java.io.PrintWriter;import java.net.URLEncoder; @WebServlet(name = "EncoderCookie", urlPatterns = {"/encoderCookie"})public class EncoderCookie extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("EncoderCookie doPost被调用..."); //1.创建一个带有中文的cookie //Cookie company = new Cookie("company", "小葵花公司"); //2.保存到浏览器 /** * 1.如果直接存放带有中文的cookie,Tomcat服务器会报错: * Control character in cookie value or attribute. * 2.解决方法:将中文编码设置成URL编码 * 3.使用工具类 URLEncode * 4.编码后再保存cookie即可 */ String company = URLEncoder.encode("小葵花公司", "utf-8"); Cookie cookie = new Cookie("company", company); response.addCookie(cookie); //3.给浏览器返回提示信息 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.print("<h1>设置cookie中文信息成功</h1>"); writer.flush(); writer.close(); }}
  1. 浏览器访问地址:http://localhost:8080/cs/encoderCookie

    image-20221121211750168
  2. 进行抓包:如下,浏览器在保存中文cookie时,以url编码进行保存

    image-20221121211718026
    image-20221121211942352
  3. 服务器在获取该中文cookie时,也要以url编码形式进行解码,否则得到的cookie的值是url编码。

    ReadCookie2:

    package com.li.cookie; import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;import java.io.PrintWriter;import java.net.URLDecoder; @WebServlet(name = "ReadCookie2", value = "/readCookie2")public class ReadCookie2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //读取中文cookie Cookie[] cookies = request.getCookies(); Cookie companyCookie = CookieUtils.readCookieByName("company", cookies); String companyVal = companyCookie.getValue(); System.out.println("companyVal= " + companyVal);//url编码 //解码 companyVal = URLDecoder.decode(companyVal, "utf-8"); System.out.println("解码后的companyVal= " + companyVal);//中文 //给浏览器返回提示信息 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.print("<h1>读取中文cookie并解码成功</h1>"); writer.flush(); writer.close(); }}

    浏览器访问该资源,后台输出如下:

    image-20221121213440651

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK