Session&Cookie 你的名字 2023-09-29 23:56 46阅读 0赞 ## 一.会话 ## ### 1.1概念 ### http协议是基于请求与响应的无状态协议,但是进行使用时,通常会进行多次的请求与响应,将多次的请求与响应当做一个会话(浏览器窗口没有关闭) * 是一个过程,用户打开浏览器浏览网页(对同一个服务器多次请求–响应),关闭浏览器,这个过程称为会话 ### 1.2作用 ### 以因为http协议不会保存客户端状态,所以需要使用会话技术进行客户端数据的存储 * 每个用户与服务器交互,会产生一些数据,程序希望保存这些数据,就可以保存在会话对象中。 ## 二.cookie ## ### 2.1概念 ### * 是客户端的会话技术,默认cookie是保存在用户的浏览器上 * 程序把用户的数据以cookie的形式写回到用户的浏览器上(响应头:set-cookie) * 当用户使用浏览器访问程序的时候,携带自己浏览器上的cookie(请求头:cookie) ### 2.2原理 ### * cookie是服务器端创建,客户端保存(默认浏览器的缓存中) * cookie是基于http协议的 * cookie可以在客户端与服务器端传递数据 当浏览器向服务器发送请求,服务根据请求处理后决定是否创建cookie,服务器创建cookie并设置cookie相关的信息(数据.地址.时效),并将其放置到响应头中,发送至浏览器,浏览器解析响应头获取cookie数据进行保存(浏览器允许存储cookie的情况下),当浏览器再次请求服务器时,根据存储时cookie设置的信息(地址:判断是否是设置的地址,时效:是否过期)判断是否携带cookie,将cookie放置到请求头中,发送给服务器,服务器接收后从请求头中解析cookie数据并使用. ### 2.3使用步骤 ### #### **创建cookie对象并发送至客户端** #### <table> <thead> <tr> <th>方法</th> <th>参数</th> <th>备注</th> </tr> </thead> <tbody> <tr> <td>new Cookie(name,value);</td> <td>name:存储cookie的名字 value:存储cookie的值</td> <td>name与value都为字符串(最好不要使用中文)</td> </tr> <tr> <td>response.addCookie(c1);</td> <td>c1:在响应头中添加的cookie对象</td> <td>该方法由响应对象提供</td> </tr> </tbody> </table> @WebServlet(name = "SetCookieServlet", value = "/set") public class SetCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //cookie由服务器创建 存储在客户端浏览器中 //cookie在java中使用Cookie类创建的对象进行表示 //当客户端浏览器请求服务 需要创建cookie时 创建Cookie对象 //cookie只能存储字符串 并每个cookie都是一个键值对 对象 //key与value都是字符串 不建议使用中文 如果使用中文在添加与获取时需要特殊操作 Cookie c1=new Cookie("username","李四"); Cookie c2=new Cookie("password","abcdef"); //cookie通过响应发送至客户端 response.addCookie(c1); response.addCookie(c2); } } 当浏览器请求对应url后,服务器创建cookie对象并响应 存储在客户端 cookie响应结果如下 ![在这里插入图片描述][c20bbe25107941afa9800f6bb3b0eec0.png_pic_center] 注意:在进行数据传输时会进行流的形式传输,如果数据是中文可能导致乱码问题(所以不建议使用中文作为数据) ![在这里插入图片描述][664f46e8ae754704ab96dad789c0ba7a.png_pic_center] 客户端获取cookie后进行保存,当再次请求时会携带请求的缓存数据,如上图request cookies所示 #### **获取请求中的cookie数据** #### <table> <thead> <tr> <th>方法</th> <th>参数</th> <th>备注</th> </tr> </thead> <tbody> <tr> <td>request.getCookies()</td> <td>无</td> <td>由request对象提供的获取请求头中cookie数组的方法</td> </tr> <tr> <td>c.getName()</td> <td>无</td> <td>由cookie对象提供的,获取对应cookie对象name的方法</td> </tr> <tr> <td>c.getValue()</td> <td>无</td> <td>由cookie对象提供的,获取对应cookie对象value的方法</td> </tr> <tr> <td>c.getPath()</td> <td>无</td> <td>由cookie对象提供的,获取cookie携带请求url路径</td> </tr> <tr> <td>c.getMaxAge()</td> <td>无</td> <td>由cookie对象提供的,获取cookie的存活时间</td> </tr> </tbody> </table> @WebServlet(name = "GetCookieServlet", value = "/get") public class GetCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //当客户端请求中携带了cookie数据 可以通过请求对象的方法获取cookie数组 Cookie[] cookies = request.getCookies(); //判断cookie是否为null if(cookies!=null){ for (Cookie c:cookies) { //获取name与value System.out.println(c.getName()+"|"+c.getValue()); //因为存储数据的编码与当前环境一致 所以在浏览器显示的中文乱码可以识别 } } } } #### cookie中文数据的编码与解码 #### 在进行cookie创建时,如果书写中文,在浏览器存储时可能出现乱码,所以可以先将其转换一定的编码后存储,获取后再解码(编码解码只不过是不想将中文直接显示.也可以理解为简单的加密) * URLEncoder.encode(“张三”, “UTF-8”);//编码 * URLDecoder.decode(cookie.getValue(), “UTF-8”);//解码 //在创建cookie添加value时 将数据字符串编码后添加 Cookie c1=new Cookie("username", URLEncoder.encode("张三", "UTF-8") );//编码 //张三编码后=>%E5%BC%A0%E4%B8%89 //在获取cookie后进行解码 输出 URLDecoder.decode(c.getValue(), "UTF-8");//解码 该编码与解码方式使用的是中文在url地址栏进行传输时的编码方式 #### 设置cookie的持久化时间 #### <table> <thead> <tr> <th>方法</th> <th>参数</th> <th>备注</th> </tr> </thead> <tbody> <tr> <td>c1.setMaxAge(min);</td> <td>min:设置持久化时间 单位 :秒</td> <td>如果不设置 或设置为任意负数 则为关闭浏览器失效</td> </tr> </tbody> </table> 在创建cookie时,可以通过方法设置cookie的持久化时间,如果没有设置默认为-1(任意负数),时间为当前浏览器关闭前(有些浏览器不允许没有进行安全注册(备案)的服务器存储长时间的cookie,但是允许默认cookie的使用) 当关闭浏览器,再次请求时,cookie就会失效,不会携带cookie数据 ![在这里插入图片描述][6f04e151bb4a4694a58b41bf84148ee9.png_pic_center] @WebServlet(name = "SetCookieServlet", value = "/set") public class SetCookieServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //在创建cookie添加value时 将数据字符串编码后添加 Cookie c1=new Cookie("username", URLEncoder.encode("张三", "UTF-8") );//编码 Cookie c2=new Cookie("password","abcdef"); //设置cookie的持久化时间 单位秒 c1.setMaxAge(60*5); //cookie通过响应发送至客户端 response.addCookie(c1); response.addCookie(c2); } ![在这里插入图片描述][787fcd37556845f9afcdc6dee4067a80.png_pic_center] 当关闭浏览器 请求获取cookie地址,由于只设置了username的存活时间,所以password设置为默认浏览器关闭失效,所以重新打开浏览器请求只有username ![在这里插入图片描述][65d9cd5c6b3c46448df029773decd0c8.png_pic_center] #### 设置cookie的访问路径 #### 当创建cookie时可以设置cookie的访问路径(当前请求服务器对应路径时才会携带cookie,请求其他路径不会携带cookie) <table> <thead> <tr> <th>方法</th> <th>参数</th> <th>备注</th> </tr> </thead> <tbody> <tr> <td>c1.setPath(url);</td> <td>url:设置请求的路径</td> <td>如果没有设置则当前服务器任意url都携带cookie</td> </tr> </tbody> </table> //设置cookie访问路径 //只有请求当前服务器并且访问路径为指定路径时才携带cookie //如果没有设置 默认为/ 请求当前服务器任意路径都会携带cookie c1.setPath("/get"); 由于username设置了请求的url为get 所以请求set路径时不会携带cookie ![在这里插入图片描述][52db4ae5b2974e70977559787e922a33.png_pic_center] 由于设置了项目名称,所以请求的url前需要书写项目名称,所以uername还是不会携带 ![在这里插入图片描述][22e0f4807c094e78b97dff5c6ffe8988.png_pic_center] 当直接请求服务器地址/get时,就会携带对应的cookie ![在这里插入图片描述][fc432b18195c471a8209ed03b3fc3b85.png_pic_center] //cookie常用的path设置路径 //1.默认路径/ //只要请求的是当前的服务器 都会携带cookie(默认) c1.setPath("/"); //2.项目路径 /项目名 //只要请求的url是指定项目下的url 都会携带cookie c1.setPath("/web0816") //3.服务路径 /项目名/服务名 //只有请求指定服务时 才会携带cookie c1.setPath("/web0816/get") #### 删除cookie #### cookie由服务器创建存储在客户端浏览器,所以不能通过方法直接删除,但是可以通过设置cookie的存活时间进行删除,也可以将value设置为空字符串 //清除Cookie Cookie cookie = new Cookie("username", ""); //1:设置访问的路径path, 这里的Path必须和设置Cookie 的路径保持一致 cookie.setPath(request.getContextPath()); //2:设置存活时间 cookie.setMaxAge(0); //3:将cookie发送到浏览器 response.addCookie(cookie); //删除cookie就是将指定cookie存活时间设置为0让浏览器删除 ### 2.4案例 ### #### 显示上一次访问时间 #### public class LastTimeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //通过request获取所有的cookie Cookie [] cks = req.getCookies(); //定义cookie变量 Cookie c = null; //判断cks是否为空 if(cks != null){ //遍历数组 for (Cookie cookie : cks) { //查找名字是lasttime的cookie if(cookie.getName().equals("lasttime")){ //找到了 c = cookie; break; } } } //获取系统当前时间 Date date = new Date(); //判断c是否为空 if(c == null){ //用户是第一次访问 c = new Cookie("lasttime", Long.toString(date.getTime())); //向客户端响应你好 resp.getWriter().write("Hello"); }else{ //用户不是第一次访问 String lasttime = c.getValue(); //日期解析 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String now = df.format(new Date(new Long(lasttime))); //响应到客户端 resp.getWriter().write("你好上一次访问的时间是"+now); c.setMaxAge(10); //将当前系统时间写入到cookie中 c.setValue(Long.toString(date.getTime())); } //将cookie写回浏览器 resp.addCookie(c); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } #### 显示用户浏览历史记录 #### product\_list.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <style type="text/css"> img{ width:200px; } </style> </head> <body> <h2>商品列表</h2> <div> <a href="/huihua/historyServlet?pid=1"><img alt="" src="./image/1.jpg"></a> </div> <div> <a href="/huihua/historyServlet?pid=2"><img alt="" src="./image/2.jpg"></a> </div> <div> <a href="/huihua/historyServlet?pid=3"><img alt="" src="./image/3.jpg"></a> </div> <div> <a href="/huihua/historyServlet?pid=4"><img alt="" src="./image/4.jpg"></a> </div> <h2>历史浏览记录</h2> <% Cookie [] ck = request.getCookies(); if(ck != null){ for(Cookie cookie : ck){ if(cookie.getName().equals("history")){ String lishi = cookie.getValue(); String [] goodsId = lishi.split("-"); for(int i = 0;i<goodsId.length;i++){ %> <img alt="" src="./image/<%=goodsId[i] %>.jpg"> <% } } } } %> </body> </html> HistoryServlet.java package com.yh; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HistoryServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取商品pid String pid = req.getParameter("pid"); //获取客户端发送的cookie Cookie[] cks = req.getCookies(); //定义cookie Cookie cookie = null; //判断cks是否为空 if(cks != null){ //遍历数组,查找历史纪录的cookie for (Cookie c : cks) { if(c.getName().equals("history")){ //历史纪录的cookie已经存在 cookie = c; } } } if(cookie == null){ //新建历史纪录cookie "1-2-3-" cookie = new Cookie("history", pid+"-"); }else{ //获取cookie的值 String lishi = cookie.getValue(); //将字符串转StringBuilder StringBuilder sb = new StringBuilder(lishi); //在字符串中查找pid if(sb.indexOf(pid) != -1){ //找到了 }else{ //没找到 sb.insert(0, pid+"-"); } lishi = sb.toString(); cookie.setValue(lishi); } //写回浏览器 resp.addCookie(cookie); //重定向商品列表 resp.sendRedirect("/huihua/product_list.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } ## 三.session ## ### 3.1概念 ### * session是服务器端的技术 * 服务器在运行时为每一个用户创建一个独享的session对象 * 每个用户在访问服务器过程中,产生的数据可以放在session对象中 * 每个用户需要保存个人的,每次访问服务器的时候,都携带个人的sessionid * session技术基于cookie,使用cookie传递sessionid。 ### 3.2原理 ### ![在这里插入图片描述][6bfd3bbce87c41d78ce9721c874a86f0.png_pic_center] session依赖于cookie保存sessionid,当客户端第一次请求服务器端时,服务器端根据需求判断是否需要创建存储会话数据的session对象(请求服务器可能不会直接创建session对象)。 如果需要创建session对象存储数据,那么在创建后获取创建session对象的id,在响应中添加对应的cookie存储并响应,当客户端再次请求时(没有关闭浏览器拥有sessionid缓存cookie),服务端获取请求携带的coolie数据中的sessionid获取存储对应会话的session对象并进行数据操作 注意:在客户端cookie中存储的id,只是一个标识,用于在请求时告诉服务器,应该从哪个sessio对象中获取数据,当浏览器关闭时,丢失的是在客户端浏览器存储的cookie对象,而在服务器中对应存储的session并没有丢失,而是达到最大存活时间后自动回收。 ### 3.3 API ### <table> <thead> <tr> <th>方法名</th> <th>功能</th> <th>备注</th> </tr> </thead> <tbody> <tr> <td>void setAttribute(String name, Object value)</td> <td>向域对象存入值</td> <td></td> </tr> <tr> <td>Object getAttribute(String name)</td> <td>域对象取值</td> <td></td> </tr> <tr> <td>void removeAttribute(String name)</td> <td>域对象删除值</td> <td></td> </tr> <tr> <td>String getId()</td> <td>session的空间有唯一的id值,获取该id值的。</td> <td></td> </tr> <tr> <td>void invalidate()</td> <td>销毁session对象</td> <td></td> </tr> </tbody> </table> ### 3.4创建和销毁 ### #### 创建 #### * HttpSession session=request.getSession() * 该方法可以创建session的对象,但是也可以来获取到session对象 * 根据cookie对象中是否有jsessionid的cookie,如果有,通过id值查找,找到了不用创建了,返回。如果没有找到,创建一个新的session对象。 * session.setAttribute(‘数据’) 存储数据 * session.getAttribute(‘对象’) * A90685673C053479D142FB92FB099BD1 * A90685673C053479D142FB92FB099BD1 * 12C54052AE2091B6FBBA46754F1B3D8D #### 销毁 #### * 配置session的默认销毁时间,默认值是30分钟(在tomcat/conf/web.xml文件中设置了session默认超时时间) <session-config> <session-timeout>30</session-timeout> </session-config> * 关闭服务器销毁session * 非正常的原因关闭服务器,销毁session * 如果正常关闭服务器,session会被序列化到磁盘上。 * 设置session最大的存活的时间 * void setMaxInactiveInterval(int interval) * 直接使用方法,销毁session * invalidate() ### 3.5购物车案例 ### product\_list.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <style type="text/css"> img{ width:200px; } </style> </head> <body> <h2>商品列表</h2> <div> <img alt="" src="./image/1.jpg"> <a href="./addCart?pid=1">添加到购物车</a> </div> <div> <img alt="" src="./image/2.jpg"> <a href="./addCart?pid=2">添加到购物车</a> </div> <div> <img alt="" src="./image/3.jpg"> <a href="./addCart?pid=3">添加到购物车</a> </div> <div> <img alt="" src="./image/4.jpg"> <a href="./addCart?pid=4">添加到购物车</a> </div> </body> </html> AddCartServlet.java package com.yh; import java.io.IOException; import java.util.HashMap; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class AddCartServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException { //获取商品id String pid = req.getParameter("pid"); //获取session 创建session HttpSession session = req.getSession(); //获取session中的购物车信息 Object o = session.getAttribute("cart"); //判断o是否为空 if(o == null){ //第一次添加购物车 //创建购物车 HashMap<String, Integer> map = new HashMap<String, Integer>(); //将商品放入购物车 map.put(pid, 1); //将购物车放入session session.setAttribute("cart", map); }else{ //不是第一次添加商品到购物车 //判断购物车中是否包含当前pid HashMap<String, Integer> map = (HashMap<String,Integer>)o; if(map.containsKey(pid)){ //获取当前商品的数量 Integer count = map.get(pid); //数量+1 count++; //将数量放入map集合 map.put(pid, count); }else{ //购物车不存在当前商品 map.put(pid, 1); } System.out.println(map); } //跳转添加成功页面 resp.sendRedirect("/huihua/addSucc.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } addCartSucc.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h2>添加成功页面</h2> <a href="./product_list.jsp">继续剁手</a> <a href="./cart.jsp">结算</a> </body> </html> cart.jsp <%@page import="org.apache.jasper.tagplugins.jstl.core.ForTokens"%> <%@page import="java.util.HashMap"%> <%@page import="java.util.Map"%> <%@page import="java.util.Set"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h2>购物车页面</h2> <c:choose> <c:when test="${empty sessionScope.cart }"> 没有数据 </c:when> <c:otherwise> <c:forEach var ="good" items="${sessionScope.cart }"> ${good } </c:forEach> </c:otherwise> </c:choose> </body> </html> ## Cookie和Session的区别 ## **从存储方式上比较** Cookie只能存储字符串,如果要存储非ASCII字符串还要对其编码; Session可以存储任何类型的数据,可以把Session看成是一个容器 cookie数据存放在客户的浏览器上,session数据放在服务器上; 单个cookie在客户端的限制是4K,就是说一个站点在客户端存放的COOKIE不能超过4K(不同浏览器不同); **从隐私安全上比较** Cookie存储在浏览器中,对客户端是可见的。信息容易泄露出去。如果使用Cookie,最好将Cookie加密 Session存储在服务器上,对客户端是透明的。不存在敏感信息泄露问题。 **从有效期上比较** Cookie保存在硬盘中,只需要设置maxAge属性为比较大的正整数,即使关闭浏览器,Cookie还是存在的 Session的保存在服务器中,设置maxInactiveInterval属性值来确定Session的有效期。并且Session依赖于名为JSESSIONID的Cookie,该Cookie默认的maxAge属性为-1。如果关闭了浏览器,该Session虽然没有从服务器中消亡,但也就失效了。 **从对服务器的负担比较** Session是保存在服务器的,每个用户都会产生一个Session,如果是并发访问的用户非常多,是不能使用Session的,Session会消耗大量的内存。 Cookie是保存在客户端的。不占用服务器的资源。像baidu这样的大型网站,一般都是使用Cookie来进行会话跟踪。 ## 作业 ## 1.完成购物车功能,添加查看购物清单方法,点击查看清单将相同物品数量进行展示 例如:购物车内物品\[花生,瓜子,矿泉水,花生,矿泉水,瓜子,大碗面\] 购物清单如下: 花生 x2 瓜子 x2 矿泉水 x2 大碗面 x1 2.书写代码,完成当前用户请求次数的限制(例如:许愿每个人只能许愿3次并记录) 在输入框输入信息并点击提交,服务器接受并保存,当保存数据达到上限,再次提交后会显示:已达最大提交次数 泄露出去。如果使用Cookie,最好将Cookie加密 Session存储在服务器上,对客户端是透明的。不存在敏感信息泄露问题。 **从有效期上比较** Cookie保存在硬盘中,只需要设置maxAge属性为比较大的正整数,即使关闭浏览器,Cookie还是存在的 Session的保存在服务器中,设置maxInactiveInterval属性值来确定Session的有效期。并且Session依赖于名为JSESSIONID的Cookie,该Cookie默认的maxAge属性为-1。如果关闭了浏览器,该Session虽然没有从服务器中消亡,但也就失效了。 **从对服务器的负担比较** Session是保存在服务器的,每个用户都会产生一个Session,如果是并发访问的用户非常多,是不能使用Session的,Session会消耗大量的内存。 Cookie是保存在客户端的。不占用服务器的资源。像baidu这样的大型网站,一般都是使用Cookie来进行会话跟踪。 ## 作业 ## 1.完成购物车功能,添加查看购物清单方法,点击查看清单将相同物品数量进行展示 例如:购物车内物品\[花生,瓜子,矿泉水,花生,矿泉水,瓜子,大碗面\] 购物清单如下: 花生 x2 瓜子 x2 矿泉水 x2 大碗面 x1 2.书写代码,完成当前用户请求次数的限制(例如:许愿每个人只能许愿3次并记录) 在输入框输入信息并点击提交,服务器接受并保存,当保存数据达到上限,再次提交后会显示:已达最大提交次数 [c20bbe25107941afa9800f6bb3b0eec0.png_pic_center]: https://img-blog.csdnimg.cn/c20bbe25107941afa9800f6bb3b0eec0.png#pic_center [664f46e8ae754704ab96dad789c0ba7a.png_pic_center]: https://img-blog.csdnimg.cn/664f46e8ae754704ab96dad789c0ba7a.png#pic_center [6f04e151bb4a4694a58b41bf84148ee9.png_pic_center]: https://img-blog.csdnimg.cn/6f04e151bb4a4694a58b41bf84148ee9.png#pic_center [787fcd37556845f9afcdc6dee4067a80.png_pic_center]: https://img-blog.csdnimg.cn/787fcd37556845f9afcdc6dee4067a80.png#pic_center [65d9cd5c6b3c46448df029773decd0c8.png_pic_center]: https://img-blog.csdnimg.cn/65d9cd5c6b3c46448df029773decd0c8.png#pic_center [52db4ae5b2974e70977559787e922a33.png_pic_center]: https://img-blog.csdnimg.cn/52db4ae5b2974e70977559787e922a33.png#pic_center [22e0f4807c094e78b97dff5c6ffe8988.png_pic_center]: https://img-blog.csdnimg.cn/22e0f4807c094e78b97dff5c6ffe8988.png#pic_center [fc432b18195c471a8209ed03b3fc3b85.png_pic_center]: https://img-blog.csdnimg.cn/fc432b18195c471a8209ed03b3fc3b85.png#pic_center [6bfd3bbce87c41d78ce9721c874a86f0.png_pic_center]: https://img-blog.csdnimg.cn/6bfd3bbce87c41d78ce9721c874a86f0.png#pic_center
还没有评论,来说两句吧...