天天看点

Servlet详解(三):会话技术与Cookie

会话技术

什么是会话技术呢?

艺术来源于生活,技术也来源于生活。两个总统在一起聊天,我们称作一次会话。两个人进行会话,有两个前提:1. 两个人的语言可以互相沟通 2. 两个人要有记忆力,可以记住对方所说的内容。

在javaweb中,浏览器和服务器之间的通讯也可以看作是两个人在聊天,为了聊天尽兴,所以双方也要拥有"记忆力",可以保存之前的聊天状态。

会话范围:

打开网站,完成所需要的所有需求,是一次会话。

会话技术常见应用:

用户登录后在一段事件内,并不需要再次登录。

浏览器的记忆力:Cookie

服务器的记忆力:Session

Cookie

在浏览器端记录一些信息

原理:

Servlet详解(三):会话技术与Cookie

这个响应头的信息是一个键值对

set-Cookie:name=Feathers
           

原理即使设置响应头,浏览器接受响应头保存,然后浏览器下次的请求都会带这这个头的信息。

服务器发送cookie

// 创建Cookie 并添加到响应头中
Cookie cookie = new Cookie("name", "Feathers");
response.addCookie(cookie);
           

浏览器获取Cookie:

Cookie[] cookies = request.getCookies();
Cookie nameCookie = c;
if (cookies != null){
	for (int i = 0; i < cookies.length; i++){
		if (cookie.getName().equals("name")){
			nameCookie = cookie;
		}
	}
}
if (nameCookie != null)
	System.out.println(nameCookie.getValue());
           

设置Cookie时间

  1. 默认Cookie时间:

    浏览器关闭时,即会话结束时。’

  2. 指定Cookie时间:
Cookie c = new Cookie("name","Feathers");
c.setMaxAge(60 * 60 * 24 * 7); // Cookie有效期,告诉浏览器保存Cookie两周
// c.setMaxAge(-1); // 在会话结束后删除Cookie,即默认值
// c.setMaxAge(0); // 使用一个0秒后过期的Cookie,将会覆盖原来的Cookie,达到删除Cookie,达到删除Cookie的效果
response.addCookie(c);
           

浏览器发送Cookie

浏览器发送Cookie的条件:

  • 网站域(主机名)相同
  • 网站路径是Cookie的子路经
Servlet详解(三):会话技术与Cookie

有一个cookie的路径为

/CookieDemo

,主机域是localhost

访问如下路径:

http://localhost:8080/CookieDemo

,会发送

http://localhost:8080/CookieDemo/BServlet

,会发送

http://baidu:8080/CookieDemo/AServlet

,不会发送

http://localhost:8080/Test

,不会发送

Cookie主机和路径的设置

设置路径

  1. 默认情况

    发送Cookie的资源的所在路径

    例如:发送Cookie的资源路径为

    http://localhost:8080/CookieDemo/AServlet

    那么Cookie的默认路径就为

    /CookieDemo

  2. 手动设置
Cookie c = new Cookie("name","Feathers");
c.setPath("/MyCookie/MyServlet");
response.addCookie(c);
           

设置主机

  1. 默认主机

    发送Cookie资源的服务器主机名

  2. 手动设置
Cookie c = new Cookie("name","Feathers");
// 只能设置当前主机,可以是当前主机的主机的一部分,不能仿造别的网站的Cookie,有安全隐患
c.setDomain("loaclhost"); // Domain 域的意思
response.addCookie(c);
           

删除Cookie

cookie.setMaxAge(0)

覆盖达到删除的目的,需要注意:

只有cookie的路径、键、主机一致才可以覆盖。

###Cookie记录中文的键值对

Cookie为什么不能使用中文?

在HTTP协议中,除了正文,其他地方都不能使用Latin码表以下的码表

要想发送中文,需要使用

URLEncode

类进行转化,类似Get请求的参数。

URLEncode会将汉字转化为 二进制,然后每八位二进制数转化为两位16进制数,每两位十六进制数之间又使用%隔开。

所以我们经常看到

4C%45%7E%3A

这样的字符串。

然后,在服务器端进行decode解析,就完成了cookie传递中文的效果。

使用Cookie实现记住帐号的功能

<!-- index.jsp 登录界面界面 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录</title>
<%
	String username = "";
	System.out.println("==" + username);
	Cookie[] cookies = request.getCookies();
	for (int i = 0; i < cookies.length; i++){
		if ("username".equals(cookies[i].getName())){
			username = cookies[i].getValue();
			System.out.println("==" + username);
		}
	}
	
	if (username == null){
		username = "";
	}
%>
</head>
<body>

	<form action="FirstServlet" method="get">
		<table>
			<tr>
				<td>用户名:</td>
				<td>
					<input type="text" name="username" value=<%= username%>/>
					<font color="red"><%=request.getAttribute("error") == null ? "":request.getAttribute("error") %></font>
				</td>
			</tr>
			<tr>
				<td>密码:</td>
				<td><input type="password" name="password" value=""/></td>
			</tr>
			<tr>
				<td><input type="checkbox" name="remember" value="yes"/>记住用户名</td>
			</tr>
			<tr>
				<td><input type="submit" value="提交"/></td>
			</tr>
		</table>
	</form>
</body>
</html>

           
/* FirstServlet.java  处理登录信息、用来转发的类 */

package com.feathers.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet {

    public FirstServlet() {
        super();
    }
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		System.out.println("1");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String remember = request.getParameter("remember");
		
		System.out.println("2" + remember);
  		if (username == null || "".equals(username.trim())){
			request.setAttribute("error", "对不起,用户名不能为空");
			request.getRequestDispatcher("/index.jsp").forward(request, response);
			return;
		}
  		System.out.println("3");
		if (password == null || "".equals(password.trim())){
			request.setAttribute("error", "对不起,密码不能为空");
			request.getRequestDispatcher("/index.jsp").forward(request, response);
			return;
		}
		System.out.println("4" + remember);
		
		if (remember != null && remember.equals("yes")){
			System.out.println("添加了");
			Cookie cookie = new Cookie("username", username);
			cookie.setMaxAge(60*60*24*7*2);//保存两周
			response.addCookie(cookie);
			// 重定向到成功页面
			response.sendRedirect("/ServletDemo1/response.jsp");
		}
	}

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

}
           
<!-- response.jsp 登录成功后,重定向的页面 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功</title>
</head>
<body>
	<h1>登录成功</h1>
</body>
</html>
           

Session

在服务器记录一些信息。

###Session原理

类似Cookie…

Servlet详解(三):会话技术与Cookie

浏览器第一次访问服务器,服务器返回给浏览器一个sessionId,以后浏览器每次请求,都携带着这个sessionID,用来验证自己的身份。

常见用例:购物车,用户将商品加入到购物车中,第一次加入时,服务器给一个sessionId,以后每次加入都向这个ID的购物车加入商品。而且用户在查看购物车时,也会传入sessionID(key),服务器接受到sessionID后,根据SessionID获取Session(即value,购物车的内容)。

那么服务器是怎么返回给浏览器一个sessionID的呢?

通过给浏览器设置一个cookie,即在响应头中添加

set-cookie:JSESSIONID=39FECEA2F;Path=/项目路径

,且有效时间未设置(浏览会话结束时)的cookie。

所以浏览器也就是通过request对象携带cookie从而携带sessionID给服务器的。

Session主要用途

最常见的最基本的用于保存登录状态,以及上文的购物车(未登录也会有)

###使用Session

// 获取服务器的session
HttpSession session = request.getSession(true); // true,如果服务器没有session,那么服务器就会创建一个session返回给浏览器。false,相反,如果没有session,不会创建,不会返回session。
// request.getSession(); // 即 request.getSession(true)

// session的操作
session.setAttribute("key","value"); // 向session域中添加一个键值对
session.getAttributeNames();
session.removeAttribute("key");
           

Session的寿命

web.xml

中修改标签

<session-config>

标签

<session-config>
	<!-- 配置session的过期时间,默认30分钟,国际标准 -->
	<session-timeout>30</session-timeout>
</session-config>
           

在Session对象中也有方法进行设置session的寿命:

sessionID的存在时间?

就是cookie的时间,可以通过获取cookie设置setMaxAge 控制

Session域的范围

  • session的范围就是一次会话期间。
  1. 浏览器第一次访问服务器,服务器创建session对象,会话开始
  2. 浏览器关闭,会话结束,保存的sessionID也就丢失(默认有效事件为一个会话),session也就无效了。
  3. 或者session已经过期了。
  4. session对象在服务器内被手动销毁了

API

boolean session.isNew() // 判断session是否是新的,即session是否是第一次访问,访问第二次就是旧的
session.getCreationTime() // 获取session创建事件
session.getID() // 获取session的ID
session.getLastAccessTime() // 获取最后一次访问session的时间
session.getMaxInactiveInterval(60) // 设置session最大有效时间60s
session.invalidate(); // 立即销毁session