JSP知識總結

day11

JSP入門

 

1 JSP概述

1.1 什麼是JSPjavascript

JSP(Java Server Pages)是JavaWeb服務器端的動態資源。它與html頁面的做用是相同的,顯示數據和獲取數據html

 

1.2 JSP的組成java

  JSP = html + Java腳本(代碼片斷) + JSP動態標籤web

 

 

2 JSP語法

 

2.1 JSP腳本數據庫

JSP腳本就是Java代碼片斷,它分爲三種:c#

l  <%...%>:Java語句;windows

l  <%=…%>:Java表達式;瀏覽器

l  <%!...%>:Java定義類成員;緩存

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>服務器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>JSP演示</title>

  </head>

 

  <body>

    <h1>JSP演示</h1>

    <%

    // Java語句

    String s1 = "hello jsp";

    // 不會輸出到客戶端,而是在服務器端的控制檯打印

    System.out.println(s1);

    %>

  <!-- 輸出到客戶端瀏覽器上 -->

    輸出變量:<%=s1 %><br/>

    輸出int類型常量:<%=100 %><br/>

    輸出String類型常量:<%="你好" %><br/>

    <br/>

    使用表達式輸出常量是很傻的一件事,由於能夠直接使用html便可,下面是輸出上面的常量:<br/>

    100<br/>

    你好   

  </body>

</html>

 

2.2 內置對象out

out對象在JSP頁面中無需建立就可使用,它的做用是用來向客戶端輸出。

  <body>

    <h1>out.jsp</h1>

    <%

       //向客戶端輸出

       out.print("你好!");

    %>

  </body>

 

其中<%=…%>與out.print()功能是相同的!它們都是向客戶端輸出,例如:

<%=s1%>等同於<% out.print(s1); %>

<%=」hello」%>等同於<% out.print(「hello」); %>,也等同於直接在頁面中寫hello同樣。

 

2.3 多個<%...%>能夠通用

在一個JSP中多個<%...%>是相通的。例如:

  <body>

    <h1>out.jsp</h1>

    <%

       String s = "hello";

    %>

    <%

       out.print(s);

    %>

  </body>

 

循環打印表格:

  <body>

    <h1>表格</h1>

   

    <table border="1" width="50%">

       <tr>

           <th>序號</th>

           <th>用戶名</th>

           <th>密碼</th>

       </tr>

    <%

       for(int i = 0; i < 10; i++) {  

    %>

       <tr>

           <td><%=i+1 %></td>

           <td>user<%=i %></td>

           <td><%=100 + 1 %></td>

       </tr>

    <%

       }

    %>

    </table>

  </body>

 

3 JSP的原理

 

3.1 JSP是特殊的Servlet

  JSP是一種特殊的Servlet,當JSP頁面首次被訪問時,容器(Tomcat)會先把JSP編譯成Servlet,而後再去執行Servlet。因此JSP其實就是一個Servlet!

 

 

3.2 JSP真身存放目錄

JSP生成的Servlet存放在${CATALANA}/work目錄下,我常常開玩笑的說,它是JSP的「真身」。咱們打開看看其中的內容,瞭解一下JSP的「真身」。

你會發現,在JSP中的靜態信息(例如<html>等)在「真身」中都是使用out.write()完成打印!這些靜態信息都是做爲字符串輸出給了客戶端。

 

JSP的整篇內容都會放到名爲_jspService的方法中!你可能會說<@page>不在「真身」中,<%@page>咱們明天再講。

 

a_jsp.java的_jspService()方法:

  public void _jspService(final javax.servlet.http.HttpServletRequest request[崔1] ,

final javax.servlet.http.HttpServletResponse response[崔2] )

        throws java.io.IOException, javax.servlet.ServletException {

 

    final javax.servlet.jsp.PageContext pageContext[崔3] ;

    javax.servlet.http.HttpSession session [崔4] = null;

    final javax.servlet.ServletContext application[崔5] ;

    final javax.servlet.ServletConfig config[崔6] ;

    javax.servlet.jsp.JspWriter out [崔7] = null;

    final java.lang.Object page [崔8] = 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;

 

[崔9] 

}

 

4 再論JSP腳本

JSP腳本一共三種形式:

l  <%...%>:內容會直接放到「真身」中;

l  <%=…%>:內容會放到out.print()中,做爲out.print()的參數;

l  <%!…%>:內容會放到_jspService()方法以外,被類直接包含;

 

前面已經講解了<%...%>和<%=…%>,但尚未講解<%!...%>的做用!

如今咱們已經知道了,JSP其實就是一個類,一個Servlet類。<%!...%>的做用是在類中添加方法或成員的,因此<%!...%>中的內容不會出如今_jspService()中。

  <%!

       private String name;

       public String hello() {

           return "hello JSP!";

       }

    %>

 

5 JSP註釋

咱們如今已經知道JSP是須要先編譯成.java,再編譯成.class的。其中<%-- ... --%>中的內容在JSP編譯成.java時會被忽略的,即JSP註釋。

也能夠在JSP頁面中使用html註釋:<!-- … -->,但這個註釋在JSP編譯成的.java中是存在的,它不會被忽略,並且會被髮送到客戶端瀏覽器。可是在瀏覽器顯示服務器發送過來的html時,由於<!-- … -->是html的註釋,因此瀏覽器是不會顯示它的。

 

 

 

會話跟蹤技術

 

1 什麼是會話跟蹤技術

咱們須要先了解一下什麼是會話!能夠把會話理解爲客戶端與服務器之間的一次會晤,在一次會晤中可能會包含屢次請求和響應。例如你給10086打個電話,你就是客戶端,而10086服務人員就是服務器了。從雙方接通電話那一刻起,會話就開始了,到某一方掛斷電話表示會話結束。在通話過程當中,你會向10086發出多個請求,那麼這多個請求都在一個會話中。

在JavaWeb中,客戶向某一服務器發出第一個請求開始,會話就開始了,直到客戶關閉了瀏覽器會話結束。

 

在一個會話的多個請求中共享數據,這就是會話跟蹤技術。例如在一個會話中的請求以下:

l  請求銀行主頁;

l  請求登陸(請求參數是用戶名和密碼);

l  請求轉帳(請求參數與轉帳相關的數據);

l  請求信譽卡還款(請求參數與還款相關的數據)。

 

在這上會話中當前用戶信息必須在這個會話中共享的,由於登陸的是張三,那麼在轉帳和還款時必定是相對張三的轉帳和還款!這就說明咱們必須在一個會話過程當中有共享數據的能力。

 

2 會話路徑技術使用Cookie或session完成

咱們知道HTTP協議是無狀態協議,也就是說每一個請求都是獨立的!沒法記錄前一次請求的狀態。但HTTP協議中可使用Cookie來完成會話跟蹤!

在JavaWeb中,使用session來完成會話跟蹤,session底層依賴Cookie技術。

 

Cookie

 

1 Cookie概述

 

1.1 什麼叫Cookie

Cookie翻譯成中文是小甜點,小餅乾的意思。在HTTP中它表示服務器送給客戶端瀏覽器的小甜點。其實Cookie就是一個鍵和一個值構成的,隨着服務器端的響應發送給客戶端瀏覽器。而後客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。

 

 

  Cookie是由服務器建立,而後經過響應發送給客戶端的一個鍵值對。客戶端會保存Cookie,並會標註出Cookie的來源(哪一個服務器的Cookie)。當客戶端向服務器發出請求時會把全部這個服務器Cookie包含在請求中發送給服務器,這樣服務器就能夠識別客戶端了!

 

1.2 Cookie規範

l  Cookie大小上限爲4KB;

l  一個服務器最多在客戶端瀏覽器上保存20個Cookie;

l  一個瀏覽器最多保存300個Cookie;

 

上面的數據只是HTTP的Cookie規範,但在瀏覽器大戰的今天,一些瀏覽器爲了戰勝對手,爲了展示本身的能力起見,可能對Cookie規範「擴展」了一些,例如每一個Cookie的大小爲8KB,最多可保存500個Cookie等!但也不會出現把你硬盤佔滿的可能!

注意,不一樣瀏覽器之間是不共享Cookie的。也就是說在你使用IE訪問服務器時,服務器會把Cookie發給IE,而後由IE保存起來,當你在使用FireFox訪問服務器時,不可能把IE保存的Cookie發送給服務器。

 

1.3 Cookie與HTTP頭

 

Cookie是經過HTTP請求和響應頭在客戶端和服務器端傳遞的:

l  Cookie:請求頭,客戶端發送給服務器端;

  • 格式:Cookie: a=A; b=B; c=C。即多個Cookie用分號離開;

l  Set-Cookie:響應頭,服務器端發送給客戶端;

  • 一個Cookie對象一個Set-Cookie:

Set-Cookie: a=A

Set-Cookie: b=B

Set-Cookie: c=C

 

1.4 Cookie的覆蓋

  若是服務器端發送重複的Cookie那麼會覆蓋原有的Cookie,例如客戶端的第一個請求服務器端發送的Cookie是:Set-Cookie: a=A;第二請求服務器端發送的是:Set-Cookie: a=AA,那麼客戶端只留下一個Cookie,即:a=AA。

 

1.5 Cookie第一例

咱們這個案例是,客戶端訪問AServlet,AServlet在響應中添加Cookie,瀏覽器會自動保存Cookie。而後客戶端訪問BServlet,這時瀏覽器會自動在請求中帶上Cookie,BServlet獲取請求中的Cookie打印出來。

 

 

AServlet.java

package cn.itcast.servlet;

 

import java.io.IOException;

import java.util.UUID;

 

import javax.servlet.ServletException;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

/**

 * 給客戶端發送Cookie

 * @author Administrator

 *

 */

public class AServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       response.setContentType("text/html;charset=utf-8");

      

       String id = UUID.randomUUID().toString();//生成一個隨機字符串

       Cookie cookie = new Cookie("id", id);//建立Cookie對象,指定名字和值

       response.addCookie(cookie);//在響應中添加Cookie對象

       response.getWriter().print("已經給你發送了ID");

    }

}

 

BServlet.java

package cn.itcast.servlet;

 

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;

 

/**

 * 獲取客戶端請求中的Cookie

 * @author Administrator

 *

 */

public class BServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       response.setContentType("text/html;charset=utf-8");

      

       Cookie[] cs = request.getCookies();//獲取請求中的Cookie

       if(cs != null) {//若是請求中存在Cookie

           for(Cookie c : cs) {//遍歷全部Cookie

              if(c.getName().equals("id")) {//獲取Cookie名字,若是Cookie名字是id

                  response.getWriter().print("您的ID是:" + c.getValue());//打印Cookie值

              }

           }

       }

    }

}

 

 

 

2 Cookie的生命

2.1 什麼是Cookie的生命

  Cookie不僅是有name和value,Cookie仍是生命。所謂生命就是Cookie在客戶端的有效時間,能夠經過setMaxAge(int)來設置Cookie的有效時間。

l  cookie.setMaxAge(-1):cookie的maxAge屬性的默認值就是-1,表示只在瀏覽器內存中存活。一旦關閉瀏覽器窗口,那麼cookie就會消失。

l  cookie.setMaxAge(60*60):表示cookie對象可存活1小時。當生命大於0時,瀏覽器會把Cookie保存到硬盤上,就算關閉瀏覽器,就算重啓客戶端電腦,cookie也會存活1小時;

l  cookie.setMaxAge(0):cookie生命等於0是一個特殊的值,它表示cookie被做廢!也就是說,若是原來瀏覽器已經保存了這個Cookie,那麼能夠經過Cookie的setMaxAge(0)來刪除這個Cookie。不管是在瀏覽器內存中,仍是在客戶端硬盤上都會刪除這個Cookie。

 

2.2 瀏覽器查看Cookie

下面是瀏覽器查看Cookie的方式:

l   IE查看Cookie文件的路徑:C:\Documents and Settings\Administrator\Cookies;

l  FireFox查看Cooke:

 

l  Google查看Cookie:

 

 

 

 

 

2.3 案例:顯示上次訪問時間

l  建立Cookie,名爲lasttime,值爲當前時間,添加到response中;

l  在AServlet中獲取請求中名爲lasttime的Cookie;

l  若是不存在輸出「您是第一次訪問本站」,若是存在輸出「您上一次訪問本站的時間是xxx」;

AServlet.java

    public void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       response.setContentType("text/html;charset=utf-8");

      

       Cookie cookie = new Cookie("lasttime", new Date().toString());[崔10] 

       cookie.setMaxAge(60 * 60);[崔11] 

       response.addCookie(cookie);[崔12] 

      

       Cookie[] cs = request.getCookies();[崔13] 

       String s = "您是首次訪問本站!";

       if(cs != null) {[崔14] 

           for(Cookie c : cs) {[崔15] 

              if(c.getName().equals("lasttime")) {[崔16] 

                  s = "您上次的訪問時間是:" + c.getValue();[崔17] 

              }

           }

       }

      

       response.getWriter().print(s);[崔18] 

    }

 

3 Cookie的path

3.1 什麼是Cookie的路徑

如今有WEB應用A,向客戶端發送了10個Cookie,這就說明客戶端不管訪問應用A的哪一個Servlet都會把這10個Cookie包含在請求中!可是也許只有AServlet須要讀取請求中的Cookie,而其餘Servlet根本就不會獲取請求中的Cookie。這說明客戶端瀏覽器有時發送這些Cookie是多餘的!

能夠經過設置Cookie的path來指定瀏覽器,在訪問什麼樣的路徑時,包含什麼樣的Cookie。

3.2 Cookie路徑與請求路徑的關係

下面咱們來看看Cookie路徑的做用:

下面是客戶端瀏覽器保存的3個Cookie的路徑:

a: /cookietest;

b: /cookietest/servlet;

c: /cookietest/jsp;

 

下面是瀏覽器請求的URL:

A: http://localhost:8080/cookietest/AServlet;

B: http://localhost:8080/cookietest/servlet/BServlet;

C: http://localhost:8080/cookietest/servlet/CServlet;

 

l  請求A時,會在請求中包含a;

l  請求B時,會在請求中包含a、b;

l  請求C時,會在請求中包含a、c;

 

也就是說,請求路徑若是包含了Cookie路徑,那麼會在請求中包含這個Cookie,不然不會請求中不會包含這個Cookie。

l  A請求的URL包含了「/cookietest」,因此會在請求中包含路徑爲「/cookietest」的Cookie;

l  B請求的URL包含了「/cookietest」,以及「/cookietest/servlet」,因此請求中包含路徑爲「/cookietest」和「/cookietest/servlet」兩個Cookie;

l  B請求的URL包含了「/cookietest」,以及「/cookietest/jsp」,因此請求中包含路徑爲「/cookietest」和「/cookietest/jsp」兩個Cookie;

 

3.3 設置Cookie的路徑

設置Cookie的路徑須要使用setPath()方法,例如:

cookie.setPath(「/cookietest/servlet」);

 

若是沒有設置Cookie的路徑,那麼Cookie路徑的默認值當前訪問資源所在路徑,例如:

l  訪問http://localhost:8080/cookietest/AServlet時添加的Cookie默認路徑爲/cookietest;

l  訪問http://localhost:8080/cookietest/servlet/BServlet時添加的Cookie默認路徑爲/cookietest/servlet;

l  訪問http://localhost:8080/cookietest/jsp/BServlet時添加的Cookie默認路徑爲/cookietest/jsp;

 

4 Cookie的domain

Cookie的domain屬性可讓網站中二級域共享Cookie,次要!

百度你是瞭解的對吧!

http://www.baidu.com

http://zhidao.baidu.com

http://news.baidu.com

http://tieba.baidu.com

如今我但願在這些主機之間共享Cookie(例如在www.baidu.com中響應的cookie,能夠在news.baidu.com請求中包含)。很明顯,如今不是路徑的問題了,而是主機的問題,即域名的問題。處理這一問題其實很簡單,只須要下面兩步:

l  設置Cookie的path爲「/」:c.setPath(「/」);

l  設置Cookie的domain爲「.baidu.com」:c.setDomain(「.baidu.com」)。

 

當domain爲「.baidu.com」時,不管前綴是什麼,都會共享Cookie的。可是如今咱們須要設置兩個虛擬主機:www.baidu.com和news.baidu.com。

 

第一步:設置windows的DNS路徑解析

找到C:\WINDOWS\system32\drivers\etc\hosts文件,添加以下內容

127.0.0.1       localhost

127.0.0.1       www.baidu.com

127.0.0.1       news.baidu.com

 

第二步:設置Tomcat虛擬主機

找到server.xml文件,添加<Host>元素,內容以下:

      <Host name="www.baidu.com"  appBase="F:\webapps\www"

            unpackWARs="true" autoDeploy="true"

            xmlValidation="false" xmlNamespaceAware="false"/>

      <Host name="news.baidu.com"  appBase="F:\webapps\news"

            unpackWARs="true" autoDeploy="true"

            xmlValidation="false" xmlNamespaceAware="false"/>

 

第三步:建立A項目,建立AServlet,設置Cookie。

       Cookie c = new Cookie("id", "baidu");

       c.setPath("/");

       c.setDomain(".baidu.com");

       c.setMaxAge(60*60);

       response.addCookie(c);

       response.getWriter().print("OK");

 

把A項目的WebRoot目錄複製到F:\webapps\www目錄下,並把WebRoot目錄的名字修改成ROOT。

 

第四步:建立B項目,建立BServlet,獲取Cookie,並打印出來。

       Cookie[] cs = request.getCookies();

       if(cs != null) {

           for(Cookie c : cs) {

              String s = c.getName() + ": " + c.getValue() + "<br/>";

              response.getWriter().print(s);

           }

       }

 

把B項目的WebRoot目錄複製到F:\webapps\news目錄下,並把WebRoot目錄的名字修改成ROOT。

 

第五步:訪問www.baidu.com\AServlet,而後再訪問news.baidu.com\BServlet。

 

5 Cookie中保存中文

Cookie的name和value都不能使用中文,若是但願在Cookie中使用中文,那麼須要先對中文進行URL編碼,而後把編碼後的字符串放到Cookie中。

 向客戶端響應中添加Cookie

       String name = URLEncoder.encode("姓名", "UTF-8");

       String value = URLEncoder.encode("張三", "UTF-8");

[崔19]       Cookie c = new Cookie(name, value);[崔20] 

       c.setMaxAge(3600);

       response.addCookie(c);

 

從客戶端請求中獲取Cookie

       response.setContentType("text/html;charset=utf-8");

       Cookie[] cs = request.getCookies();

       if(cs != null) {

           for(Cookie c : cs) {

              String name = URLDecoder.decode(c.getName(), "UTF-8");

              String value = URLDecoder.decode(c.getValue(), "UTF-8");

[崔21]              String s = name + ": " + value + "<br/>";

              response.getWriter().print(s);

           }

       }

 

6 顯示曾經瀏覽過的商品

 

index.jsp

  <body>

    <h1>商品列表</h1>

    <a href="/day06_3/GoodServlet?name=ThinkPad">ThinkPad</a><br/>

    <a href="/day06_3/GoodServlet?name=Lenovo">Lenovo</a><br/>

    <a href="/day06_3/GoodServlet?name=Apple">Apple</a><br/>

    <a href="/day06_3/GoodServlet?name=HP">HP</a><br/>

    <a href="/day06_3/GoodServlet?name=SONY">SONY</a><br/>

    <a href="/day06_3/GoodServlet?name=ACER">ACER</a><br/>

    <a href="/day06_3/GoodServlet?name=DELL">DELL</a><br/>

   

    <hr/>

    您瀏覽過的商品:

    <%

    Cookie[] cs = request.getCookies();

    if(cs != null) {

        for(Cookie c : cs) {

           if(c.getName().equals("goods")) {

               out.print(c.getValue());

           }

        }

    }

    %>

  </body>

 

GoodServlet

public class GoodServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       String goodName = request.getParameter("name");

       String goods = CookieUtils.getCookValue(request, "goods");

      

       if(goods != null) {

           String[] arr = goods.split(", ");

           Set<String> goodSet = new LinkedHashSet(Arrays.asList(arr));

           goodSet.add(goodName);

           goods = goodSet.toString();

           goods = goods.substring(1, goods.length() - 1);

       } else {

           goods = goodName;

       }

       Cookie cookie = new Cookie("goods", goods);

       cookie.setMaxAge(1 * 60 * 60 * 24);

       response.addCookie(cookie);

      

       response.sendRedirect("/day06_3/index.jsp");

    }

}

 

CookieUtils

public class CookieUtils {

    public static String getCookValue(HttpServletRequest request, String name) {

       Cookie[] cs = request.getCookies();

       if(cs == null) {

           return null;

       }

       for(Cookie c : cs) {

           if(c.getName().equals(name)) {

              return c.getValue();

           }

       }

       return null;

    }

}

 

HttpSession

 

1        HttpSession概述

1.1 什麼是HttpSesssion

javax.servlet.http.HttpSession接口表示一個會話,咱們能夠把一個會話內須要共享的數據保存到HttSession對象中!

 

1.2 獲取HttpSession對象

l  HttpSession request.getSesssion():若是當前會話已經有了session對象那麼直接返回,若是當前會話還不存在會話,那麼建立session並返回;

l  HttpSession request.getSession(boolean):當參數爲true時,與requeset.getSession()相同。若是參數爲false,那麼若是當前會話中存在session則返回,不存在返回null;

 

1.3 HttpSession是域對象

咱們已經學習過HttpServletRequest、ServletContext,它們都是域對象,如今咱們又學習了一個HttpSession,它也是域對象。它們三個是Servlet中可使用的域對象,而JSP中能夠多使用一個域對象,明天咱們再講解JSP的第四個域對象。

l  HttpServletRequest:一個請求建立一個request對象,因此在同一個請求中能夠共享request,例如一個請求從AServlet轉發到BServlet,那麼AServlet和BServlet能夠共享request域中的數據;

l  ServletContext:一個應用只建立一個ServletContext對象,因此在ServletContext中的數據能夠在整個應用中共享,只要不啓動服務器,那麼ServletContext中的數據就能夠共享;

l  HttpSession:一個會話建立一個HttpSession對象,同一會話中的多個請求中能夠共享session中的數據;

 

下載是session的域方法:

l  void setAttribute(String name, Object value):用來存儲一個對象,也能夠稱之爲存儲一個域屬性,例如:session.setAttribute(「xxx」, 「XXX」),在session中保存了一個域屬性,域屬性名稱爲xxx,域屬性的值爲XXX。請注意,若是屢次調用該方法,而且使用相同的name,那麼會覆蓋上一次的值,這一特性與Map相同;

l  Object getAttribute(String name):用來獲取session中的數據,當前在獲取以前須要先去存儲才行,例如:String value = (String) session.getAttribute(「xxx」);,獲取名爲xxx的域屬性;

l  void removeAttribute(String name):用來移除HttpSession中的域屬性,若是參數name指定的域屬性不存在,那麼本方法什麼都不作;

l  Enumeration getAttributeNames():獲取全部域屬性的名稱;

 

2 登陸案例

須要的頁面:

l  login.jsp:登陸頁面,提供登陸表單;

l  index1.jsp:主頁,顯示當前用戶名稱,若是沒有登陸,顯示您還沒登陸;

l  index2.jsp:主頁,顯示當前用戶名稱,若是沒有登陸,顯示您還沒登陸;

 

Servlet:

l  LoginServlet:在login.jsp頁面提交表單時,請求本Servlet。在本Servlet中獲取用戶名、密碼進行校驗,若是用戶名、密碼錯誤,顯示「用戶名或密碼錯誤」,若是正確保存用戶名session中,而後重定向到index1.jsp;

 

  當用戶沒有登陸時訪問index1.jsp或index2.jsp,顯示「您尚未登陸」。若是用戶在login.jsp登陸成功後到達index1.jsp頁面會顯示當前用戶名,並且不用再次登陸去訪問index2.jsp也會顯示用戶名。由於屢次請求在一個會話範圍,index1.jsp和index2.jsp都會到session中獲取用戶名,session對象在一個會話中是相同的,因此均可以獲取到用戶名!

 

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>login.jsp</title>

  </head>

 

  <body>

    <h1>login.jsp</h1>

    <hr/>

    <form action="/day06_4/LoginServlet" method="post">

    用戶名:<input type="text" name="username" /><br/>

        <input type="submit" value="Submit"/>

    </form>

  </body>

</html>

 

index1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>index1.jsp</title>

  </head>

 

  <body>

<h1>index1.jsp</h1>

<%

    String username = (String)session.getAttribute("username");[崔22] 

    if(username == null) {

       out.print("您尚未登陸!");[崔23] 

    } else {

       out.print("用戶名:" + username);[崔24] 

    }

%>

<hr/>

<a href="/day06_4/index2.jsp">index2</a>

  </body>

</html>

 

index2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>index2.jsp</title>

  </head>

 

  <body>

<h1>index2.jsp</h1>

<%

    String username = (String)session.getAttribute("username");

    if(username == null) {

       out.print("您尚未登陸!");

    } else {

       out.print("用戶名:" + username);

    }

%>

<hr/>

<a href="/day06_4/index1.jsp">index1</a>

  </body>

</html>

 

LoginServlet

public class LoginServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       request.setCharacterEncoding("utf-8");

       response.setContentType("text/html;charset=utf-8");

      

       String username = request.getParameter("username");[崔25] 

      

       if(username.equalsIgnoreCase("itcast")[崔26] ) {

           response.getWriter().print("用戶名或密碼錯誤!");

       } else {

           HttpSession session = request.getSession();[崔27] 

           session.setAttribute("username", username);[崔28] 

           response.sendRedirect("/day06_4/index1.jsp");[崔29] 

       }

    }

}

 

3 session的實現原理

session底層是依賴Cookie的!咱們來理解一下session的原理吧!

當我首次去銀行時,由於尚未帳號,因此須要開一個帳號,我得到的是銀行卡,而銀行這邊的數據庫中留下了個人帳號,個人錢是保存在銀行的帳號中,而我帶走的是個人卡號。

當我再次去銀行時,只須要帶上個人卡,而無需再次開一個帳號了。只要帶上個人卡,那麼我在銀行操做的必定是個人帳號!

 

當首次使用session時,服務器端要建立session,session是保存在服務器端,而給客戶端的session的id(一個cookie中保存了sessionId)。客戶端帶走的是sessionId,而數據是保存在session中。

當客戶端再次訪問服務器時,在請求中會帶上sessionId,而服務器會經過sessionId找到對應的session,而無需再建立新的session。

 

 

4 session與瀏覽器

session保存在服務器,而sessionId經過Cookie發送給客戶端,但這個Cookie的生命不-1,即只在瀏覽器內存中存在,也就是說若是用戶關閉了瀏覽器,那麼這個Cookie就丟失了。

當用戶再次打開瀏覽器訪問服務器時,就不會有sessionId發送給服務器,那麼服務器會認爲你沒有session,因此服務器會建立一個session,並在響應中把sessionId中到Cookie中發送給客戶端。     

你可能會說,那原來的session對象會怎樣?當一個session長時間沒人使用的話,服務器會把session刪除了!這個時長在Tomcat中配置是30分鐘,能夠在${CATALANA}/conf/web.xml找到這個配置,固然你也能夠在本身的web.xml中覆蓋這個配置!

web.xml

    <session-config>

        <session-timeout>30</session-timeout>

    </session-config>

 

session失效時間也說明一個問題!若是你打開網站的一個頁面開始長時間不動,超出了30分鐘後,再去點擊連接或提交表單時你會發現,你的session已經丟失了!

 

5 session其餘經常使用API

l  String getId():獲取sessionId;

l  int getMaxInactiveInterval():獲取session能夠的最大不活動時間(秒),默認爲30分鐘。當session在30分鐘內沒有使用,那麼Tomcat會在session池中移除這個session;

l  void setMaxInactiveInterval(int interval):設置session容許的最大不活動時間(秒),若是設置爲1秒,那麼只要session在1秒內不被使用,那麼session就會被移除;

l  long getCreationTime():返回session的建立時間,返回值爲當前時間的毫秒值;

l  long getLastAccessedTime():返回session的最後活動時間,返回值爲當前時間的毫秒值;

l  void invalidate():讓session失效!調用這個方法會被session失效,當session失效後,客戶端再次請求,服務器會給客戶端建立一個新的session,並在響應中給客戶端新session的sessionId;

l  boolean isNew():查看session是否爲新。當客戶端第一次請求時,服務器爲客戶端建立session,但這時服務器尚未響應客戶端,也就是尚未把sessionId響應給客戶端時,這時session的狀態爲新。

 

6 URL重寫

咱們知道session依賴Cookie,那麼session爲何依賴Cookie呢?由於服務器須要在每次請求中獲取sessionId,而後找到客戶端的session對象。那麼若是客戶端瀏覽器關閉了Cookie呢?那麼session是否是就會不存在了呢?

其實還有一種方法讓服務器收到的每一個請求中都帶有sessioinId,那就是URL重寫!在每一個頁面中的每一個連接和表單中都添加名爲jSessionId的參數,值爲當前sessionid。當用戶點擊連接或提交表單時也服務器能夠經過獲取jSessionId這個參數來獲得客戶端的sessionId,找到sessoin對象。

index.jsp

  <body>

<h1>URL重寫</h1>

<a href='/day06_5/index.jsp;jsessionid=<%=session.getId() %>'[崔30]  >主頁</a>

 

<form action='/day06_5/index.jsp;jsessionid=<%=session.getId() %>' method="post">

    <input type="submit" value="提交"/>

</form>

  </body>

 

也可使用response.encodeURL()對每一個請求的URL處理,這個方法會自動追加jsessionid參數,與上面咱們手動添加是同樣的效果。

<a href='<%=response.encodeURL("/day06_5/index.jsp") %>' >主頁</a>

 

<form action='<%=response.encodeURL("/day06_5/index.jsp") %>' method="post">

    <input type="submit" value="提交"/>

</form>

 

  使用response.encodeURL()更加「智能」,它會判斷客戶端瀏覽器是否禁用了Cookie,若是禁用了,那麼這個方法在URL後面追加jsessionid,不然不會追加。

 

案例:一次性圖片驗證碼

 

1 驗證碼有啥用

在咱們註冊時,若是沒有驗證碼的話,咱們可使用URLConnection來寫一段代碼發出註冊請求。甚至可使用while(true)來註冊!那麼服務器就廢了!

驗證碼能夠去識別發出請求的是人仍是程序!固然,若是聰明的程序能夠去分析驗證碼圖片!但分析圖片也不是一件容易的事,由於通常驗證碼圖片都會帶有干擾線,人都看不清,那麼程序必定分析不出來。

 

2 VerifyCode類

如今咱們已經有了cn.itcast.utils.VerifyCode類,這個類能夠生成驗證碼圖片!下面來看一個小例子。

    public void fun1() throws IOException {

       // 建立驗證碼類

       VerifyCode vc = new VerifyCode();

       // 獲取隨機圖片

       BufferedImage image = vc.getImage();

       // 獲取剛剛生成的隨機圖片上的文本

       String text = vc.getText()[崔31] ;

       System.out.println(text);

       // 保存圖片

       FileOutputStream out = new FileOutputStream("F:/xxx.jpg");

       VerifyCode.output(image, out);[崔32] 

    }

 

3 在頁面中顯示動態圖片

咱們須要寫一個VerifyCodeServlet,在這個Servlet中咱們生成動態圖片,而後它圖片寫入到response.getOutputStream()流中!而後讓頁面的<img>元素指定這個VerifyCodServlet便可。

VerifyCodeServlet

public class VerifyCodeServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       VerifyCode vc = new VerifyCode();

       BufferedImage image = vc.getImage();

       String text = vc.getText();

       System.out.println("text:" + text);

       VerifyCode.output(image, response.getOutputStream());

    }

}

 

index.jsp

    <script type="text/javascript">

    function _change() {

        var imgEle = document.getElementById("vCode");[崔33] 

        imgEle.src = "/day06_6/VerifyCodeServlet?" + new Date().getTime();[崔34] 

    }

    </script>

... 

  <body>

    <h1>驗證碼</h1>

    <img id="vCode" src="/day06_6/VerifyCodeServlet"/>

    <a href="javascript:_change()">看不清,換一張</a>[崔35] 

  </body>

 

4 在註冊頁面中使用驗證碼

    <form action="/day06_6/RegistServlet[崔36] " method="post">

    用戶名:<input type="text" name="username"/><br/>

    驗證碼:<input type="text" name="code" size="3"/>

    <img id="vCode" src="/day06_6/VerifyCodeServlet"/>

    <a href="javascript:_change()">看不清,換一張</a>

    <br/>

        <input type="submit" value="Submit"/>

    </form>

 

5 RegistServlet

 

修改VerifyCodeServlet

public class VerifyCodeServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       VerifyCode vc = new VerifyCode();

       BufferedImage image = vc.getImage();

       request.getSession().setAttribute("vCode", vc.getText());[崔37] 

       VerifyCode.output(image, response.getOutputStream());

    }

}

 

 

RegistServlet

public class RegistServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       request.setCharacterEncoding("utf-8");

       response.setContentType("text/html;charset=utf-8");

      

       String username = request.getParameter("username");

       String vCode = request.getParameter("code");[崔38] 

      

       String sessionVerifyCode = (String)request.getSession().getAttribute("vCode");[崔39] 

      

       if(vCode.equalsIgnoreCase(sessionVerifyCode)[崔40] ) {

           response.getWriter().print(username + ", 恭喜!註冊成功!");

       } else {

           response.getWriter().print("驗證碼錯誤!");

       }

    }

}

 

6 總結驗證碼案例

l  VerifyCodeServlet:

  • 生成驗證碼:VerifyCode vc = new VerifyCode(); BufferedImage image = vc.getImage();
  • 在session中保存驗證碼文本:request.getSession.getAttribute(「vCode」, vc.getText());
  • 把驗證碼輸出到頁面:VerifyCode.output(image, response.getOutputStream);

l  regist.jsp:

  • 表單中包含username和code字段;
  • 在表單中給出<img>指向VerifyCodeServlet,用來在頁面中顯示驗證碼圖片;
  • 提供「看不清,換一張」連接,指向_change()函數;
  • 提交到RegistServlet;

l  RegistServlet:

  • 獲取表單中的username和code;
  • 獲取session中的vCode;
  • 比較code和vCode是否相同;
  • 相同說明用戶輸入的驗證碼正確,不然輸入驗證碼錯誤。

 

 

 

 

 

 

 


 [崔1]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔2]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔3]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔4]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔5]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔6]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔7]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔8]在<%=%>和<%%>中不用建立便可使用的對象!

 [崔9]JSP頁面中的內容都會在這個位置出現!這時上面所說的對象已經建立完了,因此在JSP頁面中是可使用的。

 [崔10]建立Cookie對象,名爲lasttime,值爲當前時間

 [崔11]設置Cookie在客戶端的有效時間爲1小時

 [崔12]添加Cookie到response中

 [崔13]獲取請求中的Cookie

 [崔14]若是請求中存在Cookie

 [崔15]循環遍歷請求中的Cookie

 [崔16]若是Cookie名爲lasttime

 [崔17]設置s

 [崔18]打印s到響應端

 [崔19]使用URL編碼

 [崔20]編碼後的字符串保存到Cookie中

 [崔21]把Cookie的name和value使用URL解碼後再打印。

 [崔22]在JSP頁面中能夠直接使用session不用建立。使用session獲取用戶名,若是沒有用戶名說明尚未登陸。

 [崔23]若是session中沒有username,說明尚未登陸

 [崔24]若是session中存在username,那麼輸出用戶名

 [崔25]獲取表單參數username

 [崔26]若是用戶爲itcast表示登陸失敗

 [崔27]獲取session對象

 [崔28]在session中保存用戶名

 [崔29]重定向到index1.jsp

 [崔30]請求注意,在index.jsp後面使用的是分號,而不是問號,這是服務器對jsessionid這個參數的特殊要求。

 [崔31]這個方法必須在調用了getImage()方法以後才能使用。由於圖片沒有生成以前是不存在圖片上的文本的。

 [崔32]把image圖片保存到out流中!

 [崔33]獲取<img>元素

 [崔34]從新指定src!由於有些瀏覽器會對其進行緩存,因此須要添加不一樣的參數,保證每次URL的參數都不一樣。

 [崔35]點擊這個連接會執行_change()函數

 [崔36]請求RegistServlet

 [崔37]在session中保存驗證碼文本

 [崔38]獲取表單中的驗證碼,這是用戶在表單中填寫的。

 [崔39]獲取session中的驗證碼,這是在生成驗證碼圖片後,保存在session中的正確的驗證碼文本。

 [崔40]比較用戶輸入的與真正的是否相同。

相關文章
相關標籤/搜索