Cookie:
Cookie是客戶端技術(shù)双谆,程序把每個用戶的數(shù)據(jù)以cookie的形式寫給用戶各自的瀏覽器狸捅。當(dāng)用戶使用瀏覽器再去訪問服務(wù)器中的web資源時偎巢,就會帶著各自的數(shù)據(jù)去微王。這樣屡限,web資源處理的就是用戶各自的數(shù)據(jù)了。
Session:
Session是服務(wù)器端技術(shù)骂远,利用這個技術(shù)囚霸,服務(wù)器在運行時可以為每一個用戶的瀏覽器創(chuàng)建一個其獨享的session對象,由于session為用戶瀏覽器獨享激才,所以用戶在訪問服務(wù)器的web資源時拓型,可以把各自的數(shù)據(jù)放在各自的session中,當(dāng)用戶再去訪問服務(wù)器中的其它web資源時瘸恼,其它web資源再從用戶各自的session中取出數(shù)據(jù)為用戶服務(wù)劣挫。
1.javax.servlet.http.Cookie
Java提供操作Cookie的API
1.1 演示Cookie的創(chuàng)建與使用
public class CookieDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.創(chuàng)建Cookie對象
Cookie cookie1 = new Cookie("name","eric");
/**
* 1)設(shè)置cookie的有效路徑。默認情況:有效路徑在當(dāng)前web應(yīng)用下东帅。 /demo
*有效路徑指的是cookie的有效路徑保存在哪里压固,那么瀏覽器在有效路徑下
*訪問服務(wù)器時就會帶著cookie信息,否則不帶cookie信息靠闭。
*/
//cookie1.setPath("/demo");
/**
* 2)設(shè)置cookie的有效時間
* 正整數(shù):表示cookie數(shù)據(jù)保存瀏覽器的緩存目錄(硬盤中)帐我,數(shù)值表示保存的時間。
負整數(shù):表示cookie數(shù)據(jù)保存瀏覽器的內(nèi)存中愧膀。瀏覽器關(guān)閉cookie就丟失了@辜!
零:表示刪除同名的cookie數(shù)據(jù)
*/
//cookie1.setMaxAge(20); //20秒檩淋,從最后不調(diào)用cookie開始計算
cookie1.setMaxAge(-1); //cookie保存在瀏覽器內(nèi)存(會話cookie)
//cookie1.setMaxAge(0);
//2.把cookie數(shù)據(jù)發(fā)送到瀏覽器(通過響應(yīng)頭發(fā)送: set-cookie名稱)
//response.setHeader("set-cookie", cookie.getName()+"="+cookie.getValue()+",email=eric@qq.com");
//推薦使用這種方法芬为,避免手動發(fā)送cookie信息
response.addCookie(cookie1);
//3.接收瀏覽器發(fā)送的cookie信息
/*String name = request.getHeader("cookie");
System.out.println(name);*/
Cookie[] cookies = request.getCookies();
//注意:判斷null,否則空指針
if(cookies!=null){
//遍歷
for(Cookie c:cookies){
String name = c.getName();
String value = c.getValue();
System.out.println(name+"="+value);
}
}else{
System.out.println("沒有接收cookie數(shù)據(jù)");
}
}
}
1.2. Cookie的使用實例,用戶上次訪問時間
public class HistServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 獲取當(dāng)前時間
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String curTime = format.format(new Date());
// 取得cookie
Cookie[] cookies = request.getCookies();
String lastTime = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("lastTime")) {
// 有l(wèi)astTime的cookie,已經(jīng)是第n次訪問
lastTime = cookie.getValue();// 上次訪問的時間
// 第n次訪問
// 1.把上次顯示時間顯示到瀏覽器
response.getWriter().write(
"歡迎回來媚朦,你上次訪問的時間為:" + lastTime + ",當(dāng)前時間為:" + curTime);
// 2.更新cookie
cookie.setValue(curTime);
cookie.setMaxAge(1 * 30 * 24 * 60 * 60);
// 3.把更新后的cookie發(fā)送到瀏覽器
response.addCookie(cookie);
break;
}
}
}
/**
* 第一次訪問(沒有cookie 或 有cookie氧敢,但沒有名為lastTime的cookie)
*/
if (cookies == null || lastTime == null) {
// 1.顯示當(dāng)前時間到瀏覽器
response.getWriter().write("你是首次訪問本網(wǎng)站,當(dāng)前時間為:" + curTime);
// 2.創(chuàng)建Cookie對象
Cookie cookie = new Cookie("lastTime", curTime);
cookie.setPath("/CookieDemo");
cookie.setMaxAge(-1);// 設(shè)置瀏覽器關(guān)閉cookie就丟失
// cookie.setMaxAge(1*30*24*60*60);//保存一個月
// 3.把cookie發(fā)送到瀏覽器保存
response.addCookie(cookie);
}
}
}
效果如下:
注意:瀏覽器一般只允許存放300個Cookie,每個站點最多存放20個Cookie半火,每個Cookie的大小限制為4KB越妈。
2. javax.servlet.http.HttpSession
Java提供操作Session的API,服務(wù)器在瀏覽器第一次訪問時如果創(chuàng)建了一個Session對象就會給該對象分配一個id并以Cookie的形式保存在瀏覽器中,以后在有效期內(nèi)瀏覽器訪問服務(wù)器時就會帶著該id,服務(wù)器通過該id就能匹配到存儲在服務(wù)器中對應(yīng)的信息钮糖。
2.1 Sesision的存儲原理
Demo:
public class SessionDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF=8");
response.setContentType("text/html;charset=UTF-8");
// 使用request對象的getSession()獲取session梅掠,如果session不存在則創(chuàng)建一個
HttpSession session = request.getSession();
// 將數(shù)據(jù)存儲到session中
session.setAttribute("data", "acamy");
// 獲取session的Id
String sessionId = session.getId();
// 判斷session是不是新創(chuàng)建的
response.getWriter().println(new Date());
if (session.isNew()) {
response.getWriter().print("session創(chuàng)建成功,session的id是:" + sessionId);
} else {
response.getWriter().print(
"服務(wù)器已經(jīng)存在該session了店归,session的id是:" + sessionId);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
效果如下:
2.2.瀏覽器禁用Cookie后的session處理
當(dāng)我們想實現(xiàn)提供用戶瀏覽過的商品時,利用上面的Cookie和Session思想很容易實現(xiàn)秩伞,但是如果瀏覽器作了上圖中的設(shè)置逞带,也就是禁用了Cookie,我們又該如何實現(xiàn)呢,這就需要用到URL重寫:
用于對sendRedirect方法后的url地址進行重寫纱新。
**response.encodeRedirectURL(java.lang.String url) **
//用于對表單action和超鏈接的url地址進行重寫
response.encodeURL(java.lang.String url)
String javax.servlet.http.HttpServletResponse.encodeURL(String url)
Encodes the specified URL by including the session ID in it, or, if encoding is not needed, returns the URL unchanged. The implementation of this method includes the logic to determine whether the session ID needs to be encoded in the URL. For example, if the browser supports cookies, or session tracking is turned off, URL encoding is unnecessary.
看了上面官方對該方法的解釋就是對特定的URL添加session ID進行編碼展氓,如果不需要的話就不會對URL作任何改變。所有對該方法的實現(xiàn)應(yīng)該包含判斷session ID的信息是否需要添加到URL里面對URL作改變的邏輯脸爱。例如遇汞,如果瀏覽器支持cookies,或者session跟蹤關(guān)了的話,就不對URL作改變簿废。
下面看實例源碼:
IndexServlet:首頁空入,列出所有書
public class IndexServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 創(chuàng)建Session
request.getSession();
out.write("本網(wǎng)站有如下書:<br/>");
Set<Map.Entry<String, Book>> set = DB.getAll().entrySet();
for (Map.Entry<String, Book> me : set) {
Book book = me.getValue();
String url = request.getContextPath() + "/buyServlet?id="
+ book.getId();
// response. encodeURL(java.lang.String
// url)用于對表單action和超鏈接的url地址進行重寫,通過此方法帶上JSESSSIONID
url = response.encodeURL(url);// 將超鏈接的url地址進行重寫
out.println(book.getName() + " <a href='" + url + "'>購買</a><br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
/**
* @author gacl 模擬數(shù)據(jù)庫
*/
class DB {
private static Map<String, Book> map = new LinkedHashMap<String, Book>();
static {
map.put("1", new Book("1", "javaweb開發(fā)"));
map.put("2", new Book("2", "spring開發(fā)"));
map.put("3", new Book("3", "hibernate開發(fā)"));
map.put("4", new Book("4", "struts開發(fā)"));
map.put("5", new Book("5", "ajax開發(fā)"));
}
public static Map<String, Book> getAll() {
return map;
}
}
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;
}
}
BuyServlet:點擊購買后的邏輯
public class BuyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
Book book = DB.getAll().get(id); // 得到用戶想買的書
HttpSession session = request.getSession();
HashSet<Book> set = (HashSet) session.getAttribute("set"); // 得到用戶用于保存所有書的容器
if (set == null) {
set = new HashSet<Book>();
session.setAttribute("set", set);
}
set.add(book);
// response. encodeRedirectURL(java.lang.String
// url)用于對sendRedirect方法后的url地址進行重寫
String url = request.getContextPath() + "/listCartServlet";
url = response.encodeRedirectURL(url);//通過此方法帶上JSESSSIONID
System.out.println(url);
response.sendRedirect(url);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ListCartServlet:購物車頁面
public class ListCartServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
HashSet<Book> set = (HashSet) session.getAttribute("set");
if (set == null || set.size() == 0) {
out.write("對不起族檬,您還沒有購買任何商品!!");
return;
}
// 顯示用戶買過的商品
out.write("您買過如下商品:<br>");
for (Book book : set) {
out.write(book.getName() + "<br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
查看首頁源碼如下:
但當(dāng)我們刷新列表頁時會發(fā)現(xiàn)URL里面帶的JSESSSIONID已經(jīng)改變,購物車頁面也會清空看尼,所以并不能實現(xiàn)完全沒禁用Cookie效果递鹉。
當(dāng)我們開啟Cookie時,只有在第一次訪問列表頁面時會有JSESSSIONID的信息,但我們刷新列表頁面時藏斩,購物車頁面沒有清空躏结,頁面源碼如下所示,沒有了JSESSSIONID的信息狰域,證明了encode方法的智能性媳拴。
2.3 session對象的銷毀時機
session對象默認30分鐘沒有使用,則服務(wù)器會自動銷毀session兆览,在web.xml文件中可以手工配置session的失效時間屈溉,例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 設(shè)置Session的有效時間:以分鐘為單位-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
當(dāng)需要在程序中手動設(shè)置Session失效時,可以手工調(diào)用session.invalidate方法抬探,摧毀session子巾。
HttpSession session = request.getSession();
//手工調(diào)用session.invalidate方法,摧毀session
session.invalidate();