session概念
- 存储在服务器端的一种会话技术,用于保存用户数据,一个浏览器独占一个session对象
- session对象由服务器创建,但实际上它是依赖于客户端的cookie技术
session优点
- session和request,servletContext一样是一个域对象,同个应用的多个资源共享其中的数据
- cookie只能存字符串,session能存对象
- 通过request创建session对象。request.getSession();
session常用方法
1. Object getAttribute(String name); //取值
2. void setAttribute(String name, Object value); //设置
3. void removeAttribute(String name); //移除
4. void setMaxInactiveInterval(int interval); //设置存活时间
5. void invalidate(); //session立即无效
session创建原理
- 从客户端cookie中取得名为JSESSIONID的值
- 如果没有这个cookie,那么服务器会创建新的session对象,并分配JSESSIONID的值,回写到客户端cookie,此时包含在浏览器内存中,而不是持久化在硬盘上。
- 如果有这个cookie,那么服务器会在内存中根据ID找session对象,找到了则取出。如果找不到,那么跟第2步一样,重新创建一个。
其他
- 默认session对象在服务器中会存活30分钟
如果浏览器禁用了cookie,那么需要对网站的所有URL地址进行重写,服务器会把sessionID的值用分号拼接到URL中,这样在访问任何资源的时候,都可以接收到。当然前提是服务器已经为你单独创建了一个sessionID。
- 用于对sendRedirect方法后的url地址进行重写。
response.encodeRedirectURL(java.lang.String url)
- 用于对表单action和超链接的url地址进行重写
response.encodeURL(java.lang.String url)
- 用于对表单action和超链接的url地址进行重写
- 用于对sendRedirect方法后的url地址进行重写。
如果在会话过程中,服务器重启或者内存溢出,session对象中的用户数据不会丢失,而是会被存盘,从内存中被序列化到硬盘中,此过程为钝化(搁置)。服务器重启完毕之后,再从硬盘中读取session数据,此过程为活化(激活)。
购物车例子
主要有下面四个类
1. Menu 首页,用于展示所有图书
2. AddToCart 将图书添加到购物车,存入session
3. ShowCart 展示购物车中的图书
4. DBUtils 获得图书对象的工具类
package com.samblack323.service;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.samblack323.entity.Book;
import com.samblack323.util.DBUtils;
public class Menu extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设定好字符集
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//得到输出流
PrintWriter out = resp.getWriter();
out.println("本站有这些书:" + "<br>");
out.println("<hr>");
//拿到所有书
Map<String, Book> allBooks = DBUtils.getAllBooks();
for (Entry<String, Book> book : allBooks.entrySet()) {
String name = book.getValue().getName();
String id = book.getKey();
//组成<a>标签,get方式提交id到下一个servlet
out.println("<a href='"+req.getContextPath()+"/session/addtocart?id="+id+"' target='_blank'>"+ name +"</a>");
}
out.println("<hr>");
//跳转到查看购物车的sevlet
out.println("<a href='"+req.getContextPath() +"/session/showcart'>查看购物车</a>");
}
}
package com.samblack323.service;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
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;
import com.samblack323.entity.Book;
import com.samblack323.util.DBUtils;
public class AddToCart extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设定好字符集
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// 得到输出流
PrintWriter out = resp.getWriter();
// 从请求对象中得到id的值,并根据id得到书
String id = req.getParameter("id");
Book book = DBUtils.getBookById(id);
// 拿到session对象
HttpSession session = req.getSession();
// 拿到session中的list对象
List<Book> cart = (List<Book>) session.getAttribute("cart");
// 若是第一次访问,session中是没有该list集合的,需要new一个
if (cart == null) {
cart = new ArrayList<Book>();
} else {
// 去除重复添加
for (int i = 0; i < cart.size(); i++) {
int index = cart.indexOf(book);
// 如果index等于-1,说明list中没有此book
if (index != -1) {
cart.remove(index);
}
}
}
// 将书加入到list集合中
cart.add(book);
// 把list集合存入session
session.setAttribute("cart", cart);
}
}
package com.samblack323.service;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.ListIterator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.samblack323.entity.Book;
public class ShowCart extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设定字符集
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// 得到输出流
PrintWriter out = resp.getWriter();
out.println("购物车中有如下图书" + "<br>");
// 得到session和seesion中的list
HttpSession session = req.getSession();
List<Book> cart = (List<Book>) session.getAttribute("cart");
// 如果有值,把list中的书都展示出来
if (cart != null) {
ListIterator<Book> iterator = cart.listIterator();
while (iterator.hasNext()) {
Book book = iterator.next();
out.println(book.getName() + "<br>");
}
} else {
out.println("您还没有购买任何图书,两秒后跳转到首页。。。");
resp.setHeader("refresh", "2;url=" + req.getContextPath() + "/session/menu");
}
}
}
package com.samblack323.util;
import java.util.HashMap;
import java.util.Map;
import com.samblack323.entity.Book;
public class DBUtils {
private static Map<String,Book> books = new HashMap<String,Book>();
//直接搞五本书,简单粗暴
static {
books.put("1", new Book("1", "金瓶梅", 20, "兰陵笑笑生"));
books.put("2", new Book("2", "葵花宝典", 20, "东方不败"));
books.put("3", new Book("3", "九阴真经", 30, "梅超风"));
books.put("4", new Book("4", "玉女心经", 10, "小龙女"));
books.put("5", new Book("5", "牡丹亭记", 40, "汤显祖"));
}
//得到所有书,便于展示所有商品
public static Map<String,Book> getAllBooks() {
return books;
}
//根据ID等到书,便于展示详细信息
public static Book getBookById(String id) {
return books.get(id);
}
}