三、Servlet-登陸、跳轉(zhuǎn)、統(tǒng)計(jì)

一、Http協(xié)議

HTTP協(xié)議:超文本傳輸協(xié)議(HTTP,HyperText Transfer Protocol)是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議。所有的WWW文件都必須遵守這個標(biāo)準(zhǔn)。

HTTP協(xié)議規(guī)定 瀏覽器(客戶端)向服務(wù)器發(fā)送 何種格式的數(shù)據(jù). 服務(wù)器 會處理數(shù)據(jù). 向?yàn)g覽器(客戶端)作出響應(yīng).(向客戶端發(fā)送何種格式的數(shù)據(jù))

HTTP協(xié)議的特點(diǎn):

  • HTTP協(xié)議遵守一個請求響應(yīng)模型.
    • 請求和響應(yīng)必須成對出現(xiàn).
    • 必須先有請求后有響應(yīng).
  • HTTP協(xié)議默認(rèn)的端口:80

1. HTTP協(xié)議的請求部分

客戶端向服務(wù)器發(fā)送的數(shù)據(jù)的格式:

GET請求方式的抓包:
GET /WEB09/demo1/subSucc.html?username=aaa&password=123 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
X-HttpWatch-RID: 63397-10023
Referer: http://localhost:8080/WEB09/demo1/demo1.html
Accept-Language: zh-Hans-CN,zh-Hans;q=0.5
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

POST方式的抓包:
POST /WEB09/demo1/subSucc.html HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
X-HttpWatch-RID: 63397-10049
Referer: http://localhost:8080/WEB09/demo1/demo1.html
Accept-Language: zh-Hans-CN,zh-Hans;q=0.5
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 25
Connection: Keep-Alive
Cache-Control: no-cache
username=aaa&password=123

請求行
請求方式 請求路徑 協(xié)議版本

  • 請求方式:請求方式有很多種 常用的是GET和POST.
  • GET和POST區(qū)別?
    • GET:請求參數(shù)會顯示到地址欄.GET方式有大小的限制.GET方式?jīng)]有請求體
    • POST:請求參數(shù)不會顯示到地址欄.在請求體中.POST沒有大小限制.POST方式有請求體.
  • 只有表單設(shè)置為method=”post”才是post請求.其他的都是get請求

請求頭
請求頭通常都是key:value的鍵值對的形式.一般情況下一個key對應(yīng)一個value但也有一個key對應(yīng)多個value的情況.

  • Referer :網(wǎng)站的來源.防盜鏈.
  • User-Agent :獲得客戶端瀏覽器的信息.(文件下載:IE:URL編碼 火狐Base64)
  • If-Modified-Since :和響應(yīng)中一個頭一起使用 完成本地緩存的查找.

請求體
POST方式 提交的請求參數(shù)

常用請求頭信息:

請求頭
Accept: text/html,image/*       --支持?jǐn)?shù)據(jù)類型
Accept-Charset: ISO-8859-1  --字符集
Accept-Encoding: gzip       --支持壓縮
Accept-Language:zh-cn       --語言環(huán)境
Host: www.itcast.cn:80      --訪問主機(jī)
If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT      --緩存文件的最后修改時間
Referer: http://www.itcast.com/index.jsp     --來自哪個頁面、防盜鏈
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
Cookie
Connection: close/Keep-Alive    --鏈接狀態(tài)
Date: Tue, 11 Jul 2000 18:23:51 GMT --時間

2. HTTP協(xié)議的響應(yīng)部分

服務(wù)器向客戶端發(fā)送的數(shù)據(jù)的格式:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"147-1455670867735"
Last-Modified: Wed, 17 Feb 2016 01:01:07 GMT
Content-Type: text/html
Content-Length: 147
Date: Wed, 17 Feb 2016 01:17:06 GMT
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>鎻愪氦鎴愬姛</h1>
</body>
</html>

響應(yīng)行
協(xié)議版本 狀態(tài)碼 狀態(tài)碼描述
200:響應(yīng)成功
302:重定向
304:查找本地緩存
404:瀏覽資源不存在.
500:服務(wù)器內(nèi)部錯誤.

響應(yīng)頭
一個key對應(yīng)一個value,也有一個key對應(yīng)多個value的頭.
Last-Modified :最后的修改文件的事件.與If-Modified-Since一起使用.
Refresh :定時刷新.
Location :重定向的路徑.
Content-Disposition:文件下載的時候使用的頭信息.
禁用瀏覽器緩存:
Pragma
Expires
Cache-Control

響應(yīng)體
頁面要顯示的內(nèi)容.

常用響應(yīng)頭信息:

響應(yīng)頭
Location: http://www.it315.org/index.jsp    --跳轉(zhuǎn)方向
Server:apache tomcat            --服務(wù)器型號
Content-Encoding: gzip          --數(shù)據(jù)壓縮
Content-Length: 80          --數(shù)據(jù)長度
Content-Language: zh-cn         --語言環(huán)境
Content-Type: text/html; charset=GB2312         --數(shù)據(jù)類型
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT    --最后修改時間
Refresh: 1;url=http://www.it315.org     --定時刷新
Content-Disposition: attachment; filename=aaa.zip   --下載
Set-Cookie:SS=Q0=5Lb_nQ; path=/search
Expires: -1                 --緩存
Cache-Control: no-cache             --緩存
Pragma: no-cache                --緩存
Connection: close/Keep-Alive            --連接
Date: Tue, 11 Jul 2000 18:23:51 GMT

二、Servlet

1.概述

運(yùn)行在服務(wù)器端的一小的Java程序,接收和響應(yīng)從客戶端發(fā)送請求.
Servlet的作用:
處理客戶端的請求,并且對請求作出響應(yīng).


servlet.png

a. 客戶端發(fā)送請求至服務(wù)器端;
b. 服務(wù)器將請求信息發(fā)送至 Servlet;
c. Servlet 生成響應(yīng)內(nèi)容并將其傳給服務(wù)器。響應(yīng)內(nèi)容動態(tài)生成,通常取決于客戶端的請求;
d. 服務(wù)器將響應(yīng)返回給客戶端。

一個 Servlet 就是 Java語言中的一個類,它被用來擴(kuò)展服務(wù)器的性能,服務(wù)器上駐留著可以通過“請求-響應(yīng)”編程模型來訪問的應(yīng)用程序。雖然 Servlet 可以對任何類型的請求產(chǎn)生響應(yīng),但通常只用來擴(kuò)展 Web 服務(wù)器的應(yīng)用程序。

我們通過tomcat上提供的案例來看下servlet的寫法:
如圖:


servlets.png

啟動tomcat服務(wù)器,訪問examples工程,查看其下的servlets。


servlets2.png

點(diǎn)擊Servlets examples,我們可以看到下圖


Servlets examples.png

查看一個示例,例如Hello World這個示例。


Hello World.png

這是Hello World這個示例的源代碼,我們可以很清楚的知道,servlet其實(shí)就是一個java類,這個類繼承了HttpServlet,注意,HttpServlet是java servlet api下的一個類,它不在我們的jdk中,所以使用時我們需要單獨(dú)導(dǎo)入這個jar包,我們可以在tomcat中的lib下找到這個包.
路徑: ***\apache-tomcat-7.0.42\lib\servlet-api.jar

那么我們在瀏覽器上輸入一個路徑后,怎樣就可以訪問到這個servlet呢?
我們來查看examples這個工程的配置文件web.xml,在這個文件中有下面這段內(nèi)容:

    <servlet>
        <servlet-name>HelloWorldExample</servlet-name>
        <servlet-class>HelloWorldExample</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HelloWorldExample</servlet-name>
    <url-pattern>/servlets/servlet/HelloWorldExample</url-pattern>
 </servlet-mapping>

其實(shí)這段內(nèi)容就是對我們訪問的HelloWorld這個servlet在tomcat服務(wù)器上的一個配置路徑,簡單說,當(dāng)我們訪問 http://localhost:8080/examples/servlets/servlet/HelloWorldExample時,就會通過<url-pattern>映射的路徑查找到對應(yīng)的servlet 類。

對于一個servlet來說,我們要創(chuàng)建它的步驟如下:
1.創(chuàng)建一個類,繼承HttpServlet
2.重寫doGet(和doPost)方法
3.在web.xml文件中配置servlet。

2. Servlet體系結(jié)構(gòu)與api詳解

Javax.servlet.http.HttpServlet類,是一個抽象類,它的作用是提供將要被子類以創(chuàng)建適用于web 站點(diǎn)的Http servlet的抽象類。而對于HttpServlet的子類,一般需要重寫以下方法。
?doGet,如果 servlet 支持 HTTP GET 請求
?doPost,用于 HTTP POST 請求
?init 和 destroy,用于管理 servlet 的生命周期內(nèi)保存的資源
?getServletInfo,servlet 使用它提供有關(guān)其自身的信息
我們在操作中一般重寫doPost或doGet方法就可以。

  • GenericServletd類
    這個類是HttpServlet的父類,它也是一個抽象類,它主要是處理一般的,與協(xié)議無關(guān)的servlet,如果,要編寫關(guān)于http協(xié)議請使用HttpServlet。
    對于我們創(chuàng)建一個servlet,也可以直接繼承GenericServlet,雖然這種方式不常見,但也是創(chuàng)建servlet的一種方式。
    對于GenericServlet,它實(shí)現(xiàn)了一個Servlet接口,這個接口定義了所有的servlet都必須實(shí)現(xiàn)的方法。

  • Servlet接口
    定義所有 servlet 都必須實(shí)現(xiàn)的方法。
    servlet 是運(yùn)行在 Web 服務(wù)器中的小型 Java 程序。servlet 通常通過 HTTP(超文本傳輸協(xié)議)接收和響應(yīng)來自 Web 客戶端的請求。
    要實(shí)現(xiàn)此接口,可以編寫一個擴(kuò)展 javax.servlet.GenericServlet 的一般 servlet,或者編寫一個擴(kuò)展 javax.servlet.http.HttpServlet 的 HTTP servlet。
    此接口定義了初始化 servlet 的方法、為請求提供服務(wù)的方法和從服務(wù)器移除 servlet 的方法。這些方法稱為生命周期方法,它們是按以下順序調(diào)用的:
    1.構(gòu)造 servlet,然后使用 init 方法將其初始化。
    2.處理來自客戶端的對 service 方法的所有調(diào)用。
    3.從服務(wù)中取出 servlet,然后使用 destroy 方法銷毀它,最后進(jìn)行垃圾回收并終止它。

除了生命周期方法之外,此接口還提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一種方法獲得任何啟動信息,而后一種方法允許 servlet 返回有關(guān)其自身的基本信息,比如作者、版本和版權(quán)。
接下來,我們通過一個圖來將上述內(nèi)容總結(jié)一下:


servlet體系結(jié)構(gòu).png

3. Servlet的生命周期

加載和實(shí)例化 Servlet。這項(xiàng)操作一般是動態(tài)執(zhí)行的。然而,Server 通常會提供一個管理的選項(xiàng),用于在 服務(wù)器啟動時強(qiáng)制裝載和初始化特定的 Servlet。

  1. Server 創(chuàng)建一個 Servlet的實(shí)例
  2. 第一個客戶端的請求到達(dá)服務(wù)器
  3. 服務(wù)器調(diào)用 Servlet 的 init() 方法(可配置為 服務(wù)器 創(chuàng)建 Servlet 實(shí)例時調(diào)用,在 web.xml 中 <servlet> 標(biāo)簽下配置 <load-on-startup> 標(biāo)簽,配置的值為整型,值越小 Servlet 的啟動優(yōu)先級越高),一個客戶端的請求到達(dá) 服務(wù)器, 服務(wù)器實(shí)例化一個 Servlet的實(shí)例
  4. 服務(wù)器創(chuàng)建一個請求對象,處理客戶端請求
  5. 服務(wù)器創(chuàng)建一個響應(yīng)對象,響應(yīng)客戶端請求
  6. 服務(wù)器激活 Servlet 的 service() 方法,傳遞請求和響應(yīng)對象作為參數(shù)
    service() 方法獲得關(guān)于請求對象的信息,處理請求,訪問其他資源,獲得需要的信息
  7. service() 方法使用響應(yīng)對象的方法,將響應(yīng)傳回Server,最終到達(dá)客戶端。service()方法可能激活其它方法以處理請求,如 doGet() 或 doPost() 或程序員自己開發(fā)的新的方法。

對于更多的客戶端請求,服務(wù)器創(chuàng)建新的請求和響應(yīng)對象,仍然激活此 Servlet 的 service() 方法,將這兩個對象作為參數(shù)傳遞給它。如此重復(fù)以上的循環(huán),但無需再次調(diào)用 init() 方法。一般 Servlet 只初始化一次(只有一個對象),當(dāng) 服務(wù)器不再需要 Servlet 時(一般當(dāng) 服務(wù)器關(guān)閉時),服務(wù)器 調(diào)用 Servlet 的 destroy() 方法。
簡單描述如下:
1.客戶端請求該 Servlet;
2.加載 Servlet 類到內(nèi)存;
3.實(shí)例化、初始化該 Servlet;
4.init() 初始化參數(shù);
5.service()(doGet() 或者 doPost());
6.destroy()。

示例代碼如下:
servlet生命周期1.png

web.xml中配置:

<servlet>
        <servlet-name>LifeServlet</servlet-name>
        <servlet-class>com.yzy.loginservlet.servlet.LifeServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LifeServlet</servlet-name>
        <url-pattern>/life</url-pattern>
    </servlet-mapping>

注意:我們在重寫init方法是,不需要重寫帶參數(shù)的,只需要重寫無參數(shù)的init方法就可以。
原因: 在GenericServlet中已經(jīng)將有參數(shù)的init方法重寫,并調(diào)用了一個無參數(shù)的init,所以我們在重寫時,不需要在重寫有參數(shù)init方法


servlet生命周期3.png

客戶端第一次訪問該Servlet的時候才會創(chuàng)建一個Servlet的對象,那么Servlet中的init方法就會執(zhí)行.任何一次從客戶端發(fā)送的請求,那么服務(wù)器創(chuàng)建一個新的線程執(zhí)行Servlet中service方法為這次請求服務(wù).
service方法的內(nèi)部根據(jù)請求的方式的不同調(diào)用不同doXXX的方法.當(dāng)Servlet從服務(wù)器中移除或者關(guān)閉服務(wù)器的時候Servlet對象就會被銷毀.destroy的方法就會執(zhí)行.

Servlet的接口的實(shí)現(xiàn):

Servlet         接口
    |
GenericServlet  通用的Servlet
    |
HttpServlet     HttpServlet

配置Servlet的啟動時加載
在web.xml中<servlet>標(biāo)簽中配置
<load-on-startup>2</load-on-startup>

4. 配置url-pattern

我們在創(chuàng)建servlet后,如果想要這個servlet可以被我們訪問到,必須在web.xml文件中對其進(jìn)行配置。
在其中有一個<url-pattern>這個標(biāo)簽是用于確定我們訪問一個servlet的路徑,接下來,我們詳細(xì)介紹一下關(guān)于這個標(biāo)簽的配置
<url-pattern>它是用于確定我們訪問一個servlet的路徑.
一個servlet可以被不同的路徑映射,換句話說多個不同配置可以映射同一個servlet.我們可以通過下面的示例來說明上面的問題

 <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.yzy.loginservlet.servlet.LoginServlet</servlet-class>
        <!--<load-on-startup>2</load-on-startup>-->
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login2</url-pattern>
    </servlet-mapping>

上面是關(guān)于LifeServlet的配置,大家發(fā)現(xiàn)我們對于LoginServlet它有兩個<servlet-mapping>與其映射,那么這時當(dāng)我們訪問
http://localhost:8080/login
http://localhost:8080/login2
時都可以訪問到LgoinServlet.

那么對于<url-pattern>我們在值的寫法到底應(yīng)該怎樣處理哪?
對于<url-pattern>我們在開發(fā)中它的寫法有以下幾種:

【完全路徑匹配】
* 以/開頭  如:/aaa /aaa/bbb
【目錄匹配】
* 以/開頭 以*結(jié)尾  如:/* /aaa/* /aaa/bbb/*
【擴(kuò)展名匹配】
* 不能以/開始的 需要以*開始   如:*.jsp  *.do  *.action

優(yōu)先級:完全路徑匹配 > 目錄匹配 > 擴(kuò)展名匹配

我們現(xiàn)在查看幾個例子,我們找到tomcat/conf/web.xml ,在這個文件中配置的所有內(nèi)容,其實(shí)是被我們自己的工程中的web.xml文件繼承了,在這個配置文件中有以下幾段內(nèi)容:


tomcat-web.xml.png

對于這段配置,只要訪問時后綴名是jsp或jspx就會執(zhí)行名稱叫jsp的servlet內(nèi)容,這是一個很典型的擴(kuò)展名匹配效果
在tomcat/conf/web.xml中還有這樣一段配置


tomcat-web.xml2.png

注意:這時<url-pattern>它的值就是”/”那么這時它就是一個默認(rèn)(缺省)的servlet.。
默認(rèn)的servlet其作用是用于處理其它的servlet處理不了的請求。

5. load-on-startup

上面我們提到過<load-on-startup>,它可以讓我們在服務(wù)器實(shí)例化servlet時就調(diào)用這個servlet,簡單說就是可以讓一個servlet可以在服務(wù)器啟動時,就加載這個servlet。
我們以LoginServlet類為例來說明一下:

 <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.yzy.loginservlet.servlet.LoginServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

我們在<servlet>標(biāo)簽中添加了一個<load-on-startup>,它的值為2,那么這時LifeServlet就會在服務(wù)器啟動時,跟隨啟動。
注意:<load-on-startup>的值越小代表的是優(yōu)先級越高。

6. 客戶端訪問servlet路徑問題

我們在開發(fā)中,經(jīng)常在頁面上通過表單或超連接向服務(wù)器發(fā)送請求,如果我們訪問的是一個servlet,那么這時訪問servlet的路徑應(yīng)該如何書寫?接下來我們就介紹一下,關(guān)于在客戶端訪問servlet的路徑問題.
在介紹之前,我們先看一下,現(xiàn)階段我們有多少種方式可以訪問服務(wù)器端的一個資源

  1. 在地址欄上直接輸入url
  2. 超連接的方式
  3. 通過表單方式
  4. 通過js的location.href方式
  5. 通過js的window.open()方法

對于以上方式,只有表單提交的方式才可能有POST請求,其它的都是GET請求。

客戶端訪問servlet的路徑問題:

  • 相對路徑:不是以 / 開始的路徑.
    localhost:8080/WEB/servletDemo5
    localhost:8080/WEB/demo2/demo1.html

  • 絕對路徑:
    通常都是以 / 開始的路徑.
    帶工程名的路徑(客戶端的路徑)
    不帶工程名的路徑(服務(wù)器端路徑)

我們使用絕對路徑會比較多一些,而在使用絕對路徑時,我們主要使用的是不帶協(xié)議的絕對路徑,而帶協(xié)議的絕對路徑只要在訪問站外資源時才會使用。對于相對路徑,我們需要分析它們的相對關(guān)系,所以不建議大家使用。

7. ServletConfig

ServletConfig是javax.servlet包下的一個接口,它是由servlet容器(tomcat)創(chuàng)建,并封裝了servlet相關(guān)配置信息的對象,并在servlet容器初始化期間傳遞給了servlet. 通過init(ServletConfig config)方法傳遞。

關(guān)于有參數(shù)init(ServletConfig config)與無參數(shù)init()方法關(guān)系:
有參數(shù)的init方法,是servlet接口中定義的。
而無參數(shù)的init方法是GenericServlet中定義的。
在GenericServlet中重寫了有參數(shù)的init方法,并在其中調(diào)用了無參數(shù)的init方法。
那么,我們在創(chuàng)建一個servlet時,如果是繼承了HttpServlet,在重寫init方法時,就可以只重寫無參數(shù)init就可以。

在web.xml文件中我們可以對servlet進(jìn)行配置,在<servlet>配置標(biāo)簽內(nèi)可以有以下這樣的子標(biāo)簽

        <init-param>
            <param-name>參數(shù)名稱</param-name>
            <param-value>參數(shù)值</param-value>
         </init-param>

這就是用于聲明servlet的初始化參數(shù)

這個對象可以獲得Servlet的配置信息:

  1. 獲取當(dāng)前servlet的名稱 getServletName()
  2. 獲取當(dāng)前servlet的初始化參數(shù)
    getInitParameter()
    getInitParameterNames()
  3. 獲取全局管理者 getServletContext()

方法:
String getServletName():獲取當(dāng)前servlet的名稱(web.xml配置的servlet-name)
String getInitParameter(String key):通過名稱獲取指定的參數(shù)值,如果不存在,返回null
Enumeration getInitParameterNames() :獲取所有初始化參數(shù)的名稱,以 String 對象的 Enumeration 的形式返回
初始化參數(shù)是放在 web.xml文件
servlet標(biāo)簽下子標(biāo)簽 init-param
getServletContext():獲取全局管理者
servletconfig是由服務(wù)器創(chuàng)建的,在創(chuàng)建servlet的同時也創(chuàng)建了它,通過servlet的init(ServletConfig config)將config對象傳遞給servlet,由servlet的getServletConfig方法獲取

  • 獲取servletConfig
    對于ServletConfig對象,我們在自己的servlet中如果想要獲取到,可以通過getServletConfig()對象來獲取。這個方法是在javax.servlet.Servlet接口中定義的,在GenericServlet中對getServletConfig()方法進(jìn)行了實(shí)現(xiàn)。在servlet中以過下面代碼就可以獲取ServletConfig對象。
    ServletConfig config=this.getServletConfig();

8. ServletContext

ServletContext它是javax.servlet.包下的一個接口。

WEB容器在啟動時,它會為每個WEB應(yīng)用程序都創(chuàng)建一個對應(yīng)的ServletContext對象,它代表當(dāng)前web應(yīng)用。

ServletConfig對象中維護(hù)了ServletContext對象的引用,開發(fā)人員在編寫servlet時,可以通過ServletConfig.getServletContext方法獲得ServletContext對象。

由于一個WEB應(yīng)用中的所有Servlet共享同一個ServletContext對象,因此Servlet對象之間可以通過ServletContext對象來實(shí)現(xiàn)通訊。ServletContext對象通常也被稱之為context域?qū)ο蟆?/p>

它代表的是web應(yīng)用上下文(全局管理者)
一個項(xiàng)目的引用.代表了當(dāng)前項(xiàng)目.
當(dāng)項(xiàng)目啟動的時候,服務(wù)器為每一個web項(xiàng)目創(chuàng)建一個servletcontext對象.
當(dāng)項(xiàng)目被移除的時候或者服務(wù)器關(guān)閉的時候servletcontext銷毀
作用:
1.獲取全局的初始化參數(shù)
2.共享資源(xxxAttribute)
3.獲取文件資源
4.其他操作

獲取servletcontext:
方式1:
getServletConfig().getServletContext()
方式2:
getServletContext()

常用方法:
String getInitParameter(String key):通過名稱獲取指定的參數(shù)值
Enumeration getInitParameterNames() :獲取所有的初始化參數(shù)名稱
在根標(biāo)簽下有一個 context-param子標(biāo)簽 用來存放初始化參數(shù)

                <context-param>
                    <param-name>encoding</param-name>
                    <param-value>utf-8</param-value>
                </context-param>

xxxAttribute :存取域?qū)ο?br> String getRealPath(String path):獲取文件部署到tomcat上的真實(shí)路徑(帶tomcat路徑)
getRealPath("/"):獲取文件絕對路徑
D:\javaTools\apache-tomcat-7.0.52\webapps\day09
InputStream getResourceAsStream(String path):以流的形式返回一個文件
String getMimeType(String file) 可以獲取一個文件的mimeType類型.
URL getResource(String path)它返回的是一個資源的URL
還提供 log(String msg),getRequestDispatcher(String path) 等這樣的方法,可以做日志與轉(zhuǎn)向操作

  • servletContext實(shí)現(xiàn)servlet共享
    ServletContext對于一個web應(yīng)用只有一個,所有的servlet使用的就是同一個ServletContext。
    ServletContext提供以下方法用于在域中進(jìn)行數(shù)據(jù)操作
    Object getAttribute(String name)
    返回具有給定名稱的 servlet 容器屬性,如果不具有該名稱的屬性,則返回 null。
    void setAttribute(String name,Object object)
    將對象綁定到此 servlet 上下文中的給定屬性名稱。如果已將指定名稱用于某個屬性,則此方法將使用新屬性替換具有該名稱的屬性。
    void removeAttribute(String name)
    從 servlet 上下文中移除具有給定名稱的屬性。

應(yīng)用場景:統(tǒng)計(jì)訪問站點(diǎn)的人數(shù)

三、Classpath

java project----所有class都在bin目錄下
web project-----所有的class都在classes目錄下

  1. Class獲取
    Class.getResource("/").getPath();獲取classes目錄的絕對磁盤路徑
    Class.getResource("").getPath();獲取的是當(dāng)前Class對象代表的類所在的包的路徑。

  2. ClassLoader獲取
    Class.getClassLoader().getResource("/").getPath();
    獲取的是classes目錄的絕對磁盤路徑
    Class.getClassLoader().getResource("").getPath();
    獲取的是classes目錄的絕對磁盤路徑

這兩個getResource()是使用當(dāng)前ClassLoader加載資源(即資源在 Class path中),這樣資源和class直接打在jar包中,避免文件路徑問題.
兩者不同是Class的getResource()方法是從當(dāng)前.class 文件路徑查找資源,ClassLoader則是從jar包根目錄查找.。

簡單歸納:
通過類加載器獲取文件的路徑(處于classes目錄下的文件)
類.class.getClassLoader().getReource("文件路徑").getPath()
類.class.getClassLoader().getReourceAsStream("文件路徑")

四、實(shí)例:完成系統(tǒng)的登錄功能,登錄后頁面定時跳轉(zhuǎn),并記錄系統(tǒng)被訪問多少次

技術(shù)要點(diǎn):

  • 頁面跳轉(zhuǎn)所用技術(shù)
    【Refresh的響應(yīng)頭】
    HttpServletResponse的操作響應(yīng)頭的方法:
* addHeader(String name,String value); --針對一個key對應(yīng)多個value頭的設(shè)置
    * addDateHeader(String name,long value);
    * addIntHeader(String name,int value);
* setHeader(String name,String value); --針對一個key對應(yīng)一個value
    * setDateHeader(String name,long value);
    * setIntHeader(String name,int value);

簡單實(shí)例:

response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>登錄成功!頁面將在5秒后跳轉(zhuǎn)</h1>");
response.setHeader("Refresh", "5;url=/WEB09/loginSucc.html");

另一種方法,在jsp頁面設(shè)置定時跳轉(zhuǎn):

可以通過html頁面中的一個標(biāo)簽設(shè)置頭信息<meta>標(biāo)簽.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Refresh" content="5;url=/WEB09/succ.html">
<script type="text/javascript" src="/WEB09/js/jquery-1.11.3.min.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
    $(function(){
        setInterval("changeTime()", 1000);
    });
    var i = 5;
    function changeTime(){
        // 獲得id為s1的元素:
        i--;
        $("#s1").html(i);
    }
</script>
</head>
<body>
<h1>登錄成功!??!頁面將在<span id="s1">5</span>秒后跳轉(zhuǎn)!</h1>
</body>
</html>
  • 統(tǒng)計(jì)訪問次數(shù)用到的技術(shù):
    【ServletContext*****】
    ServletContext :Servlet中全部的內(nèi)容ServletContext都了解.一個WEB應(yīng)用只有一個ServletContext對象.服務(wù)器啟動的時候,服務(wù)器為每個WEB工程創(chuàng)建一個屬于自己項(xiàng)目的ServletContext對象.服務(wù)器關(guān)閉的時候或者項(xiàng)目從服務(wù)器中移除ServletContext才會被銷毀.如果將值保存在ServletContext中.值就有一個作用的范圍.所以這個對象稱為”域?qū)ο蟆?

  • 保存全局性信息和數(shù)據(jù):

    • 網(wǎng)站的訪問次數(shù):
    • 聊天室:
  • 在Servlet中獲得ServletContext:

    • ServletContext getServletContext();
  • 操作這個對象的方法:

    • void setAttribute(String name,Object value);
    • Object getAttribute(String name);
    • void removeAttribute(String name);

簡單實(shí)現(xiàn):

  1. 編寫一個Servlet中的init方法.在init方法中初始化一個被登錄次數(shù)0.將這個值存入到ServletContext域中.配置Servlet的load-on-startup.
  2. 在登錄成功代碼中獲得原來的次數(shù)+1.存回到ServletContext域中.
  3. 在5秒后跳轉(zhuǎn)的Servlet中,從ServletContext域中獲得次數(shù),并且顯示到頁面上.
配置SErvlet為啟動時加載:
  <servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>com.itheima.servlet.demo2.UserServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/userServlet</url-pattern>
  </servlet-mapping>

在Servlet的init方法中初始化次數(shù)為0
    @Override
    public void init() throws ServletException {
        // super.init();
        // 獲得ServletContext對象.初始化一個值為0.
        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("count", 0);
    }

在登錄成功的代碼中獲得原來的次數(shù)并且+1,存回到SErvletContext域中。
// 登錄成功的時候 獲得原來的次數(shù) + 1
                Integer count = (Integer) this.getServletContext().getAttribute("count");
                // 存回到ServletContext域中
                this.getServletContext().setAttribute("count", ++count);

在CountServlet中獲得次數(shù)并且顯示:
response.setContentType("text/html;charset=UTF-8");
        // 獲得次數(shù):
        Integer count = (Integer) this.getServletContext().getAttribute("count");
        response.getWriter().println("<h1>您是第"+count+"位登錄成功的用戶!</h1>");

案例代碼實(shí)現(xiàn):
步驟一:設(shè)計(jì)一個登錄頁面.

登陸頁面

image.png

注意:如果html頁面改成jsp頁面需要在頂部加上
<%@ page pageEncoding="utf-8"%>
然后保存,否則會有亂碼錯誤。
注意修改登錄頁面對應(yīng)的name屬性值
image.png

如果想使用el表達(dá)式,首先需要導(dǎo)入jstl的jar包:

 <!-- https://mvnrepository.com/artifact/jstl/jstl -->
      <dependency>
          <groupId>jstl</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
      </dependency>

然后在相應(yīng)的頁面導(dǎo)入jstl標(biāo)簽:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
使用el表達(dá)式顯示次數(shù):

image.png

步驟二:在登錄頁面上點(diǎn)擊登錄按鈕.提交到Servlet.
修改form表單的action和method屬性值:
action地址和web.xml里面的<servlet-mapping>下的地址對應(yīng)。

image.png

另需要與數(shù)據(jù)庫進(jìn)行交互,注意導(dǎo)包:

</dependency>
      <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.30</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
      <dependency>
          <groupId>com.mchange</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.5.2</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/com.mchange/mchange-commons-java -->
      <dependency>
          <groupId>com.mchange</groupId>
          <artifactId>mchange-commons-java</artifactId>
          <version>0.2.11</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
      <dependency>
          <groupId>commons-dbutils</groupId>
          <artifactId>commons-dbutils</artifactId>
          <version>1.6</version>
      </dependency>

步驟三:后端核心代碼

Servlet類

package com.yzy.loginservlet.servlet;


import com.yzy.loginservlet.domain.User;
import com.yzy.loginservlet.service.UserService;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;

public class LoginServlet extends HttpServlet {
    @Override
    //初始化登錄次數(shù)
    public void init() throws ServletException {
        //獲取全局管理者
        ServletContext context = getServletContext();

        //初始化次數(shù)
        context.setAttribute("count", 0);

        System.out.println("初始化次數(shù)成功");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //0.設(shè)置編碼
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");

        //1.接受用戶名和密碼
        String username=req.getParameter("name");
        String password=req.getParameter("password");
        System.out.println(username);

        //2.調(diào)用userservice 里的login(username,password) 返回值:User user
        User user = null;
        try {
            user = new UserService().login(username,password);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("網(wǎng)絡(luò)異常,請稍后再試!");
        }

        //3.判斷user是否為空
        if(user==null){
            //3.1若為空 寫"用戶名和密碼不匹配"
            resp.getWriter().print("用戶名和密碼不匹配,3秒之后跳轉(zhuǎn)");
            //案例2-定時跳轉(zhuǎn)
            resp.setHeader("refresh", "3;url=/login.jsp");

        }else{
            //3.2若不為空 寫"xxx:歡迎回來"
            resp.getWriter().print(user.getUname()+":歡迎回來");
            resp.setHeader("refresh", "1;url=/index.jsp");
            //4.獲取全局管理者
            ServletContext context = this.getServletContext();

            //5.獲取總次數(shù)
            Integer cishu = (Integer) context.getAttribute("count");

            //6.將次數(shù)+1
            cishu++;

            //7.將次數(shù)再次放入域?qū)ο笾?            context.setAttribute("count", cishu);
            System.out.println(cishu);

        }
    }
}

DAO層代碼:

package com.yzy.loginservlet.dao;

import java.sql.SQLException;

import com.yzy.loginservlet.domain.User;
import com.yzy.loginservlet.utils.DataSourceUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;


public class UserDao {

    /**
     * 登錄
     * @param username 用戶名
     * @param password 密碼
     * @return 用戶
     * @throws SQLException 
     */
    public User getUserByUsernameAndPwd(String username, String password) throws SQLException {
        //創(chuàng)建queryrunner
        QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
        
        //編寫sql
        String sql="select * from userinfo where uname = ? and upsw = ?";
        
        //執(zhí)行sql
        User user = qr.query(sql, new BeanHandler<>(User.class), username,password);
        System.out.println(user);
        return user;
    }

}

web.xml代碼:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.yzy.loginservlet.servlet.LoginServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

效果:


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 0 系列目錄# WEB請求處理 WEB請求處理一:瀏覽器請求發(fā)起處理 WEB請求處理二:Nginx請求反向代理 本...
    七寸知架構(gòu)閱讀 14,233評論 22 189
  • 一.Servlet規(guī)范 什么是Servlet:JavaEE中的一種規(guī)范,也是一種組件。在Java中最小的程序單元就...
    賈里閱讀 466評論 0 0
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,931評論 1 92
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 文/游天杰 寫詩十年。我嘗遍了生活的艱辛、孤獨(dú)和失敗,很多時候,是詩歌讓我沉默,讓我回到簡單又豐盈的日子。...
    游天杰閱讀 334評論 2 3

友情鏈接更多精彩內(nèi)容