• cookie与session是老生常谈的问题了,之前一直的认知是从测试视角,并不全面,这次通过开发的时间对cookie与session进行一个全面的挖底

    什么是cookie?

  • cookie 是服务器通知客户端保存kv对的一种技术

  • 客户端有了cookie之后,每次请求都发送给服务器
  • 每个cookie的大小不能超过4kb,,简单记忆 1个饼干4kb

    如何创建cookie?

    ```java

public class CookieServlet extends BaseServlet {

  1. /*
  2. * @Author shihu
  3. * @Description //TODO 创建cookied方法
  4. * @Date 9:22 下午 2021/9/12
  5. * @Param [req, resp]
  6. * @return void
  7. **/
  8. public void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  9. // 创建cookie对象
  10. Cookie cookie = new Cookie("key1", "value1");
  11. // 通知客户端保存cookie
  12. resp.addCookie(cookie);
  13. resp.getWriter().write("cookie创建成功");
  14. }
  15. // baseServlet 为封装类,进行一些提前的处理,不用在意

- 创建cookie对象,同时调用有参构造进行值设定
- 通知客户端保存cookie
```java
如何创建cookie
    客户端(浏览器 )                   服务器(tomcat
                    ----》          1 创建 cookie对象 
                                       Cookie cookie = new Cookie("key1","value1");
             通过响应头 set-cookie   2 通知客户端保存cookie

 收到响应后,发现有               通知客户端进行保存cookie
  set-cookie响应头
  就去查看是否有cookie
  没有则创建,有则修改      《-----          response.setCookie(cookie)
  • 注意:

    • cookie可以一次性创建多个,但是不能忘记response.addCookie 如果不add是不算数的

      服务端如何取得cookie?

  • 一句话代码 req.getCookies();cookie[] 方法返回为一个数组

      public void getCookie(HttpServletRequest request, HttpServletResponse response) throws IOException {
    
          Cookie[] cookies = request.getCookies();
          // servlet 原生没有提供根据cookie name来去查砸后value的方法,所以只能通过for循环来进行查找
          // 但是可以按照这个思路来进行封装
          for (Cookie cookie :
                  cookies) {
    //            response.getWriter().write(cookie.getName());
    //            response.getWriter().write(cookie.getValue());
              if ("key1".equals(cookie.getName())){
                  System.out.println("找到了自己想要的哪个cookie");
                  System.out.println(cookie.getValue());
              }
    
          }
    
      }
    
  • 需要注意的是,httpservlet没有提供像map那样根据cookie的name求获取value的方法,所以需要自行封装 ```java public class CookieUtils { /**

    • 查找指定名称的Cookie对象
    • @param name
    • @param cookies
    • @return */ public static Cookie findCookie(String name , Cookie[] cookies){ if (name == null || cookies == null || cookies.length == 0) {

       return null;
      

      }

      for (Cookie cookie : cookies) {

       if (name.equals(cookie.getName())) {
           return cookie;
       }
      

      }

      return null; }

}

<a name="ssrDs"></a>
# Cookie的修改

- 方案一
   - 1 先创建一个要修改的同名cookie对象
   - 在构造器方法时同时赋新值
   - 调用response.addCookie
- 方案二
   - 先查到要修改的cookie对象
   - 调用setVlue()方法进行修改
   - response.addCookie
- 方案二需要要修改的目标cookie必须存在
```java
       //  对cookie 进行修改
        // 1 首先创建一个要修改的同名的cookie对象
        // 2 在构造器,同时赋予新的cookie值
        Cookie cookie = new Cookie("key1", "newValue1");
        // 3 调用response.addCookie(cookie)  // 通知客户端保存修改之后的cookie
        response.addCookie(cookie);

        // 方案2
        // 1 先查找到需要修改的cookie对象
        cookie = CookieUtils.findByCookieName("cookieName")
        // 2 调用setValue 方法来赋予新的cookie值
        // 3 调用response.add(cookie) 方法
        // cookie 的值不能包含空格,特殊符号,中文

Cookie的生命控制

  • 其实也就是cookie的持续时间控制,管理cookie什么时间被销毁(删除
  • 相关方法为 setMaxAge() ```java public void setMaxAge(int expiry) {
      this.maxAge = expiry;
    
    }

- expiry 为 正数,在指定的秒数后过期
- 为负数,表示浏览器已关闭,cookie就删除,默认为-1
- 0 表示马上删除cookie
<a name="vCgF7"></a>
# Cookie有效路径path的设置

- cookie的path属性可以有效的过滤哪些cookie可以发送给服务器,哪些则不行
- path属性是通过请求的地址来进行有效的过滤的
```java

   cookieA   path=/工程路径
   cookieB    path=/工程路径/abc

  请求路径如下
    http://ip:port/工程路径/a.html

    cookieA 发送
    cookieB 不发送

    http://ip:port/工程路径/abc/a.html
    cookieA 发送
    cookieB 发送

image.png
经过这样设计的cookie 在非对应的path下是看不到该cookie存在的


    public  void  testPath(HttpServletRequest request,HttpServletResponse response) throws IOException {
        Cookie cookie = new Cookie("key233","value233");
        //  getContexzpath 得到工程路径
        cookie.setPath(request.getContextPath() + "/abc");  // 得到工程路径后的abc
        response.addCookie(cookie);
        response.getWriter().write("创建了一个带有path的cookie");


    }

Session 会话

  • 是什么
    • session就是一个接口 httpSession
    • session 就是会话, 用来维护一个客户端和服务器之间关联的一种技术
    • 每个客户端都有一个session会话
    • session会话中经常用来保存用户登录之后的信息
  • cookie 是保存在客户端-浏览器中的。session是保存在 服务器端的。

    如何创建session和获取session

  • 创建和获取session的api是一样的

  • request.getSession()
  • 判断是否为新创建出来的session ,isNew()
    如何创建和获取session,api是一样的
    request.getSession()
        第一次调用是:创建session会话
        之后调用都是,获取前面创建好的session会话对象

    针对如何判断session是否为最新创建的。httpServlet提供了一个api
        isNew() 判断到底是不是刚创建出来的(新的)
            true 表示刚创建
            false 表示获取之前创建的
    每个会话都有一个身份号,也就是id值,且id是唯一的
    getId()获取session的会话id值




public class SessionServlet extends BaseServlet {

    public void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 创建和获取session会话对象
        HttpSession session = req.getSession();
        // 判断 当前session会话,是否是新创建出来的
        boolean aNew = session.isNew();


        String id = session.getId();
        resp.getWriter().write("得到的sessionid为:"+ id);
        resp.getWriter().write("得到的session是否为新创建的:"+ aNew);
    }

image.png
image.png

Session 域数据存取

  • 同servletContext,servletRequest对象一样,可以对域内变量进行数存取

    # session域数据的存取
      public  void setAttribute(HttpServletRequest request,HttpServletResponse response) throws IOException {
          request.getSession().setAttribute("username","addicated");
          response.getWriter().write("向session中存储数据成功ing");
    
      }
    
      public void getAttribute(HttpServletRequest request, HttpServletResponse response) throws IOException {
          Object username = request.getSession().getAttribute("username");
          response.getWriter().write(" 从session中取出的数据是 "+ username);
      }
      1 通过session对象。setAttr ,getAttr即可
    

    Session 的生命控制

  • void setMaxInactiveInterval(int var1);

    • 设置超时时间,超过指定的时间,session就会销毁
      • 单位为秒
        • 正数 设置超时时间
        • 负数 表示永不超时
  • int getMaxInactiveInterval();
    • 获取当前项目/服务器中对session超时时间的配置
  • void invalidate();

    • 立即销毁session,方法会让当前的sesison会话马上超时无效

      Session的默认超时时间

  • 默认为1800秒,即30min

  • 那么这个默认时间从何而来?
    • 是从tomcat下的web.xml 中进行的配置,表示所有部署在tomcat服务器上的项目的默认会话超时时间
  • 修改

    • 当然也可以针对项目修改,在项目下的web.xml 中进行配置变更

         <session-config>
             <session-timeout>20</session-timeout>
         </session-config>
      </web-app>
      
    • 同样可以使用前面叙述的api来进行修改。

      Session超时的概念

  • 区别于一般意义上的超时,session超时指的是两次请求之间间隔的最大时长 ```java session超时的概念,指的是客户端两次请求的最大间隔时长 客户端(浏览器 设置3秒超时 服务器(tomcat

                  -----》                      session对象
                                              开始倒计时 timeout=3
                                                    timeout=2
                                                     timeout=1
                  间隔1秒或者两秒 对服务器请求            timeout=0
                  ------》                   timeout重新刷新为3
           原因就是因为 session的过期机制实际上是两次请求之间的间隔超过过期时间,判定session过期
           如果在session的过期时间内发生了再次请求,就会重置过期时间
    

```

浏览器和Session之间关联的技术内幕

  • 如下图
  • image.png