Servlet笔记 —— 会话技术(Session和Cookie)

会话技术

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

    • 一次会话:浏览器第一次给服务器发送请求,会话建立,直到有一方断开为止
  2. 功能:

    • 在一次会话范围内,共享数据。

      由于Http是无状态的,每次请求之间是相互独立的。若要在多次请求之间,进行数据共享,就只能使用会话技术

  3. 实现方式:

    1. 客户端会话技术:Cookie(将数据存在客户端)
    2. 服务端会话技术:Session(将数据存在服务端)

Cookie

使用步骤
  1. 服务端创建Cookie,绑定数据

    Cookie cookie = new Cookie("name","yogurt");
    
  2. 发送Cookie对象

    response.addCookie(cookie);
    
  3. 客户端获取Cookie,拿到数据

    Cookie[] cookies = request.getCookies();
    
实现原理

服务端往客户端发送Cookie时,会在response的响应头上设置

扫描二维码关注公众号,回复: 12315703 查看本文章

set-cookie:name=yogurt

浏览器看到这个响应头时,会把这个数据保存在浏览器端

第二次请求时,会把这个cookie放在请求头上

cookie:name=yogurt

这是Http协议和浏览器自动做的

Cookie的细节
  • 一次是否能发送多个Cookie?

    可以发送多个Cookie,使用response调用多次addCookie方法即可,多个cookie在response的响应头时设置多个字符串键值对,以逗号隔开

  • Cookie在浏览器中保存多长时间?

    • 默认情况下,在浏览器关闭时,Cookie数据被清除

    • 可以设置cookie生命周期,让其持久化存储

      setMaxAge(int seconds)

      1. 参数为正数:将cookie写到硬盘文件中,参数为cookie存货时间
      2. 参数为负数:默认值
      3. 参数为零:表示删除cookie
  • Cookie能不能存中文?

    1. tomcat 8之前,cookie不能存储中文

      -> 解决方案:将中文数据转码 , 一般采用URL编码

    2. tomcat 8以后,cookie能存储中文,但对特殊字符还是不支持,比如空格,建议使用URL编码存储,读取时用URL解码。(空格经过URL编码后会变成+)

Cookie的共享问题?
  1. 假设在同一个tomcat服务器中,部署了多个web项目,那么这些web项目中的cookie能不能共享?

    • 默认情况下,多个web项目之间的cookie不能共享

    • setPath(String path) ,默认情况下,会调用该方法,设置当前项目的虚拟目录

    • 如果要共享,可以将path设置为/

          Cookie cookie = new Cookie("n","c");
          cookie.setPath("/");```
    
    
  2. 那么在不同tomcat服务器之间的cookie,如何共享?

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

    2. 比如setDomain(".baidu.com"),那么tieba.baidu.comnews.baidu.com之间也能共享cookie

Cookie的特点和作用
  1. 特点
    1. cookie存储在浏览器端(容易被篡改,不怎么安全)
    2. 浏览器对单个cookie的大小有限制(一般是4kb),对同一个域名下的cookie总数量也有限制(一般是20个以内)
  2. 作用
    1. cookie一般用来存储少量的,不太敏感的数据
    2. 在不登陆的情况下,完成服务器对客户端的身份识别
Cookie使用案例:记录上一次的登录时间
  1. 访问一个Servlet,若是第一次访问,则输出,欢迎访问
  2. 若不是第一次访问,则显示,你好,欢迎回来,你上次登录的时间是:${上次访问时间}
  3. 代码实现
@WebServlet("/loginDemo")
public class ShowLastTimeServlet extends HttpServlet {
    
    

	private static final String lastTimeLogin = "lastTimeLogin";

	private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		response.setContentType("text/html;charset=utf-8;");
		Cookie[] cookies = request.getCookies();
		PrintWriter writer = response.getWriter();
		boolean firstLogin = true;
		String lastLoginTimeStr = "";
		if (cookies == null || cookies.length == 0){
    
    
			firstLogin = true;
		}else {
    
    
			for (Cookie cookie : cookies){
    
    
				String cookieName = cookie.getName();
				String cookieValue = cookie.getValue();
				cookieValue = URLDecoder.decode(cookieValue,"utf-8");
				if (lastTimeLogin.equals(cookieName)){
    
    
					lastLoginTimeStr = cookieValue;
					firstLogin = false;
					break;
				}
			}
		}
		String nowStr = timeFormatter.format(LocalDateTime.now());
		/** 对空格进行特殊处理,使用URL编解码 **/
		nowStr = URLEncoder.encode(nowStr,"utf-8");
		Cookie newCookie = new Cookie(lastTimeLogin,nowStr);
		newCookie.setMaxAge(60 * 60 * 24 * 30);
		response.addCookie(newCookie);
		if (firstLogin){
    
    
			writer.write("<h1>你好,欢迎访问!</h1>");
		}else {
    
    
			writer.write("<h1>你好,欢迎回来!你上次的登陆时间是:"+ lastLoginTimeStr +"</h1>");
		}

	}
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		doPost(request, response);
	}
}

Session

原理

session是依赖于cookie的。可以通过request.getSession()来获取session,若是第一次,则会创建一个session。第一次响应时,会通过在响应头上添加set-cookie:JSESSIONID=xxxx。随后在浏览器发起的请求,会带上这个cookie,表现为在请求头上添加cookie:JSESSIONID=xxxx,然后服务器根据这个id,找到自己内存中的session对象。

细节
  1. 客户端关闭,服务器不关闭,两次获取的session是否为同一个?

    => 默认情况下,不是同一个。若希望是同一个,则可以手动创建一个cookie,其name为JSESSIONID,并用setMaxAge()方法设置其存活时间

  2. 客户端不关闭,服务器关闭,两次获取到的session是否为同一个?

    => 肯定不是同一个,但在有些场景下需要确保数据不丢失。Tomcat自带有session的钝化和活化策略。

    钝化:在服务器关闭之前,将session序列化,存储到服务器的磁盘中(tomcat的work工作目录下)

    活化:在服务器启动时,从磁盘中反序列化session文件,创建session对象,加载到内存中

    session的钝化和活化是Tomcat默认支持的。需要在Tomcat中启动,才有效。如果在IDEA中启动项目,则只会钝化session,但重启后因为会删除work工作目录,故无法活化session

  3. session失效时长?

    Session在服务器关闭会被销毁;

    调用Session的invalidate也会销毁;

    session默认的失效时长是30分钟。

    Tomcat的web.xml中有对session的配置:<session-config>

特点
  1. 用于存储一次会话,多次请求的数据,存在服务端
  2. session可以存任意类型,任意大小
Session使用案例:校验验证码
  1. 调用servlet生成验证码时,将生成的验证码设置到session中
  2. 用户点击登录后,接收到第二次请求,将其所输入的验证码和session中的做比对,正确则验证通过
  3. 代码实现
    html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>带验证码的登陆案例</title>

    <script>
        window.onload = function () {
     
     
            var img = document.getElementById("checkImage");
            img.onclick = function () {
     
     
                var date = new Date().getTime();
                img.src = "/checkImage?" + date;
            }
        }
    </script>
</head>
<body>

    <form action="/login" method="post">
        <table>
            <tr>
                <td>用户名</td>
                <td><input type="text" placeholder="username" name="username"/></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><input type="password" placeholder="password" name="password" /></td>
            </tr>
            <tr>
                <td>验证码</td>
                <td><input type="text" placeholder="请输入验证码" name="checkCode" /></td>
            </tr>
            <tr>
                <td colspan="2"><img src="/checkImage" id="checkImage" /></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="提交" /></td>
            </tr>
        </table>
    </form>
</body>
</html>

Servlet代码

@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    
    
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		// 先判断验证码是否正确
		// 再验证用户名和密码
		String checkCode = request.getParameter("checkCode");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		response.setContentType("text/html;charset=utf-8;");

		String rightCheckCode = (String)request.getSession().getAttribute("checkCode");
		String errorMsg = "";
		if (checkCode != null && checkCode.equals(rightCheckCode)){
    
    
			if ("yogurt".equals(username) && "123456".equals(password)){
    
    
				request.getSession().setAttribute("username","yogurt");
				response.sendRedirect("/success.jsp");
			}else {
    
    
				errorMsg = "用户名和密码不正确";
			}
		}else {
    
    
			errorMsg = "验证码不正确";
		}

		if (!"".equals(errorMsg)){
    
    
			request.getSession().setAttribute("errorMsg",errorMsg);
			response.sendRedirect("/failure.jsp");
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		doPost(request, response);
	}
}

生成验证码的Servlet

@WebServlet("/checkImage")
public class ImageServlet extends HttpServlet {
    
    
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		doGet(request,response);
	}
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
		//1 生成一张图
		int width = 100;
		int height = 50;
		BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		//2 美化图
		Graphics g = image.getGraphics();
		//2.1 填充背景色
		g.setColor(Color.PINK);
		g.fillRect(0,0,width,height);
		//2.2 画边框
		g.setColor(Color.BLUE);
		g.drawRect(0,0, width - 1,height - 1);
		//2.3 写验证码
		String str = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890";
		Random random = new Random();
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 1; i <= 4 ; i++) {
    
    
			int index = random.nextInt(str.length());
			g.drawString(str.charAt(index) + "",width / 5 * i,30);
			stringBuilder.append(str.charAt(index));
		}
		String checkCode = stringBuilder.toString();
		HttpSession session = request.getSession();
		session.setAttribute("checkCode",checkCode);
		//2.4 画干扰线
		g.setColor(Color.GREEN);
		//随机生成坐标点
		for (int i = 1; i < 5; i++) {
    
    
			int x1 = random.nextInt(width);
			int y1 = random.nextInt(height);
			int x2 = random.nextInt(width);
			int y2 = random.nextInt(height);
			g.drawLine(x1,y1,x2,y2);
		}
		//3 输出图片到response流
		ImageIO.write(image,"jpg",response.getOutputStream());
	}
}

JSP页面
failure.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>错误!<%= session.getAttribute("errorMsg")%></h1>
</body>
</html>

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>登录成功 <%= session.getAttribute("username")%> , 欢迎你!</h1>
</body>
</html>

Cookie和session区别

1.存储位置不同
2.类型,大小限制不同
3.安全性

猜你喜欢

转载自blog.csdn.net/vcj1009784814/article/details/106084292
今日推荐