一次会话:打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器
用户登录后在一次会话中用户信息有效。
商品加入购物车,关闭浏览器,打开浏览器进入购物车,查看上次的商品。
会话管理: 管理浏览器客户端 和 服务器端之间会话过程中产生的会话数据。
context域对象是所有用户的公共资源,会覆盖数据,不适用。
request域对象一定要使用转发技术跳转页面,不适用。
Cookie 会话数据保存在浏览器客户端;
Session 会话数据保存在服务器端;
Cookie://servletAPI.chm javax.servlet.http
API:
1、构造Cookie对象:Cookie(String name,String value)
2、设置Cookie:
void setPath(String uri) 设置cookie的有效访问路径
void setMaxAge(int expiry) 设置有效时间
void setValue(String newValue)
3、发送cookie到浏览器端保存,服务器端不会保存cookie数据
void response.addCookie(Cookie cookie)
4、服务器接收cookie
Cookie[] request.getCookies()
示例1、
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、服务器创建cookie对象,把会话数据存储到cookie对象中
//2、浏览器得到服务器发送的cookie,然后保存在浏览器端
//3、服务器发送cookie信息到浏览器
//4、浏览器在下次访问服务器时,会带着当前web应用下的cookie信息
//5、服务器接收到浏览器带来的cookie信息
Cookie cookie=new Cookie("name","MrL");//不能存放中文
Cookie cookie2=new Cookie("age","11");
//cookie.setPath("/day11");设置cookie有效路径,默认是当前web应用下,
cookie.setMaxAge(20);//20秒,从最后不调用cookie开始计算
//正整数:表示cookie数据保存浏览器的缓存目录(硬盘中)
//-1, 负整数 表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了
//零:表示删除同名的cookie数据
response.addCookie(cookie);//自动拼接cookie 隐藏发送了一个set-cookie名称的响应头 //手动拼接 response.setHeader("set-cookie","name=mrl,age=11");
response.addCookie(cookie2);
Cookie[] cookies=request.getCookies();
if(cookies!=null){
for(Cookie c:cookies){
System.out.println(c.getName()+"="+c.getValue());
}
}else{
System.out.println("没有接收到cookie数据");
}
}
浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB
//ProductDao.java public class ProductDao { // 该类存放对Product对象CRUD方法 private static List<Product> data=new ArrayList<Product>(); /* * 初始化商品数据 */ static{ //只执行一次 for(int i=0;i<=10;i++){ data.add(new Product(""+i,"笔记本"+i,"LN00"+i,34.0+i)); } } /* * 查询到所有商品 */ public List<Product> findAll(){ return data; } /* * 根据编号查找商品 */ public Product findById(String id){ for(Product p:data){ if(p.getId().equals(id)); return p; } return null; } } //Product.java public class Product{ private String id,name,proType; provate double Price; //getter setter public Product(){super();} public Product(String id,String name,double price){ super(); this.id=id; this.price=price; } public String toString(){ return "Product[id="+id+",price"+price+"]"; } } //ListServlet.java public class ListServlet extends HttpServlet{ public void doGet(request,response) throws Exception{ response.setContentType("text/html;charset=utf-8"); ProductDao dao=new ProductDao(); List<Product> list=dao.findAll(); String html="<html><body><table>"; if(list!=null){ for(Product p:list){ html+="<td><a href='"+request.getContextPath()+"/DetailServlet?id="+p.getId()+"'>"+p.getName()+"</td>"; } } } //浏览过的商品 html += "最近浏览过的商品:<br/>"; //取出prodHist的cookie Cookie[] cookies = request.getCookies(); if(cookies!=null){ for (Cookie cookie : cookies) { if(cookie.getName().equals("prodHist")){ String prodHist = cookie.getValue(); // 3,2,1 String[] ids = prodHist.split(","); //遍历浏览过的商品id for (String id : ids) { //查询数据库,查询对应的商品 Product p = dao.findById(id); //显示到浏览器 html += ""+p.getId()+" "+p.getName()+" "+p.getPrice()+"<br/>"; } } } } response.getWriter().append(html); } //DetailServlet.java, Cookie cookie=new Cookie("prodHist",createVal(request,id)); private String createVal(HttpServletRequest request,String id){ Cookie[] cookies = request.getCookies();//cookie去掉重复值,id放到前面,只存放最近3个浏览记录 String prodHist = null; if(cookies!=null){ for (Cookie cookie : cookies) { if(cookie.getName().equals("prodHist")){ prodHist = cookie.getValue(); break; } } } if(cookies==null || prodHist==null){ return id; } String[] ids=prodHist.split(","); Collection colls = Arrays.asList(ids); //<3,21> // LinkedList 方便地操作(增删改元素)集合 // Collection -> LinkedList LinkedList list = new LinkedList(colls); if(list.contains(id)){ list.remove(id); } list.addFirst(id); if(list.size()>3){ list.removeLast(); } StringBuffer sb = new StringBuffer(); for (Object object : list) { sb.append(object+","); } String result = sb.toString(); result = result.substring(0, result.length()-1); return result; }
Session:会话数据保存在服务器内存中,一个浏览器独占一个session对象
cookie的局限:cookie不能保存中文,不能保存对象只能保存字符串,1个cookie容量不能超过4k
1)创建或得到session对象
HttpSession getSession()
HttpSession getSession(boolean create)
2)设置session对象
void setMaxInactiveInterval(int interval) : 设置session的有效时间
void invalidate() : 销毁session对象
java.lang.String getId() : 得到session编号
3)保存会话数据到session对象
void setAttribute(java.lang.String name, java.lang.Object value) : 保存数据
java.lang.Object getAttribute(java.lang.String name) : 获取数据
void removeAttribute(java.lang.String name) : 清除数据
http请求中Set-Cookie:JSESSIONID=*
1)创建或得到session对象
HttpSession getSession()
HttpSession getSession(boolean create)
2)设置session对象
void setMaxInactiveInterval(int interval) : 设置session的有效时间
void invalidate() : 销毁session对象
java.lang.String getId() : 得到session编号
3)保存会话数据到session对象
void setAttribute(java.lang.String name, java.lang.Object value) : 保存数据
java.lang.Object getAttribute(java.lang.String name) : 获取数据
void removeAttribute(java.lang.String name) : 清除数据
代码解读:HttpSession session = request.getSession();
1)第一次访问创建session对象,给session对象分配一个唯一的ID,叫JSESSIONID
new HttpSession();
2)把JSESSIONID作为Cookie的值发送给浏览器保存
Cookie cookie = new Cookie("JSESSIONID", sessionID);
response.addCookie(cookie);//有效时间 为负数 浏览器关闭清空cookie
3)第二次访问的时候,浏览器带着JSESSIONID的cookie访问服务器
4)服务器得到JSESSIONID,在服务器的内存中搜索是否存放对应编号的session对象。
5)如果找到对应编号的session对象,直接返回该对象
6)如果找不到对应编号的session对象,创建新的session对象,继续走1的流程
1)java.lang.String getId() : 得到session编号
2)两个getSession方法:
getSession(true) / getSession() : 创建或得到session对象。没有匹配的session编号,自动创建新的session对象。
getSession(false): 得到session对象。没有匹配的session编号,返回null
3)void setMaxInactiveInterval(int interval) : 设置session的有效时间
session对象销毁时间:
3.1 默认情况30分服务器自动回收
3.2 修改session回收时间
3.3 全局修改session有效时间
<!-- 修改session全局有效时间:分钟 -->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
3.4.手动销毁session对象 void invalidate(): 销毁session对象
4)如何避免浏览器的JSESSIONID的cookie随着浏览器关闭而丢失的问题
手动发送一个硬盘保存的cookie给浏览器
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
禁用Cookie后servlet共享数据导致的问题。
解决方案:URL重写
response. encodeRedirectURL(java.lang.String url)
用于对sendRedirect方法后的url地址进行重写。
response. encodeURL(java.lang.String url)
用于对表单action和超链接的url地址进行重写 <a href=“<%=response.encodeURL(“maillogin.jsp“)%>“>