Servlet(五)【Cookie会话技术、Cookie免登录案例】

前 言

人总是要有梦想的,也许哪天就实现了呢!

如果有不正确之处,还望指正,毕竟我还是一个菜鸟!


一、会话技术

  1. 概述:一次会话中包含多次请求和响应

    一次会话:当浏览器发送HTTP请求给服务器资源时,服务端创建会话对象后,则会话在浏览器和服务器之间完成建立,直到有一方断开为止,会话结束
    功能:在一次会话的范围内(从创建到消亡的过程中)的多次http请求中,浏览器和服务器可以共享Cookie或Session中存储的数据
    
  2. 方式:

    1. 客户端会话技术:Cookie,创建与服务器中,数据存储于浏览器中
    2. 服务器端会话技术:Session,创建于服务器中,数据存储于服务器中

二、Cookie 介绍

  1. 概述:Cookie是一种客户端技术,Cookie存储在客户端浏览器中,用于存储用户的基本信息。

  2. 为什么需要Cookie技术?

    假设现在我们在淘宝买东西,先是添加了一个物品到购物车,然后又添加一个物品到购物车,在这期间,你发起了多次请求,我们知道通过request域是
    不能在多次请求之间共享的,而response对象也只是对浏览器响应时才需要的,那么你的购物车是如何确定这些东西都是你的,而不是别人的呢?
    由于之前学习的request和response对象都无法解决这一问题,所以就诞生了cookie会话技术。Cookie会话技术允许浏览器端在一次会话中可以发起
    多次请求,只要会话不断开,多少次都行。当你登入到系统的时候,建立cookie,你所发起的每次请求都会带上这个特定的cookie,所以也就保证了你所
    添加的物品都是你的,而不是别人的。
    
  3. 作用:通过设置Cookie来区分不同的用户。解析:当我们第一次去会员制奶茶店时,奶茶店会给我们一张会员卡,上面有会员编号并记录有本次的积分,当我们以后再去该奶茶店的时候,只需要拿着这张会员卡就能进行积分,并且不会将自己的积分积到别人的会员卡上。这里,会员卡就是我们的Cookie,可以有效的区别每一位会员用户,即Cookie可以有效的区别每一个用户。

  4. 原理:当浏览器发起请求调用了创建Cookie的Servlet时,服务器会响应给浏览器该cookie对象,在本次会话中,不管浏览器发出多少次请求,在请求报文中都有该cookie信息,除非cookie失效了。
    在这里插入图片描述

  5. 特点:

    1. cookie信息存储于客户端浏览器中,既可以持久化存储也可以暂时存在内存中。
    2. 浏览器对于单个cookie 的大小有限制(4KB),并且对同一个域名下的总cookie数量也有限制(20个)。
  6. 应用场景:

    1. 用于客户端用户免登录,即在不登录的情况下,完成对客户端身份的识别。
    2. 用于存储少量且不重要的数据信息。

三、Cookie 使用

  1. 一次会话中发送多个Cookie信息:

    /**
    * 只需要在设置Cookie时多创建几个Cookie对象,并且加入到Cookie中去即可
    */
    Cookie c1 = new Cookie("msg", "hello");
    Cookie c2 = new Cookie("name", "张三 ");
    response.addCookie(c1);
    response.addCookie(c2);
    

    注意:如果当创建Cookie对象的时候,发送键相同值不相同的情况,那么就会覆盖之前的value。

    如果在上面代码中添加Cookie c3 = new Cookie("name", "李四");代码,那么"李四"就会把"张三"给覆盖。

  2. 设置Cookie的存活时间:默认情况下,当浏览器关闭后,Cookie数据就会被销毁

    /**
    * 方法:setMaxAge(int seconds)
    * 	1. 正数:将Cookie数据写到硬盘的文件中,进行持久化存储,并指定cookie在硬盘中的保留时间,时间到了后,cookie文件就会自动失效
    *   2. 负数:将cookie有效时间设置为负数,其作用和默认值一样,关闭浏览器,cookie就会失效
    *   3. 零:删除cookie的信息
    */
    Cookie c = new Cookie("msg", "hello");
    response.addCookie(c); 
    

    注意:当设置了Cookie存活时间后,Cookie对象就会存储于客户端磁盘中,到时间才会自动消除。

  3. Cookie的共享问题:

    1. 同一个Tomcat下不同项目之间的cookie共享:

      一般情况下,不同的项目之间是不能进行cookie共享的。但是我们都知道,tomcat的虚拟目录可以为"/",表示可以访问任意的该tomcat下的所有项目,因此,我们可以将cookie的路径设置为"/",这样就提升了该cookie的范围,就允许该tomcat下所有的web应用都可以共享该cookie。

      setPath(String path) // 设置cookie的获取范围。默认情况下,设置当前的虚拟目录,如果要共享,则可以将path设置为"/"
      
    2. 同一个项目不同的Tomcat之间的cookie共享:

      如果将一个项目分为几部分部署于不同的服务器,那么其域名都会不同,但都有一个共同的一级域名,你可以通过一级域名找到该web项目。所以,我们可以通过给cookie设置一级域名,就能够保证cookie在不同的服务器之间共享。例如,百度一级域名为baidu.com,而二级域名包括news.baidu.com、tieba.baidu.com,想要新闻网和贴吧网可以共享cookie,就需要将cookie的一级域名设置为c.setDomain("baidu.com");即可。

      setDomain(String path) // 如果设置一级域名相同,那么多个服务器之间cookie可以共享
      

四、Cookie 免登录案例

  1. 需求分析:
用户进行登录操作,如果账号或密码错误,在request域中存储一个错误信息,跳转至登录页面,在页面中显示错误信息。
如果登录成功,需要添加一个userid的cookie,时效为一个星期,然后跳转至个人信息servlet。
在个人信息servlet中,需要对userid的cookie进行校验,如果从数据库中有该对象id,则显示该用户信息,否则跳转至登录页面。

这里采用Druid连接池和JdbcTemplate来完成对数据库的操作。页面通过JSP来展示。
所需要的jar包:
commons-logging-1.2.jar
druid-1.0.9.jar
mysql-connector-java-8.0.16.jar
spring-beans-5.0.0.RELEASE.jar
spring-core-5.0.0.RELEASE.jar
spring-jdbc-5.0.0.RELEASE.jar
spring-tx-5.0.0.RELEASE.jar
  1. 目录结构:
    在这里插入图片描述

  2. 数据库用户表的设计:
    在这里插入图片描述

  3. JSP页面:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>用户登录</title>
    </head>
    <body>
        <!-- 获取错误提示信息 -->
        <%
            String error = (String) request.getAttribute("error");
            if (error == null || error.equals("")) {
                error = "";
            }
        %>
        <form action="/cookie_war_exploded/login" method="post">
            <label>账号:</label>
            <input type="text" name="username" /><br>
            <label>密码:</label>
            <input type="password" name="password" /><br>
            <span><%= error %></span>
            <input type="submit" value="点击登录">
        </form>
    </body>
    </html>
    
    
  4. DAO层:

    public interface LoginDao {
    
        public User login(String username, String password);
    
        public User userInfo(String id);
    
    }
    
    public class LoginDaoImpl implements LoginDao {
    
        private JdbcTemplate jdbcTemplate = new JdbcTemplate(JdbcUtils.getDataSource());
    
        @Override
        public User login(String username, String password) {
            String sql = "select * from user" +
                    " where username = ? and password = ?";
            try {
                User user = jdbcTemplate.queryForObject(sql,
                        new BeanPropertyRowMapper<User>(User.class),
                        username, password);
                return user;
            } catch (Exception e) {
                return null;
            }
        }
    
        @Override
        public User userInfo(String id) {
            String sql = "select * from user where id = ?";
            try {
                User user = jdbcTemplate.queryForObject(sql,
                        new BeanPropertyRowMapper<User>(User.class), id);
                return user;
            } catch (Exception e) {
                return null;
            }
    
        }
    }
    
  5. Servlet:

    /**
    * 用户登录Servlet
    */
    @WebServlet(value = "/login")
    public class LoginServlet extends HttpServlet {
    
       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp)
               throws ServletException, IOException {
    
           req.setCharacterEncoding("UTF-8");
           resp.setContentType("text/html;charset=utf-8");
           LoginDao loginDao = new LoginDaoImpl();
           String username = req.getParameter("username");
           String password = req.getParameter("password");
           User user = loginDao.login(username, password);
           if (user == null ) {
               // 登录失败
               req.setAttribute("error", "账号或密码不正确!");
               req.getRequestDispatcher("/login.jsp").forward(req, resp);
           }
           // 登录成功
           Cookie cookie = new Cookie("userid", String.valueOf(user.getId()));
           cookie.setMaxAge(60 * 60 * 24 * 7); // cookie保存一个星期
           resp.addCookie(cookie);
           // 转发到主页面
           resp.sendRedirect("/cookie_war_exploded/userInfoServlet");
       }
    
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp)
               throws ServletException, IOException {
           this.doPost(req, resp);
       }
    }
    
    /**
    * 用户信息展示servlet
    */
    @WebServlet(value = "/userInfoServlet")
    public class UserInfoServlet extends HttpServlet {
    
       private LoginDao loginDao = new LoginDaoImpl();
    
       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp)
               throws ServletException, IOException {
           Cookie[] cookies = req.getCookies();
           boolean isUserId = false;
           String userId = "";
           for (Cookie cookie : cookies) {
               if (cookie.getName().equals("userid")) {
                   userId = cookie.getValue();
                   isUserId = true;
                   break;
               }
           }
           if (isUserId) {
               User user = loginDao.userInfo(userId);
               if ( user != null ) {
                   resp.setContentType("text/html;charset=utf-8");
                   resp.getWriter().write(user.toString());
               }
           } else {
               // 没有userId
               req.getRequestDispatcher("/login.jsp").forward(req, resp);
           }
    
       }
    
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp)
               throws ServletException, IOException {
           this.doPost(req, resp);
       }
    }
    
    
    
发布了22 篇原创文章 · 获赞 0 · 访问量 341

猜你喜欢

转载自blog.csdn.net/Yi__Ying/article/details/104665861