Java Web学习笔记四

一、会话

1.会话概述:

用户第一次打开浏览器去访问服务器,就是会话的开始;

用户发送请求给服务器,服务器返回响应给浏览器渲染表现,就是会话的过程;

用户关闭浏览器,才是会话的结束,只要没有关闭浏览器,期间的每次访问都属于同义词会话;

2.会话技术:

2.1 会话技术的作用:

由于Http协议时无状态的协议,所以会话技术就是用来保存用户产生的数据,方便判断用户是谁,做了什么;

2.2 两种会话技术:

  1. cookie:

    客户端会话技术:会话数据保存到浏览器端

  2. session:

    服务器会话技术:会话数据存储到服务器端

二、Cookie

1.Cookie使用场景

因为cookie是存储在浏览器端的数据,由服务器返回给浏览器,浏览器接受并保存到电脑的某个位置,下次打开这个网页的时候,自动读取存储的数据,并在需要的时候发送给服务器端;

eg:

浏览器某些网页的时候的自动登录功能;

Cookie其实就是存储在客户机上的一个文件,方便下次使用的时候免于再次录入信息;

Cookie保存服务器返回的数据;

2.代码实现返回Cookie给浏览器

@WebServlet(name = "CookieServlet")
public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置返回编码和数据类型
        response.setContentType("text/html;charset=utf-8");
        //2.获得输出流
        PrintWriter out = response.getWriter();
        out.print("存储cookie");
        //3.创建cookie信息
        Cookie cookie = new Cookie("user", "admin");
        //4.返回cookie给浏览器,浏览器获得数据后,自动保存
        response.addCookie(cookie);
    }
}

3.Cookie运行原理

在这里插入图片描述

  1. 浏览器第一次访问服务器没有cookie数据
  2. 服务器创建cookie对象,封装之后以响应头的形式,返回给浏览器
  3. 浏览器接受到cookie之后,将它保存到本地
  4. 浏览器再次访问的时候,浏览器发送cookie以请求头的形式给服务器
  5. 服务器读取浏览器发送的cookie数据

4.Cookie过期时间设置

cookie的默认过期时间:浏览器关闭即消失失效;

@WebServlet(name = "CookieServlet")
public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置返回编码和数据类型
        response.setContentType("text/html;charset=utf-8");
        //2.获得输出流
        ServletOutputStream out = response.getOutputStream();
        out.print("存储cookie");
        //3.创建cookie信息
        Cookie cookie = new Cookie("user", "admin");
        //设置cookie过期时间;单位:秒;
        //如果数值为负,则自动设置为默认值,负数无效;设置为0,删除cookie
        cookie.setMaxAge(600);
        //4.返回cookie给浏览器,浏览器获得数据后,自动保存
        response.addCookie(cookie);
    }
}

由于功能需要,所以在某些情况下需要删除Cookie

实现方式:

  1. 创建一个同名的cookie,有效路径也要一直,但是value无所谓
  2. 设置过期时间为0
  3. 返回给浏览器端;

代码实现:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        ServletOutputStream out = response.getOutputStream();
        out.print("删除cookie");
        Cookie cookie = new Cookie("user", "admin");
        cookie.setMaxAge(0);
        cookie.setPath(request.getContextPath()+"");
        response.addCookie(cookie);
    }

5.代码读取cookie

   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置返回数据编码和类型,避免乱码
       response.setContentType("text/html;charset=utf-8");
       //获得cookie
       Cookie[] cookies = request.getCookies();
       if(cookies !=null){
            //获得字节输出流
       	ServletOutputStream out = response.getOutputStream();
       	//循环输出cookie到浏览器显示
       	for (Cookie cookie : cookies) {
           	out.print(cookie.getName()+"\t"+cookie.getValue()+"\t");
       	}
       }
       
   }

6.设置Cookie有效路径

为什么要设置?

因为保存在浏览器的数据,在浏览器访问服务器其他所有页面的时候,默认都会携带cookie;

这样就会造成数据量变大,设置有效路径之后,可以减少数据量的传输;

@WebServlet(name = "CookieServlet")
public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置返回编码和数据类型
        response.setContentType("text/html;charset=utf-8");
        //2.获得输出流
        ServletOutputStream out = response.getOutputStream();
        out.print("存储cookie");
        //3.创建cookie信息
        Cookie cookie = new Cookie("user", "admin");
        //设置cookie过期时间
        cookie.setMaxAge(60 * 60 * 24 * 7);
        //设置cookie有效路径或,访问路径
        //设置要以项目名为第一个访问路径开头,然后再设置要访问的html或网页
        // “/项目名/要网文的网页、jsp、servlet”
        //或者可以用代码来实现: request.getContextPath()
        cookie.setPath("/WebApp/login");
        //4.返回cookie给浏览器,浏览器获得数据后,自动保存
        response.addCookie(cookie);
    }
}

问题:如果访问路径是 setPath("/day-cookie"),以下路径哪些可以正常访问?

访问地址能否访问到 Cookie
http://localhost:8080/day-cookie/
http://localhost:8080/day-cookie/aa/bb
http://localhost:8080/day/不能
http://localhost:8080/不能

注意:设置有效路径之后,设置路径的子路径也可以访问,但是其他路径无法访问

7.Cookie使用非法字符:

由于在设置cookie时,无法使用使用特殊字符,但是难免会用到这些非法字符,所以要做相应的设置来使用非法字符,并使之有效;

那么就需要先对包含非法字符的字符串进行url编码,将编码后的结果作为value返回给浏览器;

当浏览器发送这个数据给服务器的时候,要再进行url解码,才能还原数据;

//假设这里有可能会出现非法字符,那么接下来就进行处理
//把username加密之后再传输
username = URLEncoder.encode(username, "utf8");
//读取时候也要进行相应的解码
//获取Cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
	//找到保存相应信息的cookie
	if (cookie.getName().equals("username")){
		//把内容解码
		String encode = URLEncoder.encode(cookie.getValue(), "utf8");
	}
}

8.拓展:实现自动登录功能:

  1. 如果要实现自动登录,那么就要记录好用户输入的用户名和密码
  2. 然后再特定页面把信息填入应该填入的地方
  3. 自动点击提交登录,等待登录成功

而自动登录的实现主要是需要获得本地存储的信息,所以需要使用cookie来实现!

Servlet代码:

@WebServlet(urlPatterns = "/AutoServlet")
public class AutoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.转换编码格式,防止乱码
        request.setCharacterEncoding("utf8");
        response.setContentType("text/html;charset=utf-8");
        //2.获得用户登录信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String remember = request.getParameter("remember");
        //3.判断用户登录是否成功
        if ("admin".equals(username) && "123".equals(password)) {
            //4.登录成功,判断是否需要存储cookie信息,下次免登录
            if (remember != null) {
                //6.保存用户信息到cookie并返回给浏览器保存
                Cookie uCookie = new Cookie("username", username);
                Cookie pCookie = new Cookie("password", password);
                response.addCookie(uCookie);
                response.addCookie(pCookie);
            }
            //7.跳转到登录成功后看到的页面
            response.sendRedirect("index.jsp");
        } else {
            //5.登录失败,返回页面
            response.sendRedirect("login.html");
        }
    }
}

前端页面代码:

<h2>用户登录</h2>
<form action="login" method="post" id="loginForm">
    <table>
        <tr>
            <td width="60">用户名</td>
            <td><input type="text" name="username" id="username"/></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="password" id="password"/></td>
        </tr>
        <tr>
            <td>记住我</td>
            <!--没有value属性的前提下,点中它的值是on-->
            <td><input type="checkbox" name="remember"/></td>
        </tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" value="登录"/></td>
        </tr>
    </table>
</form>

JS代码:(用来实现自动点击登录按钮)

   /**
     * 页面加载完成,读取cookie的信息
     * 如果有username和password
     * 则将用户名和密码发送给服务器,实现自动登录
     * 如果没有,则显示登录页面
     */
    window.onload = function () {
        // 读取Cookie信息
        var cookies = document.cookie;
        // 如果cookie不为空
        if (cookies) {
            // 得到用户名和密码
            var username = getCookie("username"); // jack
            var password = getCookie("password"); // 123

            // 设置文本框的值
            document.getElementById("username").value = username;
            document.getElementById("password").value = password;

            // 提交表单
            document.getElementById("loginForm").submit();
        }
    };

    /*
     * 得到指定cookie的值
     */
    function getCookie(cname) {
        var ca = document.cookie.split(';'); // [username=admin;password=123]
        for(var i = 0; i < ca.length; i++) {
            var c = ca[i]; // "password=123"
            var arr = c.split("="); // ["password",123]
            if (arr[0].trim() == cname){ // password
                return arr[1];
            }
        }
        return "";
    }

三、Session

1.Session应用场景

在这里插入图片描述

数据存储在服务器端,一般用于对比用户传入的信息;

eg:验证码的实现;

Session也是servlet三大作用域中的会话域;

Session是什么?

因为是Servlet中的会话域,所以也是服务器中的一小块内存,每个会话域都有自己的内存区域,不同的会话之间不能共享数据,底层是map结构;

session的作用就是用于同一次会话时,把数据存储在Session中共享;

2.session运行原理:

在这里插入图片描述

  1. 服务器第一次调用请求对象的getSession()方法时,创建一个内存区域分配给这个session,并且指定一个唯一的会话id;
  2. 浏览器第一次访问没有会话id
  3. 服务器有了session之后,会将会话id以cookie的形式返回给浏览器,浏览器把数据保存到本地
  4. 浏览器再次访问服务器的时候,就会把会话id以请求头的方式发送到服务器;
  5. 服务器根据会话id找到session分配好的内存,对其中的数据增删查改;

3.Session常用方法:

HttpSession接口方法作用
String getId()获得会话ID
long getCreationTime()获得会话创建时间:毫秒值
long getLastAccessedTime()获得上一次访问会话域的时间:毫秒值
boolean isNew()判断是否是新的会话
ServletContext getServletContext()获得上下文对象

4.Session常见问题:

  1. 浏览器关闭,还能不能得到之前会话域中的信息?

    不能获得会话域中的数据,因为会话域中的id,默认在会话结束(浏览器关闭)之后就会销毁;

  2. 如果浏览器关闭,服务器上的会话信息是否还存在?

    还存在,服务器会话域中的数据过期时间默认是30分钟;(含义是:在30分钟之内,没有操作才会自动销毁,但是如果你再次访问,则会再次刷新)

  3. 如果让浏览器关闭之后还可以访问服务器上没有消失的信息?

    自己保存会话id,设置过期时间;

5.保存会话ID

@WebServlet(urlPatterns = "/SessionServlet")
public class SessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取session对象
        HttpSession session = request.getSession();
        //2.获取会话id
        String sessionId = session.getId();
        //3.新建cookie保存会话id
        //注意,这里要设置成服务器可以自动读取的id,不然无法是西安
        Cookie cookie = new Cookie("JSESSIONID", sessionId);
        //4.把设置好的cookie返回给浏览器
        response.addCookie(cookie);
    }
}

保存会话id其实没有什么难度,只需要把该注意的注意到了即可

6.设置会话过期时间

设置会话的过期时间,其实某种程度上来说是为了避免有些用户不小心关闭浏览器,导致信息丢失;

设置合理的会话过期时间,一方面可以提高用户体验,另一方面可以管理服务器;

6.1 通过代码:

session.setMaxInactiveInterval(60 * 60 * 30);

6.2 配置xml文件:

 <!--设置会话过期时间,单位分钟-->
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>

6.3 调用销毁方法:

session.invalidate();

四、Cookie、Session的比较和选择

1.如何选择Cookie和Session

如果数据类型比较大,或者包含隐私数据,选择session,否则的话可以选择cookie

2.对比图表

技术类型数据存储位置键值对的数据类型
Cookie浏览器端会话技术保存在客户端的一个文件中键和值都是String类型
Session服务器端的会话技术保存服务器的内存中键是String类型
值是Object类型

五、Servlet三个作用域的比较和总结

1.作用域的创建和销毁

作用域接口名作用范围生命周期
请求域HttpServletRequest同一个请求有效请求开始到请求结束
会话域HttpSession同一个会话有效会话开始到会话结束
上下文域ServletContext同一应用有效服务器启动到服务器关闭

2.作用域共同的方法

功能方法名
存放数据setAttribute
获取数据getAttribute
删除数据removeAttribute

3.如何选择作用域

  • 如果小范围的作用域能够满足需要就使用小范围的作用域
  • 请求域 < 会话域 < 上下文域
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值