Java Web程序设计——会话及其会话技术

思维导图放上:

java会话管理 重点 java什么是会话_java会话管理 重点

会话概述

  • 从打开浏览器,到访问网页,到最终关闭浏览器,整个过程就是一次会话。
    比如:一个用户在某网站上的整个购物过程就是一个会话
会话的特点
  • 包含多个请求,一次完整的会话针对一个用户
会话技术
  • Cookie技术,客户端技术
  • Session技术,服务端技术
会话中的数据存储问题

在一次会话中往往会产生一些数据,而这些数据是需要保存起来的

  • 如果使用request作用域来保存会话中产生的数据,由于会话是多次请求,多次响应,而request域的作用范围仅仅是一次请求,所以用request域保存会话中产生的数据,作用范围太小了
  • 如果使用ServletContext作用域来保存会话中产生的数据,ServletContext的作用范围是整个WEB应用,如果将每一个客户端和服务器产生的会话数据都保存在ServletContext域中,很可能会发生混乱

例:
在某宝买东西,买完商品后,买的商品存到什么对象比较合适?

  1. 使用request域对象保存商品信息:不可以,因为每次发送请求,都会产生一个新的请求对象
  2. 使用ServletContext域对象保存商品信息:可以,但是不合理。
    所以在开发中,保存会话过程中产生的数据,采用会话技术,也就是使用Cookie和Session技术来保存会话过程产生的数据。

Cookie对象

  • Cookie是一种会话管理技术,它是用老保存会话过程中产生的数据,然后在浏览器和服务器交互时,会使用cookie里面保存的数据。

注:首次访问服务器,浏览器不会携带Cookie到服务端。

Cookie在浏览器和服务器之间的传输:

java会话管理 重点 java什么是会话_web_02


java会话管理 重点 java什么是会话_java会话管理 重点_03


结论:1.第一次访问服务器,服务器会增加Set-Cookie头字段,将Cookie信息发送给浏览器,并保存在客户端。

2.当后续访问服务器时,会在请求消息中将用户信息以Cookie的形式发送给服务器,从而使服务器端分辨出当前请求是由哪个用户发出的。

Cookie常用的API
  • 得到Cookie对象:Cookie cookie = new Cookie(String key,String value);
  • 响应Cookie到浏览器端:response.addCookie(cookie);
  • 得到Cookie名称:String key = cookie.getName();
  • 得到Cookie的值:String value = cookie.getValue();
  • 给Cookie设置生命时长:setMaxAge(int sr);
    例:cookie.setMaxAge(606024*7),说明Cookie能存活7天
  • 给Cookie设置路径,设置域名:setPath(路径的url),setDomain(域名);
    例:域名就是服务器名称,比如:www.CSDN.net
  • 获取Cookie:Cookie[ ] cookies = request.getCookies();

通过Cookie实现显示用户上次访问时间

步骤:

  1. 判断是否是首次访问:如果Cookie里面有时间,说明就不是第一次访问
  2. 如果是第一次访问,创建Cookie,保存时间,把这个Cookie回写到浏览器端
  3. 如果不是第一次访问,把时间回写到浏览器,记住当前时间,把时间保存Cookie里面
package chapter.cookie.example;

import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 显示用户的上次访问时间
 */
public class LastAccessServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 处理响应中文的乱码问题
		response.setContentType("text/html;charset=utf-8");
		// 1.获取cookie数组
		Cookie[] cookies = request.getCookies();
		// 2.遍历cookie数组
		String lastTime = null;
		for (int i = 0; cookies != null && i < cookies.length; i++) {
			// 3.获取cookie的名称
			String name = cookies[i].getName();
			if ("lastAccess".equals(name)) {
				// 获取cookie的时间
				lastTime = cookies[i].getValue();
			}
		}
		// 4.判断是否是首次访问,如果cookie里有时间,就不是第一次访问,否则就是第一次访问
		if (lastTime == null) {
			// 第一次访问
			response.getWriter().print("你是首次访问本网站");
		} else {
			// 说明不是第一次访问
			// 把上次访问时间,回写到浏览器
			response.getWriter().print("你的上次访问时间:"+lastTime);
		}
		// 第三次,第四次------
		String time = String.format("%tF %<tT", new Date());
		Cookie cookie = new Cookie("lastAccess", time);
		cookie.setMaxAge(60*60*24*7);
		response.addCookie(cookie);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

启动服务器,在浏览器中打开可见

java会话管理 重点 java什么是会话_session_04

cookie规范
  • 一个cookie最大4kb
  • 一个服务器最多在一个客户端寄存20个cookie
  • 一个浏览器最多保存300个cookie
  • cookie是有安全隐患的:由于数据保存在浏览器端,所以可以被任意的查看,安全性较低,但是可以长时间存储数据。cookie善于存储安全性要求较低,但是存储时间较长的数据。

Session对象

  • Session是一种会话管理技术,用来保存会话过程中的数据,保存的数据存储到服务器。是基于Cookie实现的,更确切的说是基于会话级别的Cookie实现的。
HttpSession API
  • 得到Session的id(JESSIONID对应的值):getId()
  • 设置Session的生命时长:setMaxInactiveInterval(int interval)
  • 销毁Session:invalidate()
  • 得到Session:HttpSession session = getSession()
  • Seesion域对象:作用范围一次完整的会话(包含多个请求):
    存值:setAttribute(String key,object obj);
    取值:Object obj = getAttribute(String key);
    移除:removeAttribute(String key);

注:域对象:request域对象:作用范围一次请求,通常和转发操作配合使用;
session域对象:作用范围一次会话,通常和重定向操作配合使用
servletContext域对象:作用范围整个项目,和重定向、转发操作都可以配合使用。
以上作用范围依次变大。

Session超时管理
  • Session对象是由生命时长,它的默认存活时间是30分钟
  • 在会话过程中,会话的有效时间可以在web.xml文件中设置,其默认值由Servlet容器定义。在<tomcat安装目录>\conf\web.xml文件中,可以找到如下一段配置信息:
<session-config>
        <session-timeout>30</session-timeout>
    </session-config>

注:如果将<session-timeout>元素中的时间值设置成0或负数,则表示会话永不超时!

Session实现购物车

步骤:

  1. 创建Book封装图书信息:Book
package session.example01;

public class Book {
	private String id;
	private String name;
	
	public Book() {
		super();
	}

	public Book(String id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
}
  1. 创建BookDB,模拟数据库,里面保存图书
package session.example01;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

public class BookDB {
	private static Map<String, Book> map = new LinkedHashMap<String, Book>();
	static {
		map.put("1", new Book("1", "javaWeb"));
		map.put("2", new Book("2", "java基础"));
		map.put("3", new Book("3", "python"));
		map.put("4", new Book("4", "php"));
		map.put("5", new Book("5", "C语言"));
	}

	// 1.得到所有图书
	public static Collection<Book> getAll() {
		return map.values();
	}

	// 2.根据map的key,也就是图书的id,得到某本图书
	public static Book getBook(String id) {
		return map.get(id);

	}
}
  1. 提供图书的购买页面:ListBookServlet
package session.example01;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 提供一个购买图书的页面
 */
public class ListBookServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 处理响应中文的乱码
		response.setContentType("text/html;charset=utf-8");
		//1.得到所有图书
		Collection<Book> books = BookDB.getAll();
		//2.显示页面
		PrintWriter out = response.getWriter();
		out.print("以下是本网站售卖的所有图书:"+"<br/><br/>");
		//3.遍历集合,显示图书页面
		for(Book b:books) {
			//4.得到图书名称
			String name = b.getName();
			String id = b.getId();
			//提供一个购买图书的链接
			String url="<a href='/chapter/purcharse?id="+id+"'>点击购买</a>";
			out.print("图书名称:"+name+"  "+url+"<br/><br/>");
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}
  1. 添加购物车:PurcharseServlet
package session.example01;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 添加购物车
 */
public class PurcharseServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		// 1.获取图书信息
		String id = request.getParameter("id");
		//判断id是否存在
		if (id == null) {
			// 没有购买图书
			response.sendRedirect("/chapter/list");
			return;
		}
		//2.图书已经购买了
		Book book = BookDB.getBook(id);
		//3.把图书添加到购物车
		HttpSession session = request.getSession();
		java.util.List<Book> list = (java.util.List<Book>) session.getAttribute("cart");
		//4.判断购物车是否存在,是不是首次购买
		if (list==null) {//首次购买
			list = new ArrayList<Book>();
			session.setAttribute("cart", list);
		}
		//5.把图书添加到购物车
		list.add(book);
		//6.把请求跳转到CartServlet
		//session基于自己创建的cookie完成效果:在浏览器关闭后,cookie对象还存在,就能找到session对象
		Cookie cookie = new Cookie("JEAAIONID", session.getId());
		cookie.setMaxAge(60*60*24);
		cookie.setPath("/chapter");
		response.addCookie(cookie);
		//跳转到cartServlet里面
		response.sendRedirect("/chapter/cart");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}
  1. 显示购物车图书信息:CartServlet
package session.example01;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class CartServlet
 */
public class CartServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		// 1.得到购物车
		List<Book> cart = null;
		// 2.得到用户自己的session
		HttpSession session = request.getSession(false);
		// 3.自己定义一个flag,判断购物车里面是否有图书
		boolean cartFlag = true;
		if (session == null) {
			cartFlag = false;
		} else {
			cart = (List<Book>) session.getAttribute("cart");
			if (cart == null) {
				cartFlag = false;
			}
		}
		// 4.购物车有商品了
		if (!cartFlag) {
			out.print("对不起,你的购物车里面没有图书,请去购买。");
		} else {
			// 购物车有图书
			out.print("购买图书如下:" + "<br/>");
			for (Book b : cart) {
				out.print("购买的图书:" + b.getName() + "<br/>");
			}
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

6.启动服务器,用浏览器打开

java会话管理 重点 java什么是会话_前端_05


java会话管理 重点 java什么是会话_session_06


java会话管理 重点 java什么是会话_session_07

注:如果浏览器禁用了cookie,购物车功能就不能实现了,因为session是基于cookie实现的。

Session实现用户登录

  1. 创建User类,封装用户名和密码
package session.example;

public class User {
	private String username;
	private String password;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public User() {
		super();

	}

}
  1. 提供首页面,欢迎用户登录:IndexServlet,提供一个退出的链接
package session.example;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class IndexServlet
 */
public class IndexServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 用来欢迎用户登录,并且显示用户信息、
		response.setContentType("text/html;charset=utf-8");
		//1.获取用户信息
		HttpSession session = request.getSession();
		User user = (User)session.getAttribute("key");
		//2.判断用户是否存在
		if(user==null) {
			//说明用户不存在,也就是用户根本没有登录
			response.sendRedirect("chapter/login.html");
		}else {
			String name = user.getUsername();
			String url = "<a href='/chapter/logOut'>退出</a>";
			response.getWriter().print("欢迎您:"+name+" 登录本网站"+url);
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}
  1. 提供登录的servlet:处理登录请求
package session.example;

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

/**
 * Servlet implementation class LoginServlet
 */
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		// 1.获取用户名和密码
		String name = request.getParameter("username");
		String psw = request.getParameter("password");
		// 2.判断用户和密码是否正确,用户名是admin,密码是123,就认为是正确的,否则是错误的
		if ("admin".equals(name) && "123".equals(psw)) {
			// 登录成功
			User u = new User();
			u.setUsername(name);
			u.setPassword(psw);
			HttpSession session = request.getSession();
			session.setAttribute("key", u);
			// 自己创建cookie,让session使用自己的cookie
			Cookie c = new Cookie("JESSIONID", session.getId());
			c.setMaxAge(3600 * 24 * 7);
			c.setPath("/chapter");
			response.sendRedirect("/chapter/index");
		} else {
			// 登陆失败
			response.getWriter().print("用户名和密码错误,登录失败!");
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

login.html

java会话管理 重点 java什么是会话_cookie_08

  1. 提供退出servlet:处理退出页面的请求
package session.example;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class LogOutServlet
 */
public class LogOutServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 清空session
		HttpSession session = request.getSession();
		// session.removeAttribute("key");
		session.invalidate();
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

启动服务器,用浏览器打开

登录成功:

java会话管理 重点 java什么是会话_web_09

java会话管理 重点 java什么是会话_前端_10

登陆失败:

java会话管理 重点 java什么是会话_web_11


java会话管理 重点 java什么是会话_session_12