一、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).

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的寫法:
如圖:

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

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

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

這是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é)一下:

3. Servlet的生命周期
加載和實(shí)例化 Servlet。這項(xiàng)操作一般是動態(tài)執(zhí)行的。然而,Server 通常會提供一個管理的選項(xiàng),用于在 服務(wù)器啟動時強(qiáng)制裝載和初始化特定的 Servlet。
- Server 創(chuàng)建一個 Servlet的實(shí)例
- 第一個客戶端的請求到達(dá)服務(wù)器
- 服務(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í)例
- 服務(wù)器創(chuàng)建一個請求對象,處理客戶端請求
- 服務(wù)器創(chuàng)建一個響應(yīng)對象,響應(yīng)客戶端請求
- 服務(wù)器激活 Servlet 的 service() 方法,傳遞請求和響應(yīng)對象作為參數(shù)
service() 方法獲得關(guān)于請求對象的信息,處理請求,訪問其他資源,獲得需要的信息 - 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()。

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的時候才會創(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)容:

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

注意:這時<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ù)器端的一個資源
- 在地址欄上直接輸入url
- 超連接的方式
- 通過表單方式
- 通過js的location.href方式
- 通過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的配置信息:
- 獲取當(dāng)前servlet的名稱 getServletName()
- 獲取當(dāng)前servlet的初始化參數(shù)
getInitParameter()
getInitParameterNames() - 獲取全局管理者 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目錄下
Class獲取
Class.getResource("/").getPath();獲取classes目錄的絕對磁盤路徑
Class.getResource("").getPath();獲取的是當(dāng)前Class對象代表的類所在的包的路徑。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):
- 編寫一個Servlet中的init方法.在init方法中初始化一個被登錄次數(shù)0.將這個值存入到ServletContext域中.配置Servlet的load-on-startup.
- 在登錄成功代碼中獲得原來的次數(shù)+1.存回到ServletContext域中.
- 在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ì)一個登錄頁面.


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

如果想使用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ù):

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

另需要與數(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>
效果:
