1、会话
(1)什么是会话?
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
(2)会话过程中要解决的一些问题?
每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据。
例如:用户点击超链接通过一个servlet购买了一个商品,程序应该保存用户购买的商品,以便于用户点结帐servlet时,结帐servlet可以得到用户商品为用户结帐。
思考:用户购买的商品保存在request或servletContext中行不行?
2、保存会话数据的两种技术:
(1)Cookie
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
(2)Session
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
(3) Session 占用服务器空间,安全性更高 ,Cookie节省服务器资源,安全性差一些
3、Cookie技术
4、Cookie快速入门
显示用户上次访问时间
package cn.itheima.cookie;
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 CookieServlet1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
// 首先要判断 用户 到底 有木有 带 cookie 过来.
Cookie lastVisitCookie = findCookie(cookies, "lastvisit");
response.setContentType("text/html;charset=utf-8");
if(lastVisitCookie == null){
response.getWriter().print("亲爱的, 你是 第一次 访问 噢 ...");
}else{
// 通过 cookie.getValue()拿到 cookie 的value 值.
String lastVistTime = lastVisitCookie.getValue();
long time = Long.parseLong(lastVistTime);
response.getWriter().print("亲, 你上一次的访问时间是 : " + new Date(time).toLocaleString());
}
// 将用户 最后一次的 访问时间 回写 给 用户 .
Cookie newCookie = new Cookie("lastvisit", System.currentTimeMillis() + "");
// 一种 : 没有设置 maxAge (maxicum) , 那么 默认的情况下 cookie的 有效时间是 浏览器 进程.
// 也就是 说, 如果浏览器 木有关闭, 那么 这个 cookie 就 一直存在
// 会话 级别的 cookie .
// 第二种 : 变成 持久化的 cookie 呢? // Cookie 的 有效期 就变成了 一个小时
newCookie.setMaxAge(60*60); // 60* 60
// 设置 cookie 的 有效 路径, 一般情况下 就设置 "/" ,但是 不是 最好的 设置 方法.
// 你可以针对 自己当前的servlet 去单独的设置 一个 有效的 路径, 这样 可能性能 会 高 一些.
// newCookie.setPath("/abc");
newCookie.setPath("/");
response.addCookie(newCookie);
}
private Cookie findCookie(Cookie[] cookies, String name) {
if(cookies==null){
// 说明 没有 带 任何 cookie 过来, 那也就更 没有 最后 访问 的时间 这样一个cookie 了吧.
return null;
}else{
// 如果 用户带了cookie 过来 , 那么 就去 带过来的cookie 中去查找 lastvisit这个cookie.
for (Cookie cookie : cookies) {
if(cookie.getName().equals(name)){
// 如果 查找 到, 直接 返回 这个cookie
return cookie;
}
}
return null;
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
1、第一次访问VisitServlet
请求中没有cookie信息
响应中 Set-Cookie: lastvisit=1350615153109
* Cookie信息保存浏览器缓存中
2、第二次访问VisitServlet
请求中 Cookie: lastvisit=1350615153109
响应中 Set-Cookie: lastvisit=1350615241359
默认cookie都是浏览器内存中进行缓存的 ,当浏览器关闭,会话结束,内存释放
* 从request请求中查找 指定name的cookie信息
public Cookie findCookie(Cookie[] cookies, String name) {
if (cookies == null) {
// 不存在任何cookie
return null;
} else {
// 存在cookie,查找指定cookie
for (Cookie cookie : cookies) {
if (cookie.getName().equals(name)) {
// 找到了
return cookie;
}
}
// 没有找到
return null;
}
}
* 服务器端向客户端写出一个新的cookie
Cookie newLastVisitCookie = new Cookie("lastvisit", System.currentTimeMillis()+ "");
response.addCookie(newLastVisitCookie);
5、Cookie API (阅读api 文档)
Javax.servlet.http.Cookie类用于创建一个Cookie,response接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。Cookie类的方法:
public Cookie(String name,String value)
setValue与getValue方法
setMaxAge与getMaxAge方法
setPath与getPath方法
setDomain与getDomain方法
getName方法
1 读取cookie
request.getCookies() 返回Cookie[]
首先判断cookies数组是否存在 cookies == null,如果cookies存在,根据cookie的name去查找指定cookie
* 参见 上面findCookie 方法
2、服务器向客户端发送cookie
cookie对象创建 new Cookie(name,value)
response.addCookie(cookie) 将cookie发送客户端
* cookie有name和value,提供三个方法 getName getValue setValue
3、cookie从持久性上分为两类 会话cookie和持久cookie
会话cookie 保存在浏览器内存中cookie,当会话结束浏览器关闭,会话cookie信息就是丢失
持久cookie 保存在浏览器临时文件缓存区中cookie (硬盘上) ,当关闭浏览器结束会话,持久cookie不会被删除
* 持久cookie存在过期时间,过期后会自动删除
持久cookie 需要设置cookie 有效期 setMaxAge
Set-Cookie: lastvisit=1350617047968; Expires=Fri, 19-Oct-2012 04:24:07 GMT
4、cookie访问有效路径
携带cookie 必须path一致
默认 http://localhost/day7/visit 生成cookie ---- 默认path 就是/day7/ (visit资源所在目录就是默认path)
* 只有在访问 http://localhost/day7/ 目录和子目录情况下 才会携带cookie 信息
path也可以手动指定 setPath
newLastVisitCookie.setPath("/abc");
抓取信息:
Set-Cookie: lastvisit=1350617427109; Expires=Fri, 19-Oct-2012 04:30:27 GMT; Path=/abc
再次访问 :http://localhost/day7/visit 不会携带cookie信息,因为path 不符合
最简单方案:setPath("/");
Set-Cookie: lastvisit=1350617644468; Expires=Fri, 19-Oct-2012 04:34:04 GMT; Path=/
5、cookie有效域名
setDomain 设置cookie有效域名 ---- 例如:setDomain(".itcast.cn"); 传智播客网站的cookie
* 不需要记这个
访问A 网站 ,生成 B网站 Cookie ----- 第三方cookie (恶意cookie)
访问A 网站, 生成A 网站Cookie ----- 第一方Cookie(安全cookie )
6、删除持久cookie
删除持久cookie,可以将cookie最大时效设为0,注意,删除cookie时,path必须一致,否则不会删除
6、Cookie细节
(1)一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
(2)一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
(3)浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
(4)如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。
(5)删除持久cookie,可以将cookie最大时效设为0,注意,删除cookie时,path必须一致,否则不会删除
7、Cookie应用
显示用户上次浏览过的商品(老师版)
package cn.itheima.cookie;
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 cn.itheima.utils.CookieUitls;
public class ShowPorductServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
// history
Cookie[] cookies = request.getCookies();
Cookie histCookie = CookieUitls.findCookie(cookies,"history");
response.setContentType("text/html;charset=utf-8");
if(histCookie==null){
// response.getWriter().write("您当前 无任何 商品 浏览记录 !!!");
Cookie historyCookie = new Cookie("history", id);
historyCookie.setMaxAge(60*60*14);
historyCookie.setPath("/");
response.addCookie(historyCookie);
}else{
String historyRecords = histCookie.getValue();
String[] records = historyRecords.split(",");
if(!existRecord(records,id)){
Cookie newCookie = new Cookie("history", historyRecords + "," + id);
newCookie.setMaxAge(60*60*14);
newCookie.setPath("/");
response.addCookie(newCookie);
}
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("浏览商品成功 !! <a href='/day05/cookie/product.jsp'>返回</a>");
}
private boolean existRecord(String[] records, String id) {
// TODO Auto-generated method stub
for (String record : records) {
if(record.equals(id)){
return true;
}
}
return false;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
<%@page import="cn.itheima.utils.CookieUitls"%>
<%@ 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>Insert title here</title>
</head>
<body>
<h3 style="color: red"><a href="/day05/clearrecords">删除浏览记录</a></h3>
<hr>
<h1>商品列表</h1>
<a href='/day05/showproduct?id=1'>辟邪剑谱</a>
<a href='/day05/showproduct?id=2'>泡妞秘籍</a>
<a href='/day05/showproduct?id=3'>我的野蛮女友</a>
<a href='/day05/showproduct?id=4'>别太单纯,也别太不单纯</a>
<a href='/day05/showproduct?id=5'>android 系统移植与调试</a>
<hr>
<h2>商品浏览记录</h2>
<%
Cookie[] cookies = request.getCookies();
Cookie histCookie = CookieUitls.findCookie(cookies, "history");
if(histCookie == null ){
out.print("您没有任何浏览记录");
}else{
String histRecords = histCookie.getValue();
out.print("您的浏览记录有: <br/>");
String[] records = histRecords.split(","); // 2 3 4
String [] bookNames = {"辟邪剑谱","泡妞秘籍","我的野蛮女友","别太单纯,也别..","android 系统移植与调试"};
for(int i=0; i<records.length;i++){
out.print(bookNames[Integer.parseInt(records[i])-1] + "<br/>");
}
}
%>
</body>
</html>
显示用户上次浏览过的商品(学生改良版)
package Exercise;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
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 Test3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("trxt/html;charset=utf-8");
String id=request.getParameter("id");
String[]books={"《狼图腾》","《追风筝的人》","《十万个为什么》","《Java基础详解》","《Android系统开发和移植》"};
float[]prices={50F,32.5F,27F,42F,59.5F};
//制作获取id的cookie
//制作书名——数目集合
Map<String,Integer>map = (Map<String, Integer>) request.getSession().getAttribute("map");
if(map==null)
{
map=new HashMap();
for(int i=0;i<5;i++)
{
map.put(i+"", 0);
}
}
float price=prices[Integer.parseInt(id)];
Cookie cookie=new Cookie(id,price+"");
cookie.setPath("/");
response.addCookie(cookie);
request.getSession().setAttribute("map", map);
response.sendRedirect("/day05/jsp/Test2.jsp?id="+id);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
<%@page import="cn.itheima.utils.CookieUitls"%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>我的购书城</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">
tr
{ text-align:center;
}
</style>
</head>
<body>
<hr color="#FF0000"/>
<h3><center>基于Cookie的图书购物车</center></h3>
<hr color="#0000FF" />
<br /><br />
<table align="center" border="1px" bordercolor="#0099FF">
<tr><th>图书名称</th><th>售价</th><th>选项</th></tr>
<tr><td>《狼图腾》</td><td>50元</td><td><a href="/day05/Test3?id=0">购买</a></td></tr>
<tr><td>《追风筝的人》</td><td>32.5元</td><td><a href="/day05/Test3?id=1">购买</a></td></tr>
<tr><td>《十万个为什么》</td><td>27元</td><td><a href="/day05/Test3?id=2">购买</a></td></tr>
<tr><td>《Java基础详解》</td><td>42元</td><td><a href="/day05/Test3?id=3">购买</a></td></tr>
<tr><td>《Android系统开发和移植》</td><td>59.5元</td><td><a href="/day05/Test3?id=4">购买</a></td></tr>
</table>
<br /><br />
<hr color="#CC00CC"/>
<center>
<h3>购物清单</h3><br />
<table align="center" bordercolor="red" border="1px">
<%
String[]books={"《狼图腾》","《追风筝的人》","《十万个为什么》","《Java基础详解》","《Android系统开发和移植》"};
Cookie[]cookies=request.getCookies();
Map <String,Integer> map=(Map<String,Integer>)request.getSession().getAttribute("map");
int num=0;
if(map!=null)
{
out.print("<tr><td>购买书目</td><td>数量</td><td>价格</td></tr>");
String id=request.getParameter("id");
num=map.get(id)+1;
map.put(id, num);
request.getSession().setAttribute("map", map);
float sum=0;
for(Cookie cookie:cookies)
{
if(cookie.getName().equals("JSESSIONID"))
{
continue;
}
String book=books[Integer.parseInt(cookie.getName())];
float price=Float.parseFloat(cookie.getValue());
int count=map.get(cookie.getName());
sum=price*count+sum;
out.print("<tr><td>"+book+"</td><td>"+count+"</td><td>"+price*count+"元</td></tr>");
}
out.print("<tr><td>总价</td><td colspan='2'>"+sum+"元</td></tr>");
out.print("<tr><td colspan='3'><a href='/day05/Test4?id=Test2'>清除历史记录</a></td></tr>");
}
else
{
out.print("您现在还没有购买记录~");
}
%>
</table>
</center>
<hr color="#CC0000">
</body>
</html>
8、Session
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
Session和Cookie的主要区别在于:
Cookie是把用户的数据写给用户的浏览器。
Session技术把用户的数据写到用户独占的session中(服务器端)。
Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
9、session为每个浏览器保存数据
10、session实现原理
(1)Session 将用户相关信息保存服务器端,服务器会为每个浏览器创建单独Session对象,每个用户各自数据 保存各自浏览器对应Session对象中。不同用户 获取到各自浏览器对应Session 保存数据。
(2)Session对象创建 : request.getSession();
(3)服务器端会为每个浏览器创建单独Session对象,如何做到的? Session的原理
* Session 通过cookie 传输 jsessionid 用来在服务器端查找对应Session对象
(4)问题:如何实现关掉浏览器后,再开浏览器,上次购买的商品还在。
1、第一次访问 响应 Set-Cookie: JSESSIONID=7B67782D880A07ADADA64A312ED23D72; Path=/day7
2、第二次访问 请求 Cookie: JSESSIONID=7B67782D880A07ADADA64A312ED23D72
关闭浏览器重新打开
3、直接访问 session2 : 无法访问刚才Session信息
4、解决方案:将jsessionid 信息保存 持久Cookie
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60 * 60 * 24);
cookie.setPath("/");
response.addCookie(cookie);
(5)抓取响应
Set-Cookie: JSESSIONID=4E14F3FD831BDAD3C532C13568EEA358; Path=/day7
Set-Cookie: JSESSIONID=4E14F3FD831BDAD3C532C13568EEA358; Expires=Sat, 20-Oct-2012 06:37:50 GMT; Path=/
(6)浏览器禁用Cookie之后,Session还能否使用 ? 可以的
* 浏览器无法保存cookie中jsession id ,无法完成Session追踪
SESSIONID=985E0B491708994C0039BEFC0B277056; Path=/day7
第二次请求服务器 http://localhost/day7/session2;jsessionid=985E0B491708994C0039BEFC0B277056
11、session案例
使用Session完成简单的购物车功能 (老师版)
package cn.itheima.session;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BuyServlet extends HttpServlet {
@SuppressWarnings("unchecked")
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取 用户 购买的 书的 id
String id = request.getParameter("id");
String[] bookNames = {"辟邪剑谱","这书能让你戒烟","玉女心经","金瓶梅","缺一门"};
String productName = bookNames[Integer.parseInt(id)-1];
Map<String,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
if(cart==null){
cart = new HashMap<String, Integer>();
}
if(!cart.containsKey(productName)){
cart.put(productName, 1);
}else{
int number = cart.get(productName);
cart.put(productName, number+ 1);
}
request.getSession().setAttribute("cart", cart);
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("添加商品到购物车成功 !!! <a href='/day05/session/product.jsp'>返回</a>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
<%@page import="java.util.Set"%>
<%@page import="java.util.Map"%>
<%@ 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>Insert title here</title>
</head>
<body>
<%
Map<String,Integer> cart = (Map<String,Integer>)request.getSession().getAttribute("cart");
if(cart==null){
out.print("您当前还木有 购买 任何 东东 ... <a href='/day05/session/product.jsp'>去购买</a>");
}else{
Set<String> names = cart.keySet();
out.print("亲, 您购买的 东东 有: <br/>");
for(String pName:names){
int number = cart.get(pName);
out.print("" + pName + ", 数量 : " + number +"<br/>");
}
}
%>
</body>
</html>
<%@ 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>Insert title here</title>
</head>
<body>
<h2>商品列表</h2>
辟邪剑谱:<a href='/day05/buy?id=1'>购买</a><br/>
这书能让你戒烟:<a href='/day05/buy?id=2'>购买</a><br/>
玉女心经:<a href='/day05/buy?id=3'>购买</a><br/>
金瓶梅:<a href='/day05/buy?id=4'>购买</a><br/>
缺一门:<a href='/day05/buy?id=5'>购买</a><br/>
<hr>
<a href="/day05/session/cart.jsp">查看购物车</a>
</body>
</html>
显示用户上次浏览过的商品(学生加强版)
package Exercise;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
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 Test3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("trxt/html;charset=utf-8");
String id=request.getParameter("id");
String[]books={"《狼图腾》","《追风筝的人》","《十万个为什么》","《Java基础详解》","《Android系统开发和移植》"};
float[]prices={50F,32.5F,27F,42F,59.5F};
//制作获取id的cookie
//制作书名——数目集合
Map<String,Integer>map = (Map<String, Integer>) request.getSession().getAttribute("map");
if(map==null)
{
map=new HashMap();
for(int i=0;i<5;i++)
{
map.put(i+"", 0);
}
}
float price=prices[Integer.parseInt(id)];
Cookie cookie=new Cookie(id,price+"");
cookie.setPath("/");
response.addCookie(cookie);
request.getSession().setAttribute("map", map);
response.sendRedirect("/day05/jsp/Test2.jsp?id="+id);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>我的购书城</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">
tr
{ text-align:center;
}
</style>
</head>
<body>
<hr color="#FF0000"/>
<h3><center>基于Session的图书购物车</center></h3>
<hr color="#0000FF" />
<br /><br />
<table align="center" border="1px" bordercolor="#0099FF">
<tr><th>图书名称</th><th>售价</th><th>选项</th></tr>
<tr><td>《狼图腾》</td><td>50元</td><td><a href="/day05/Test2?id=0">购买</a></td></tr>
<tr><td>《追风筝的人》</td><td>32.5元</td><td><a href="/day05/Test2?id=1">购买</a></td></tr>
<tr><td>《十万个为什么》</td><td>27元</td><td><a href="/day05/Test2?id=2">购买</a></td></tr>
<tr><td>《Java基础详解》</td><td>42元</td><td><a href="/day05/Test2?id=3">购买</a></td></tr>
<tr><td>《Android系统开发和移植》</td><td>59.5元</td><td><a href="/day05/Test2?id=4">购买</a></td></tr>
</table>
<br /><br />
<hr color="#CC00CC"/>
<center>
<h3>购物清单</h3><br />
<table align="center" bordercolor="red" border="1px">
<%
Map<String,Integer>map=(Map<String, Integer>) request.getSession().getAttribute("boo");
if(map!=null)
{
out.print("<tr><td>购买书目</td><td>数量</td><td>价格</td></tr>");
Map<String,Float>map2=(Map<String,Float>)request.getSession().getAttribute("pri");
Set keys=map.keySet();
Iterator it=keys.iterator();
float all=0;
while(it.hasNext())
{
String key=it.next()+"";
int num=map.get(key);
float price=map2.get(key);
float sum=num*price;
all=all+sum;
out.print("<tr><td>"+key+"</td><td>"+num+"</td><td>"+sum+"元</td></tr>");
}
out.print("<tr><td>总价</td><td colspan='2'>"+all+"元</td></tr>");
out.print("<tr><td colspan='3'><a href='/day05/Test4?id=Test1'>清除历史记录</a></td></tr>");
}
%>
</table>
</center>
<hr color="#CC0000">
</body>
</html>
附送清理历史记录~~~~
package Exercise;
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;
public class Test4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html;charset=utf-8");
String quary=request.getParameter("id");
//清理历史记录
//(1)清除session
HttpSession session = request.getSession();
if(session.getAttribute("boo")!=null)
{
session.removeAttribute("boo");
}
if(session.getAttribute("pri")!=null)
{
session.removeAttribute("pri");
}
if(session.getAttribute("map")!=null)
{
session.removeAttribute("map");
}
//(2)清除Cookie
Cookie[]cookies=request.getCookies();
for(Cookie cookie:cookies)
{
if(cookie.getName().equals("JSESSIONID"))
{
continue;
}
cookie.setMaxAge(0);
}
//(3)返回到原页面
response.sendRedirect( "/day05/jsp/"+quary+".jsp") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
12、浏览器禁用Cookie后的session处理
(1)实验演示禁用Cookie后servlet共享数据导致的问题。
(2)解决方案:URL重写
response. encodeRedirectURL(java.lang.String url)
用于对sendRedirect方法后的url地址进行重写。
response. encodeURL(java.lang.String url)
用于对表单action和超链接的url地址进行重写
(3)附加:
Session的失效
Web.xml文件配置session失效时间
如何设置 手动设置session的 过期时间
Session的生命周期
1、Session对象创建 : request.getSession() 执行时 (当前会话第一次执行)
2、session对象何时销毁?
浏览器如果关闭后,Session对象是不是就销毁了?
答案:不是,Session保存在服务器端,和浏览器是否关闭没有关系 ,关闭浏览器时删除会话cookie,丢失jsessionid,没有jsession无法找到服务器端对应Session
三种销毁Session对象情况:1、不正常关闭服务器(正常关闭服务器Session信息会被序列化到硬盘中 保存tomcat/work目录)
2、Session过期 默认过期时间在tomcat/conf/web.xml 配置
<session-config>
<session-timeout>30</session-timeout>
</session-config>
* 默认Session对象过期时间30分钟 (连续不使用Session对象时间)
* 也可以手动设置 setMaxInactiveInterval(int interval)
3、在程序中执行 session.invalidate() 手动销毁Session对象
问题:session.removeAttribute 和 session.invalidate区别 ?
session.removeAttribute 删除当前Session对象中一个属性值
session.invalidate 销毁当前Session对象,删除所有属性
13、session案例
利用Session实现一次性验证码用户登陆
(1)一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码。
(2)服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。
(3)密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。
<%@ 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>Insert title here</title>
</head>
<script type="text/javascript">
function changeimage(){
document.getElementById("myimage").src='/day05/image?'+new Date().getTime();
}
</script>
<body>
<h2 style="color: red">${message }</h2>
<hr>
<form action="/day05/login" method="post">
用户名:<input type="text" name="username"><br/>
用户名:<input type="password" name="password"><br/>
验证码:<input type="text" name="check_code">
<img src="/day05/image" style="cursor: pointer" onclick="changeimage();" id="myimage">
<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
<%@ 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>Insert title here</title>
</head>
<body>
欢迎您, ${username }
</body>
</html>
package cn.itheima.session;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// alt+ shift + r (rename)
public class CheckImageServlet extends HttpServlet {
private final static int WIDTH = 120;
private final static int HEIGHT = 30;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.在内存 中 构建 出 一张 图片 . // 屏幕上 能够 看到的 必须的 R,G,B , 所以要选择 TYPE_INT_RGB.
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 2. 给图片设置 一个 背景颜色 .
Graphics2D graphics = (Graphics2D) image.getGraphics();
// 状态机 , open gl ,
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, WIDTH, HEIGHT);
// 3. 画矩形的边框 .
graphics.setColor(Color.BLUE);
graphics.drawRect(0, 0, WIDTH-1, HEIGHT-1);
// 设置 字体的时候, 一定 要 要给 设置 一个 支持 中文 字符的 字体 名称, 否则, 就显示 不 了 , 乱码
graphics.setFont(new Font("黑体", Font.BOLD, 18));
// String base = "ABCDEFGHIJKLMNOPQ";
String base = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6";
Random random = new Random();
int m = 25 ;
StringBuffer sb = new StringBuffer();
// 4. 画 一些 字符 串 .
for (int i = 0; i < 4; i++) {
int index = random.nextInt(base.length());
char charAt = base.charAt(index);
graphics.setColor(Color.RED);
// -30 --- + 30
int jiaodu = random.nextInt(60) - 30;
double theta = jiaodu*Math.PI/180;
graphics.rotate(theta, m, 25);
graphics.drawString(charAt + "" , m, 20);
sb.append(charAt);
graphics.rotate(-theta, m, 25);
m += 25;
}
// 5. 画一些 干扰线.
for (int i = 0; i < 4; i++) {
graphics.setColor(Color.GREEN);
int x1 = random.nextInt(WIDTH);
int x2 = random.nextInt(WIDTH);
int y1 = random.nextInt(HEIGHT);
int y2 = random.nextInt(HEIGHT);
graphics.drawLine(x1, y1, x2, y2);
}
// 释放 资源 .
graphics.dispose();
request.getSession().setAttribute("checkcodes", sb.toString());
// 通过 imageio 类 将 构建出来的图片 , 写到 response 的 流中.
ImageIO.write(image, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package cn.itheima.session;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 解决 乱码 :
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String check_code = request.getParameter("check_code");
String checkcodes = (String) request.getSession().getAttribute("checkcodes");
System.out.println(checkcodes + "=============");
if(check_code ==null || !check_code.equals(checkcodes)){
request.setAttribute("message", "对不起, 你输入的 验证码 不正确 !!!");
request.getRequestDispatcher("/session/login.jsp").forward(request, response);
return;
}
// 进行 用户名 跟 密码的 校验
if(username == null || password ==null ){
request.setAttribute("message", "用户名或密码 为空");
request.getRequestDispatcher("/session/login.jsp").forward(request, response);
return;
}
if(username.equals("admin")&& password.equals("admin")){
request.getSession().setAttribute("username", username);
response.sendRedirect("/day05/session/welcome.jsp");
// request.getRequestDispatcher("/session/welcome.jsp").forward(request, response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
14、Servlet的数据访问范围
(1)application Scope servletContext (数据库连接池,配置, 线程池, 站点访问次数)
每一个Web应用对应一个ServletContext
存放所有用户都可以访问的数据
(2)session Scope HttpSession (存放与用户相关数据)
存放每个用户自己会话过程中的数据
(3)request Scope HttpServletRequest
(4)(Servlet处理结果,JSP显示)
数据存放在request对象中
生成新的请求时,原request存放数据丢失
(5)Servlet三种数据访问范围:ServletContext 、HttpSession、HttpServletRequest
1、保存ServletContext数据 ,在服务器关闭时才会删除,生命周期最长,全局都可以访问 (最少使用)
* 网站访问次数、全局数据库连接池 需要保存ServletContext
2、保存HttpSession数据 ,三种情况下丢失 ,主要保存用户相关数据 (不建议存放大规模数据)
* 用户登录信息、购物信息 保存HttpSession
3、保存HttpServletRequest,当前请求发生时产生,响应结束数据立刻释放 (生命周期最短,最建议使用)
* Servlet获得数据处理结果,通过请求转发 传递信息给JSP显示
(6)三种数据范围提供相同几个方法
setAttribute
getAttribute
removeAttribute
=====================================================================
内容小结:
1、Cookie和Session区别 ?
Cookie保存会话信息在客户端,Session保存会话信息在服务器端,Session基于Cookie实现的
2、Session安全吗?相对Cookie安全,不是绝对安全 ,jsessionid 可以伪装
* 二次验证必要性
3、浏览器关闭后,是不是Session对象就销毁了 ?
不是,Session保存在服务器端,关闭浏览器丢失jsessionid,无法找到服务器对应Session对象了,需要等到Session过期后才会销毁
4、禁用浏览器cookie后,Session还能否使用?
可以,URL重写
5、会话cookie和持久cookie区别 ?
会话cookie 保存浏览器内存缓存区中,关闭浏览器后,会话cookie就会删除
持久cookie 保存浏览器临时文件区 硬盘上,存在过期时间,当过期后会自动删除,通过设置maxage为0删除持久cookie
6、session的三种销毁原因?
服务器非正常关闭、session过期、invalidate
7、如何实现关闭浏览器再次打开,Session仍然可以访问?
将jsessionid 对应cookie 持久化
代码练习:记录站点上次访问时间、商品浏览记录、商品购物车、一次性验证码登陆