Session和Cookie

Session和Cookie

1. 会话技术

  1. 会话:一次会话中包含多个请求和响应;从浏览器给服务器发送请求开始,直到某一方断开连接为止
  2. 功能:在一次会话中的多次请求之间共享数据
  3. 方式:
    1. 客户端会话技术:Cookie
    2. 服务端会话技术:Session
  1. 功能:将数据保存在客户端

  2. 入门:

    1. 创建Cookie对象,绑定数据

      new Cookie(String name, String value)

      Cookie cookie=new Cookie("msg","helloworld");
      
    2. 发送Cookie对象

      response.addCookie(Cookie cookie)

      response.addCookie(cookie);
      
    3. 获取Cookie,拿到绑定的数据

      request.getCookies()

      Cookie[] cookies = request.getCookies();
      if (cookies!=null){
          for (Cookie cookie : cookies) {
              String cookieName = cookie.getName();
              String cookieValue = cookie.getValue();
              System.out.println(cookieName+""+cookieValue);
          }
      }
      
  3. 流程分析

    1. 第一次请求时服务器给响应头set-cookie: key-value
    2. 第二次请求时请求头带有cookies
  4. 细节处理

    1. 一次发送多个cookie:需要多少个就add多少个

    2. cookie在浏览器保存多久:

      1. 默认浏览器关闭后被销毁

      2. 持久化:

        setMaxAge(int seconds)

        seconds>0 表示持久化,写到文件中;同时表示cookie的保存时间(秒)

        seconds<0 表示默认值

        seconds=0 表示删除cookie

    3. cookie能否存放中文字符:

      tomcat8前不支持,特殊字符和中文也需要将中文URL编码

    4. cookie获取范围:

      1. 多个webapp能否共享?

        默认不能共享;如果需要则要设置path为根路径cookie.setPath("/")

      2. 不同tomcat服务器的cookie能共享吗?

        cookie.setDomain(String domain)设置一级域名相同,则可以共享

    5. cookie特点

      1. 数据存储在客户机
      2. 浏览器对于单个cookie大小有限制(max 4kb)以及同一域名下cookie个数有限制(20)
      3. 一般用于不登录身份鉴别
  5. Cookie案例

    1. 需求:访问Servlet,第一次访问提示:你好,欢迎使用

      ​ 以后访问显示上一次访问时间

    2. 分析:

      访问时判断是否有Cookie数据,没有就是第一次,提示你好欢迎使用,写入Cookie数据;有就取出Cookie数据,并更新当前的访问时间

3. JSP

  1. 概念:Java Server Pages:java服务器端页面,用于简化书写

  2. JSP的原理:本质就是Servlet

  3. JSP脚本:JSP定义Java代码的方式

    1. <% java code %>:定义的Java代码在service方法中,可以定义
    2. <%! java code %>:定义成员变量和成员方法
    3. <%= java code%>:定义Java代码,输出语句中可以使用
  4. JSP的九大内置对象:不需要获取和创建,可以直接使用的对象

    1. request

    2. response

    3. out:

      和writer有细微区别,writer永远会比out先输出,与缓冲区有关

4. Session

  1. 概念:在一次会话的多次请求间共享数据

  2. 入门:

    1. 获取session:HttpSession session = request.getSession()

    2. 使用session对象:

      Object getAttribute(String name)

      void setAttribute(String name, Object value)

      void removeAttribute(String name)

  3. 原理:session依赖于cookie,会有jsessionid来区分

  4. 细节:

    session什么时候被销毁:服务器关闭;session.invalidate();默认失效时间是30分钟

    session钝化:连接关闭之前,将session对象序列化到硬盘session.ser

    session活化:连接启动前,将硬盘中的数据给序列化

  5. 特点:

    1. Session用于存储一次会话的多次请求的数据
    2. 可以存储任意类型,任意大小的数据,存储在服务器端
  6. 案例:

    1. 需求:

      访问登录页面,输入username, userpwd, verifycode;如果用户名或密码错误就提示用户名或密码错误,验证码错误提示验证码错误;输入正确就直接跳转到success.jsp显示xxx,欢迎使用

    2. 代码:

      其中的验证码生成代码来自:https://www.cnblogs.com/Alice-Thinker/p/8400318.html

      效果图:
      效果图

      <%--
          login.jsp
      --%>
      <%@ page contentType="text/html;charset=UTF-8" %>
      <html>
      <head>
          <script>
              window.onload=function () {
                  document.getElementById("verifycode").onclick=function () {
                      this.src="/verifyCode?"+new Date().getTime();
                  }
              }
          </script>
          <title>用户登录</title>
      </head>
      <body>
      <form action="/login" method="post">
          <table>
              <tr>
                  <td>用户名</td>
                  <td><input type="text" name="username" ></td>
              </tr>
              <tr>
                  <td>密码</td>
                  <td><input type="password" name="userpwd" ></td>
              </tr>
              <tr>
                  <td>验证码</td>
                  <td><input type="text" name="verifyCode" placeholder="请输入验证码"></td>
              </tr>
              <tr>
                  <td colspan="2"><img src="/verifyCode" alt="verifyCode" id="verifycode"></td>
              </tr>
              <tr>
                  <td colspan="2"><input type="submit" value="登录"></td>
              </tr>
          </table>
          <div style="color: red;"><%=request.getAttribute("error0")==null?"":request.getAttribute("error0")%></div>
          <div style="color: red;"><%=request.getAttribute("error1")==null?"":request.getAttribute("error0")%></div>
      </form>
      </body>
      </html>
      
      <%--
       success.jsp
      --%>
      <%@ page contentType="text/html;charset=UTF-8" %>
      <html>
      <head>
          <title>欢迎使用</title>
      </head>
      <body>
          <h3><%=request.getSession().getAttribute("user")%> 欢迎使用本系统!</h3>
      </body>
      </html>
      
      //verifyCode.java
      import javax.imageio.ImageIO;
      import java.awt.*;
      import java.awt.image.BufferedImage;
      import java.util.Random;
      
      @javax.servlet.annotation.WebServlet(name = "verifyCode", urlPatterns = "/verifyCode")
      public class verifyCode extends javax.servlet.http.HttpServlet {
          private static final int WIDTH = 100;//设置验证码图片宽度
          private static final int HEIGHT = 30;//设置验证码图片高度
          private static final int LENGTH = 4;//设置验证码长度
          public static final int LINECOUNT = 20;//干扰线的数目
      
          //验证码的字符库
          private static final String str = "0123456789" +
                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                  "abcdefghijklmnopqrstuvwxyz";
      
          //通过随机数取字符库中的字符组合成4位验证码
          private static Random random = new Random();
      
          protected void doPost(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException {
              req.setCharacterEncoding("utf-8");
              resp.setContentType("image/jpeg");
      
              //设置不进行缓存
              resp.setHeader("pragma", "no-cache");
              resp.setHeader("cache-control", "no-cache");
              resp.setHeader("expires", "0");
              BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_3BYTE_BGR);
              Graphics g = image.getGraphics();
      
              //设置背景颜色并绘制矩形背景
              g.setColor(Color.WHITE);
              g.fillRect(0, 0, WIDTH, HEIGHT);
      
              //验证码的绘制
              String code = drawChar(g);
              System.out.println("验证码:" + code);
              //随机线的绘制
              for (int i = 0; i < LINECOUNT; i++) {
                  drawLine(g);
              }
      
              //在session中存入当前的code码,便于验证
              req.getSession().setAttribute("code", code);
      
              //绘制图片
              g.dispose();
      
              //将图片输出到response中
              ImageIO.write(image, "JPEG", resp.getOutputStream());
          }
      
          public Color getColor() {
              return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
          }
      
          //获取字体样式
          public Font getFont() {
              return new Font("Fixedsys", Font.CENTER_BASELINE, 20);
          }
      
          //绘制字符
          public String drawChar(Graphics g) {
              String code = "";
              g.setFont(getFont());
              for (int i = 0; i < LENGTH; i++) {
                  char c = str.charAt(random.nextInt(str.length()));
                  g.setColor(getColor());
                  g.drawString(c + "", 20 * i + 10, 20);
                  code = code + c;
              }
              return code;
          }
      
          //绘制随机线
          public void drawLine(Graphics g) {
              int x = random.nextInt(WIDTH);
              int y = random.nextInt(HEIGHT);
              int xl = random.nextInt(13);
              int yl = random.nextInt(15);
              g.setColor(getColor());
              g.drawLine(x, y, x + xl, y + yl);
          }
      
          protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
              request.setCharacterEncoding("utf-8");
              this.doPost(request, response);
          }
      }
      
      //login.java
      import javax.servlet.http.HttpSession;
      
      @javax.servlet.annotation.WebServlet(name = "login", urlPatterns = "/login")
      public class login extends javax.servlet.http.HttpServlet {
          protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
              request.setCharacterEncoding("utf-8");
              response.setContentType("text/html;charset=utf-8");
              String username = request.getParameter("username");
              String userpwd = request.getParameter("userpwd");
              String verifyCode = request.getParameter("verifyCode");
              HttpSession session=request.getSession();
              String realVerifyCode = (String) session.getAttribute("code");
              if(realVerifyCode.equalsIgnoreCase(verifyCode)){
                  if ("username".equals(username)&&"userpwd".equals(userpwd)){
                      session.setAttribute("user",username);
                      response.sendRedirect(request.getContextPath()+"/success.jsp");
                  }
                  else {
                      request.setAttribute("error1","用户名或密码输入错误!");
                      request.getRequestDispatcher("/login.jsp").forward(request,response);
                  }
              }
              else {
                  request.setAttribute("error0","验证码输入错误,请重新输入!");
                  request.getRequestDispatcher("/login.jsp").forward(request,response);
              }
          }
      
          protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
              request.setCharacterEncoding("utf-8");
              this.doPost(request, response);
          }
      }
      
posted @ 2020-04-23 00:49  codesucks  阅读(174)  评论(0)    收藏  举报