五扎狱、cookie & session

一琳猫、JSP

1. jsp的介紹

JSP全名為Java Server Pages伟叛,中文名叫java服務器頁面私痹,本質是一個簡化的Servlet設計脐嫂,它是由Sun Microsystems公司倡導、許多公司參與一起建立的一種動態(tài)網(wǎng)頁技術標準紊遵。JSP技術有點類似ASP技術账千,它是在傳統(tǒng)的網(wǎng)頁HTML文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP標記(tag),從而形成JSP文件暗膜,后綴名為(*.jsp)匀奏。 用JSP開發(fā)的Web應用是跨平臺的,既能在Linux下運行学搜,也能在其他操作系統(tǒng)上運行娃善。
它實現(xiàn)了Html語法中的java擴張(以 <%, %>形式)。JSP與Servlet一樣瑞佩,是在服務器端執(zhí)行的聚磺。通常返回給客戶端的就是一個HTML文本,因此客戶端只要有瀏覽器就能瀏覽炬丸。
jsp的作用:將內容的生成和顯示進行分離
用JSP技術瘫寝,Web頁面開發(fā)人員可以使用HTML或者XML標識來設計和格式化最終頁面,并使用JSP標識或者小腳本來生成頁面上的動態(tài)內容

2. jsp的原理

jsp的原理.png

上圖描述的是一個jsp頁面hello.jsp在服務器中處理的過程稠炬。
創(chuàng)建web工程day10,創(chuàng)建一個hello.jsp頁面焕阿。
1.在瀏覽器中輸入 http://localhost/day10/hello.jsp
2.服務器得到請求,會通過jsp引擎查找到hello.jsp頁面
3.服務器將查找到的hello.jsp頁面翻譯成hello_jsp.java(其本質就是一個servlet)
4.jvm會將hello_jsp.java文件編譯成hello_jsp.class
5.服務器運算hello_jsp.class文件
6.服務器生成響應結果

  • jsp對應java文件分析
    上述是我們對于一個jsp運行的原理的簡單分析首启,我們可以通過查看hello.jsp文件翻譯后的.java文件來了解具體內容暮屡,生成的hello.jsp頁面的java源文件存在于tomcat/work目錄 下。
    hello.jsp頁面源代碼
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>    
    <title>hello.jsp</title>
  </head>  
 <body>
    hello jsp
  </body>
</html>

hello_jsp.java文件源代碼

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;
public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=utf-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>    \r\n");
      out.write("    <title>hello.jsp</title>\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("    hello jsp\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

通過上面的內容毅桃,大家會發(fā)現(xiàn)在jsp頁面中的所有的html代碼褒纲,最終都會被流寫回到瀏覽器端,所以我們可以在瀏覽器上查看到jsp頁面上的html內容

3. jsp的腳本與注釋

  • jsp中三種腳本元素
    有三個基本的腳本元素疾嗅,作用是使JAVA代碼可以直接插入到HTML代碼中
    聲明標簽
    格式:<%! int a = 1; %>
    作用:聲明的變量在類的成員位置上
    腳本片斷
    格式:<% int a = 1; out.println(a); %>
    作用:內容會生成在_jspService()方法中
    腳本表達式
    格式:<%= "hello " + a %>
    作用:它就相當于是out.println()將內容直接輸出到頁面中外厂,注意表達式不能以分號結尾

  • jsp中的注釋
    在jsp頁面中可以使用三種注釋

可以使用html中注釋  
<!-- html的注釋  -->
可以對jsp腳本內容使用java注釋  //單行注釋  /* 多行注釋 */
可以使用jsp注釋(推薦)
<%--  jsp注釋  --%>

二.會話技術

會話的介紹:
會話可簡單理解為:用戶開一個瀏覽器,點擊多個超鏈接代承,訪問服務器多個web資源汁蝶,然后關閉瀏覽器,整個過程稱之為一個會話
會話的作用:
每個用戶與服務器進行交互的過程中,各自會有一些數(shù)據(jù)掖棉,程序要想辦法保存每個用戶的數(shù)據(jù)墓律。
例如:用戶點擊超鏈接通過一個servlet購買了一個商品,程序應該保存用戶購買的商品幔亥,以便于用戶點結帳servlet時耻讽,結帳servlet可以得到用戶商品為用戶結帳

會話技術會為兩類
Cookie
Cookie是客戶端技術,程序把每個用戶的數(shù)據(jù)以cookie的形式寫給用戶各自的瀏覽器帕棉。當用戶使用瀏覽器再去訪問服務器中的web資源時针肥,就會帶著各自的數(shù)據(jù)去。這樣香伴,web資源處理的就是用戶各自的數(shù)據(jù)了慰枕。

Session
Session是服務器端技術,利用這個技術即纲,服務器在運行時可以為每一個用戶的瀏覽器創(chuàng)建一個其獨享的session對象具帮,由于session為用戶瀏覽器獨享,所以用戶在訪問服務器的web資源時低斋,可以把各自的數(shù)據(jù)放在各自的session中蜂厅,當用戶再去訪問服務器中的其它web資源時,其它web資源再從用戶各自的session中取出數(shù)據(jù)為用戶服務膊畴。

三掘猿、cookie

1. cookie的介紹

Cookie最早是網(wǎng)景公司的前雇員Lou Montulli在1993年3月的發(fā)明。
Cookie是由服務器端生成巴比,發(fā)送給User-Agent(一般是瀏覽器)术奖,瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網(wǎng)站時就發(fā)送該Cookie給服務器(前提是瀏覽器設置為啟用cookie)轻绞。Cookie名稱和值可以由服務器端開發(fā)自己定義采记,對于JSP而言也可以直接寫入jsessionid,這樣服務器可以知道該用戶是否合法用戶以及是否需要重新登錄等政勃,服務器可以設置或讀取Cookies中包含信息唧龄,借此維護用戶跟服務器會話中的狀態(tài)。

cookie與http

  • cookie與http協(xié)議關系
    Cookie是Http協(xié)議制定的奸远,并不是Java語言獨有的既棺,PHT、.NET中也使用了cookie技術懒叛,因此只要是和HTTP協(xié)議相關丸冕,那么就可以使用cookie技術。
    我們知道cookie是服務器創(chuàng)建的一個鍵值對薛窥,并保存在瀏覽器端胖烛。那么服務器是如何將cookie發(fā)送給瀏覽器的呢?
    在服務器端先創(chuàng)建cookie眼姐,如 Cookie cookie=new Cookie(String name,String value),其中Cookie可以在javaeeAPI中查到的佩番,詳情可參考java_ee API众旗。然后再通過response對象將cookie信息作為響應頭發(fā)送到瀏覽器端。我們可以通過HttpWatch抓包工具查看響應信息趟畏,可以發(fā)現(xiàn)cookie是基于一個Set-Cookie響應頭工作的贡歧,由于Set-Cookie響應頭可以有多個,所以我們可以通過response.addHeader(String name,String value)方法發(fā)送Set-Cookie響應頭赋秀,例如利朵,有兩個cookie,分別為one=aaa沃琅,two=bbb哗咆,其中one、two是cookie的名稱益眉,aaa、bbb是cookie的值姥份。發(fā)送響應頭如下所示:
    response.addHeader(“Set-Cookie”,”one=aaa”)郭脂;
    response.addHeader(“Set-Cookie”,”two=bbb”);
    當瀏覽器再次訪問服務器時澈歉,會將cookie送還給服務器展鸡。那么瀏覽器是如何將cookie帶給服務器的呢?其實通過Cookie請求頭傳遞過去的。請求頭Cookie與響應頭Set-Cookie有區(qū)別埃难,多個cookie對應多個Set-Cookie響應頭莹弊,但是只對應一個Cookie請求頭,格式為:Cookie:one=aaa涡尘; two=bbb忍弛。即多個cookie之間用分號和空格隔開。
    需要注意的是:cookie是不能跨瀏覽器的考抄。例如细疚,張三首先使用IE瀏覽器訪問服務器,服務器發(fā)送了一個cookie川梅,這個cookie只會保存在IE瀏覽器疯兼,如果再使用火狐瀏覽器訪問服務器,服務器會再發(fā)送一個cookie個火狐瀏覽器贫途,在火狐瀏覽器中不能獲取IE瀏覽器中的cookie吧彪,同理IE瀏覽器也獲取不到火狐瀏覽器中的cookie。

  • http協(xié)議規(guī)定
    Http協(xié)議對Cookie做了一些規(guī)定丢早,如下所示:
    a. 一個Cookie的大小姨裸,最大為4KB;
    b. 一個服務器最多向一個瀏覽器保存20個Cookie;
    c. 一個瀏覽器最多可以保存300個Cookie啦扬。
    我們知道中狂,瀏覽器將服務器發(fā)送過來的cookie保存在本地磁盤,如果cookie過多扑毡,必然會加大瀏覽器的壓力胃榕,因此Http協(xié)議對Cookie做了以上規(guī)定。
    但是瞄摊,目前瀏覽器之間因為競爭勋又,很多都在一定范圍內違反了Http規(guī)定,例如换帜,一個瀏覽器最多保存的Cookie個數(shù)超過300個楔壤。但是也不會出現(xiàn)瀏覽器允許一個Cookie的大小超過4GB。

2. cookie常用api及其原理

javax.servlet.http.Cookie類用于創(chuàng)建一個Cookie惯驼,response接口也中定義了一個addCookie方法蹲嚣,它用于在其響應頭中增加一個相應的Set-Cookie頭字段。 同樣祟牲,request接口中也定義了一個getCookies方法隙畜,它用于獲取客戶端提交的Cookie。
構造方法
public Cookie(String name, String value):構造帶指定名稱和值的 cookie说贝。
成員方法
public String getName():返回 cookie 的名稱
public String getValue():返回 cookie 的值议惰。
public void setMaxAge(int expiry):設置 cookie 的最大生存時間,以秒為單位
public void setPath(String uri):指定客戶端應該返回 cookie 的路徑乡恕。
接下來,咱們來做個案例看下cookie是如何使用的.
在day10工程下創(chuàng)建一個CookieDemo1Servlet,寫入以下代碼:
//1.創(chuàng)建cookie
Cookie cookie=new Cookie("cookieName","cookieValue");
//2.通過response對象將cookie響應到瀏覽器
response.addCookie(cookie);

然后通過抓包工具看下:
當在瀏覽器上訪問http://localhost/day10/cookieDemo1時,抓取到的http請求與響應信息如下:
請求信息:

GET /day10/cookieDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive

響應信息

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: cookieName=cookieValue
Content-Length: 0
Date: Tue, 12 May 2015 05:26:53 GMT

再次訪問此頁面
請求信息:

GET /day10/cookieDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
Cookie: cookieName=cookieValue

通過以上分析言询,我們通過下面圖進行總結:


ckkoie原理.png

3. cookie的持久化

持久化
如果創(chuàng)建了一個cookie,并將他發(fā)送到瀏覽器傲宜,默認情況下它是一個會話級別的cookie(即存儲在瀏覽器的內存中)运杭,用戶退出瀏覽器之后即被刪除。若希望瀏覽器將該cookie存儲在磁盤上蛋哭,則需要使用Cookie類的setMaxAge方法县习,并給出一個以秒為單位的時間。
0代表的是刪除持久cookie谆趾,注意躁愿,刪除cookie時,path必須一致沪蓬,否則不會刪除
-1代表的是瀏覽器關閉后失效.

路徑:
Cookie的路徑是在服務器創(chuàng)建Cookie時設置的彤钟,它的作用是決定瀏覽器訪問服務器的某個資源時,需要將瀏覽器端保存的那些Cookie歸還給服務器跷叉,可以通過Cookie類的setPath方法來設置cookie的路徑.
關于路徑包含關系
例如逸雹,瀏覽器中保存如下幾個cookie营搅,它們的路徑分別是:
aCookie.path=/day10/
bCookie.path=/day10/jsps/
cCookie.path=/day10/jsps/cookie/
訪問路徑是:http://localhost:8080/day10/index.jsp
瀏覽器發(fā)送給服務器的cookie有:aCookie;
訪問路徑是:http://localhost:8080/day10/jsps/a.jsp
瀏覽器發(fā)送給服務器的cookie有:aCookie梆砸,bCookie转质;
訪問路徑是:http://localhost:8080/day10/jsps/cookie/b.jsp
瀏覽器發(fā)送給服務器的cookie有:aCookie,bCookie帖世,cCookie休蟹。

4. 案例--記錄上次訪問時間

案例分析


記錄上次訪問時間.png

使用到的知識點分析
Cookie cookie=new Cookie(); 創(chuàng)建cookie
response.addCookie() 將cookie添加到http響應中
request.getCookies(); 獲取所有的cookie

代碼實現(xiàn)

public class ShowCurrentTimeServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    / 1.設置響應編碼
    response.setContentType("text/html;charset=utf-8");

    / 2.獲取一個名稱叫time的cookie.
    Cookie cookie = findCookieByName("time", request.getCookies());
    Date now = new Date();
    if (cookie == null) {
        / 說明第一次訪問
        response.getWriter().write("第一次訪問時間是:" + now.toLocaleString());
    } else {
        / 不是第一次訪問
        long time = Long.parseLong(cookie.getValue());
        response.getWriter().write("上次訪問時間是:" + new Date(time).toLocaleString());
    }

    / 需要將這時訪問的時間存儲到cookie中。
    cookie = new Cookie("time", now.getTime() + "");
    /持久化cookie
    /cookie.setMaxAge(60*60*24*7);
    cookie.setMaxAge(0);/刪除cookie
    response.addCookie(cookie);

}

/ 根據(jù)名稱查找cookie
private Cookie findCookieByName(String name, Cookie[] cs) {
    if (cs == null || cs.length == 0) {
        return null;
    }
    for (Cookie c : cs) {
        if (name.equals(c.getName())) {
            return c;
        }
    }
    return null;
}
}

5. 案例--查看歷史記錄

查看歷史記錄.png

使用到的知識點分析
超連接帶參數(shù) <a href=”/day10/book?id=1”>
獲取請求參數(shù) request.getParameter()
創(chuàng)建Cookie cookie=new Cookie()
獲取所有cookie request.getCookies()
將cookie響應到瀏覽器端 response.addCookies()

代碼實現(xiàn)
book.jsp

<a href="/day10/book?id=1">西游記</a><br>
<a href="/day10/book?id=2">水滸傳</a><br>
<a href="/day10/book?id=3">紅樓夢</a><br>
<a href="/day10/book?id=4">三國演義</a><br>
<hr>
<a href="/day10/bookHistory.jsp">查看瀏覽商品記錄</a>

BookServlet

public class BookServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    / 1.得到商品的id
    String id = request.getParameter("id");

    / 2.將id值保存到cookie的名稱叫ids這個cookie中日矫。
    Cookie cookie = CookieUtils.findCookieByName("ids",
            request.getCookies());

    if (cookie == null) { / 第一次沒有ids,就得到null
        cookie = new Cookie("ids", id);
    } else { / 不是第一次赂弓,就得到的不是null.
                / 3.得到cookie的value值。
        String ids = cookie.getValue();

        / 判斷id是否重復
        List<String> list = Arrays.asList(ids.split("-")); /將數(shù)組轉換成集合哪轿。

        if (!list.contains(id)) {
            ids = ids + "-" + id;
        }
        cookie = new Cookie("ids", ids);

    }

    response.addCookie(cookie);
    response.getWriter().write("商品展示成功,<a href='/day10/book.jsp'>繼續(xù)瀏覽</a>");
}
}

bookHistory.jsp

<%
        String[] books = { "西游記", "水滸傳", "紅樓夢", "三國演義" };

        /1.得到所有的cookie盈魁,得到名稱叫ids的cookie
        Cookie[] cs = request.getCookies();
        Cookie c = CookieUtils.findCookieByName("ids", cs);

        if (c == null) {
            /沒有瀏覽記錄
            out.print("無瀏覽記錄");
        } else {
            /有瀏覽記錄
            /2.得到cookie的value
            out.print("瀏覽記錄如下:<br>");
            String ids = c.getValue(); /1-2-4

            String[] id = ids.split("-");

            for (int i = 0; i < id.length; i++) {
                int bookid = Integer.parseInt(id[i]) - 1;
                out.print(books[bookid] + "<br>");
            }

        }
%>

四.session

1. session的介紹

首先,HttpSession是javax.servlet.http包下的一個接口窃诉。從名字來看杨耙,我們可以知道HttpSession與Http協(xié)議有一定的關系,但是它并不是由Http協(xié)議定義的褐奴,而是由Javaweb提供按脚。我們可以在JavaEE api中查看它的詳細信息。
其次敦冬,HttpSession是用來進行會話跟蹤的接口,我們之前也學過另外一個與會話相關的技術Cookie唯沮。在Cookie介紹中我們了解到脖旱,Cookie是由Http協(xié)議制定的,在請求信息和響應信息中分別對應了Cookie請求頭和Set-Cookie響應頭介蛉,并且Cookie是由服務器創(chuàng)建萌庆,保存在客戶端。而HttpSession對象也是由服務器創(chuàng)建币旧,但是與Cookie不同的是践险,它保存在服務器端。
HttpSession對象是Servlet的三大域對象之一吹菱,其他兩個域對象是HttpServletRequest和ServletContext巍虫。這三個域中,request的域范圍最小鳍刷,它的域范圍是整個請求鏈占遥,并且只在請求轉發(fā)和包含時存在;session域對象的域范圍是一次會話输瓜,而在一次會話中會產(chǎn)生多次請求瓦胎,因此session的域范圍要比request大芬萍;application的域范圍是最大的,因為一個web應用只有唯一的一個application對象搔啊,只有當web應用被移出服務器或服務器關閉它才死亡柬祠,它的域范圍是整個應用。

2. session常用api,生命周期及其原理

session底層是依賴Cookie的负芋,如果瀏覽器禁用Cookie則session會依賴URL重寫漫蛔。詳情我們會在后面介紹。如何獲取HttpSession對象?在服務器端示罗,例如在Servlet中惩猫,我們通過request對象的getSession()方法獲取服務器為當前用戶創(chuàng)建的session對象,即:HttpSession session=request.getSession()蚜点。而在jsp中轧房,session是jsp的內置對象,不用獲取就可以直接使用绍绘。

session的常用api
我們知道每一個域對象都會有以下三個方法奶镶,HttpSession也不例外:
void setAttribute(String name,Object value):向域中添加域屬性;
Object getAttribute(String name):從域中獲取指定名稱的屬性值陪拘;
Void removeAttribute(String name):移出域中指定名稱的域屬性

接下來,咱們來做個案例看下session是如何使用的.
在day10工程下創(chuàng)建一個SessionDemo1Servlet,寫入以下代碼:

/ 1.獲取session
HttpSession session = request.getSession();
/ 2.向session中存儲數(shù)據(jù)據(jù)
session.setAttribute("name", "tom");

在day10工程下創(chuàng)建一個SessionDemo2Servlet,寫入以下代碼:

/ 1.獲取session
HttpSession session = request.getSession();
/ 2.獲取session中信息
String name = (String) session.getAttribute("name");
System.out.println(name);

接下來使用抓包工具看下:
打開瀏覽器訪問http:/localhost/day10/sessionDemo1
請求信息:

GET /day10/sessionDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive

響應信息:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=2021FCEFDF31A6DAC8E7CC201F7AF404; Path=/day10/; HttpOnly
Content-Length: 0
Date: Tue, 12 May 2015 21:58:39 GMT

再次訪問http:/localhost/day10/sessionDemo2:

請求信息:

GET /day10/sessionDemo2 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
Cookie: JSESSIONID=2021FCEFDF31A6DAC8E7CC201F7AF404

響應信息

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Tue, 12 May 2015 22:00:46 GMT

session對象的創(chuàng)建分析
如果請求時傅是,cookie中有jsessionid這個cookie,那么我們通過request.getSession()時稠鼻,
就會根據(jù)jsessionid值查找session的id,如果查找到刃滓,會使用已有的,如果沒有查找到欠痴,會創(chuàng)建迄靠。
如果請求時,cookie中沒有jsessionid這個cookie,那么request.getSession()就會創(chuàng)建一個新的session對象.

session對象的銷毀分析
瀏覽器關閉了喇辽,session對象不會銷毀的掌挚,session的銷毀與關閉瀏覽器無關.
session對象銷毀方式:
1.關閉服務器
2.默認超時
在tomcat/conf/web.xml文件中設置了session默認超時時間
<session-config>
<session-timeout>30</session-timeout>
</session-config>
默認30分鐘超時
3.可以設置session超時時間(以秒為單位)
void setMaxInactiveInterval(int interval)
4.銷毀session
invalidate();

session的原理

session的原理.png

第一次訪問,請求中不存在jsessionid值,這時發(fā)送請求到服務器端就會創(chuàng)建HttpSession對象.工將session的id值存儲到cookie中響應到瀏覽器端
當下一次在請求時菩咨,這時會在請求中存在jsessionid值,到服務器端后吠式,就會根據(jù)jsessionid值,查找指定id的session對象抽米。
如果查找到特占,就直接使用,而不會重新創(chuàng)建缨硝。如果沒有查找到摩钙,會重新創(chuàng)建.
HttpSession session=request.getSession();
擴展
HttpSession session=request.getSession(true/false);
如果值是true與無參數(shù)一樣.
如果是false,它不會重新創(chuàng)建session對象,會返回null值胖笛。(用的很少)

3. 案例--購物車

案例--購物車.png

使用到的知識點分析
購物車使用的數(shù)據(jù)結構 Map<String,Integer>
獲取session request.getSession()
解決請求參數(shù)亂碼 new String(name.getBytes(“iso8859-1”),”utf-8”)

Productlist.jsp

<table border='1' width="65%" align="center">
        <tr>
            <td>商品名稱</td>
            <td>操作</td>
        </tr>
        <tr>
            <td>洗衣機</td>
            <td><a href="/day10/addProductToCart?name=洗衣機">添加到購物車</a></td>
        </tr>
        <tr>
            <td>電視機</td>
            <td><a href="/day10/addProductToCart?name=電視機">添加到購物車</a></td>
        </tr>
        <tr>
            <td>縫紉機</td>
            <td><a href="/day10/addProductToCart?name=縫紉機">添加到購物車</a></td>
        </tr>
        <tr>
            <td>打火機</td>
            <td><a href="/day10/addProductToCart?name=打火機">添加到購物車</a></td>
        </tr>
        
    </table>

AddProductToCartServlet

public class AddProductToCartServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        
        / 1.獲取商品名稱
        String name = request.getParameter("name");
        / 2.解決亂碼
        name = new String(name.getBytes("iso8859-1"), "utf-8");
        / 3.獲取購物車
        HttpSession session = request.getSession();
        Map<String, Integer> cart = (Map<String, Integer>) session
                .getAttribute("cart");

        / 4.判斷購物車是否存在
        Integer count = null; /代表的是商品數(shù)量
        if (cart == null) {
            cart = new HashMap<String, Integer>();
            / cart.put(name, 1);
            count = 1;
        } else {
            / 如果購物車存在阱佛,我們需要考慮商品在購物車中是否存在。
            count = cart.get(name);
            if (count == null) {
                / 說明購物車中無此商品
                count = 1;
            } else {
                / 如果有此商品,將數(shù)量加1
                count += 1;
            }

        }
        cart.put(name, count);
        / 5.將購物車存儲到session中.
        session.setAttribute("cart", cart);
        
        response.getWriter().write("添加成功,<a href='/day10/productlist.jsp'>繼續(xù)購物</a>,<a href='/day10/cart.jsp'>查看購物車</a>");

    }
}

cart.jsp

<table border='1' align="center" width="65%">

        <tr>
            <td>商品名稱</td>
            <td>商品數(shù)量</td>
        </tr>

        <%
            /1.得到session
            HttpSession mysession = request.getSession();

            /2.得到購物車
            Map<String, Integer> cart = (Map<String, Integer>) mysession
                    .getAttribute("cart");

            /3.判斷購物車是否存在
            if (cart == null || cart.size() == 0) {
                out.print("購物車中無商品<br>");
            } else {
                /4.遍歷cart
                for (String name : cart.keySet()) {

                    out.print("<tr><td>" + name + "</td><td>" + cart.get(name)
                            + "</td></tr>");

                }
            }
        %>

    </table>

4. url重寫

url重寫介紹
如果瀏覽器不支持Cookie或用戶阻止了所有Cookie舶治,可以把會話ID附加在HTML頁面中所有的URL上诈唬,這些頁面作為響應發(fā)送給客戶杭朱。這樣,當用戶單擊URL時界轩,會話ID被自動作為請求頭的一部分而不是作為頭行發(fā)送回服務器热鞍。這種方法稱為URL重寫(URL rewriting)。

url重寫作用
當客戶機不接受cookie時慢睡,server就使用URL重寫作為會話跟蹤的基本方式.URL重寫,添加了附加數(shù)據(jù)(會話ID)到請求的URL路徑上.
會話ID必須被編碼作為該URL字符串中的路徑參數(shù)纬纪。該參數(shù)的名稱為jsessionid,
簡單說就是cookie禁用了jsessionid就不能攜帶问畅,那么每次請求卵皂,都是一個新的session對象捅膘。
如果想要使用同一個session對象,可以使用url重寫.

url重寫實現(xiàn)
response. encodeRedirectURL(java.lang.String url)
用于對sendRedirect方法后的url地址進行重寫族阅。
response. encodeURL(java.lang.String url)
用于對表單action和超鏈接的url地址進行重寫

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末篓跛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坦刀,更是在濱河造成了極大的恐慌愧沟,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲤遥,死亡現(xiàn)場離奇詭異沐寺,居然都是意外死亡,警方通過查閱死者的電腦和手機盖奈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門混坞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人钢坦,你說我怎么就攤上這事究孕。” “怎么了爹凹?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵厨诸,是天一觀的道長。 經(jīng)常有香客問我禾酱,道長微酬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任颤陶,我火速辦了婚禮颗管,結果婚禮上,老公的妹妹穿的比我還像新娘滓走。我一直安慰自己垦江,他們只是感情好,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布搅方。 她就那樣靜靜地躺著疫粥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腰懂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天项秉,我揣著相機與錄音绣溜,去河邊找鬼。 笑死娄蔼,一個胖子當著我的面吹牛怖喻,可吹牛的內容都是我干的底哗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锚沸,長吁一口氣:“原來是場噩夢啊……” “哼跋选!你這毒婦竟也來了?” 一聲冷哼從身側響起哗蜈,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤前标,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后距潘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炼列,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年音比,在試婚紗的時候發(fā)現(xiàn)自己被綠了俭尖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡洞翩,死狀恐怖稽犁,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情骚亿,我是刑警寧澤已亥,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站循未,受9級特大地震影響陷猫,放射性物質發(fā)生泄漏。R本人自食惡果不足惜的妖,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一绣檬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嫂粟,春花似錦娇未、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宽涌,卻和暖如春平夜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卸亮。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工忽妒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓段直,卻偏偏與公主長得像吃溅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鸯檬,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容