[Java面試三]JavaWeb基礎知識總結.
[Java面試三]JavaWeb基礎知識總結.
1.web伺服器與HTTP協議
Web伺服器
l WEB,在英語中web即表示網頁的意思,它用於表示Internet主機上供外界訪問的資源。
l Internet上供外界訪問的Web資源分為:
• 靜態web資源(如html 頁面):指web頁面中供人們瀏覽的資料始終是不變。
• 動態web資源:指web頁面中供人們瀏覽的資料是由程式產生的,不同時間點訪問web頁面看到的內容各不相同。
l 靜態web資源開發技術
• Html
l 常用動態web資源開發技術:
• JSP/Servlet、ASP、PHP等 ruby python
• 在Java中,動態web資源開發技術統稱為Javaweb,我們課程的重點也是教大家如何使用Java技術開發動態的web資源,即動態web頁面。
但是我們做java開發,不是做網頁。
網路上的資源分為兩種
早期:靜態頁面 html實現。 觀看
現在:動態頁面 php asp jsp 互動.
lamp =linux +apache+ mysql+php----->個人閘道器或小型企業首選
asp現在沒人用,但是網路上遺留下來的比較多。miscrosoft的技術
.net技術。
jsp--->java去做網頁所使用的技術。jsp本質上就是servlet
使用jsp開發成本高。
BS====>瀏覽器+伺服器 只要有瀏覽器就可以
CS----->客戶端+伺服器. 必須的在客戶端安裝程式.
現在基本上開發的都是BS程式
BS怎樣通訊:
必須有請求有響應。
有一次請求就應該具有一次響應,它們是成對出現的。
伺服器介紹
大型伺服器:websphere(IBM),weblogic(Oracle) J2EE容器 -
支援EJB (EnterPrice Java Bean (企業級的javabean)) – Spring
weblogic BEA公司產品,被Oracle收購,全面支援JavaEE規範,收費軟體,企業中非常主流的伺服器 -------- 網路上文件非常全面
WebSphere 文件非常少,IBM公司產品,價格昂貴,全面支援JavaEE 規範
Tomcat- apache,開源的。Servlet容器。
tomcat 開源小型web伺服器 ,完全免費,主要用於中小型web專案,只支援Servlet和JSP 等少量javaee規範 ,Apache公司jakarta 一個子專案
Jboss – hibernate公司開發。不是開源免費。J2EE容器
Tomcat安裝
注意路徑中不要包含空格與中文。
Ø 安裝步驟
1、tomcat.apache.org 下載tomcat安裝程式
Tomcat7安裝程式 ---- zip免安裝版
2、解壓tomcat
3、配置環境變數 JAVA_HOME 指向JDK安裝目錄 D:\Program Files\Java\jdk1.6.0_21
*CATALINA_HOME指定tomcat安裝目錄
4、雙擊tomcat/bin/startup.bat
5、在瀏覽器中 輸入 localhost:8080 訪問tomcat主頁了
Ø 注意問題:
啟動黑色不能關閉
1、CATALINA_HOME 指定tomcat安裝位置 --- 可以不配置
2、JAVA_HOME 指定JDK安裝目錄,不要配置bin目錄,不要在結尾加;
3、埠被佔用
啟動cmd
netstat -ano 檢視佔用埠程序pid
工作管理員 檢視---選擇列 顯示pid -- 根據pid結束程序
* 有些程序無法關係(系統服務 --- 必須結束服務) win7 自帶 World wide web publish IIS服務 預設佔用埠80
* xp 安裝apache伺服器後,會佔用80 埠 ,關閉apache服務
通過執行 services.msc 開啟服務視窗 關閉相應服務
tomcatc目錄結構
-----bin 它裡面裝入的是可執行的命令 如 startup.bat
-----conf 它裡面是一個相關的配置檔案,我們可以在裡面進行例如埠,使用者資訊的配置
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-----lib tomcat類庫。
-----logs tomcat 日誌檔案
-----temp 臨時檔案
-----webapps 它裡面放的是的 web site(web專案)
-----work 存放的是頁面(例如 jsp)轉換成的.class檔案。
2.建立網站,將網站釋出到tomcat伺服器上
建立網站根目錄
在根目錄下 建立靜態web資源和動態web資源
Web site
---- *.html *.css *.js 圖片 音訊 視訊 、*.jsp
---- WEB-INF目錄 存放java程式和配置檔案
--- classes 存放.class檔案
--- lib 存放.jar 檔案
--- web.xml 網站核心配置檔案
*** 如果靜態網站可以不存在 WEB-INF目錄的 ,WEB-INF目錄,客戶端無法直接訪問(在伺服器記憶體通過程式訪問)
將網站釋出到tomcat -----------虛擬目錄對映
虛似目錄的對映方式有三種
1.在開發中應用的比較多 直接在webapps下建立一個自己的web site就可以.
步驟 1.在webapps下建立一個myweb目錄
2.在myweb下建立WEB-INF目錄,在這個目錄下建立web.xml
3.將web.xml檔案中的xml宣告與根元素宣告在其它的web site中copy過來。
4.在myweb下建立一個index.html檔案
5.啟動tomcat
6.在瀏覽器中輸入 http://localhost/myweb/index.html
以下兩種方式,可以將web site不放置在tomcat/webapps下,可以任意放置
2.在server.xml檔案中進行配置
<Context path="/abc" docBase="C:\myweb1"/>
</Host>
在Host結束前配置
path:它是一個虛擬路徑,是我們在瀏覽器中輸入的路徑
docBase:它是我們web sit的真實路徑
http://localhost/abc/index.html
3.不在server.xml檔案中配置
而是直接建立一個abc.xml檔案
在這個xml檔案中寫
<Context path="" docBase="C:\myweb1"/>
將這個檔案放入conf\Catalina\localhost
http://localhost/abc/index.html
3.生成war檔案
war檔案是web專案的壓縮檔案。
要想生成,先將要壓縮的內容壓縮成zip檔案,
然後將字尾改成war就可以,
war檔案可以直接在伺服器上訪問。
關於tomcat-manager
可以在conf/tomcat-users.xml中進行使用者資訊新增
<role rolename="manager"/>
<user username="xxx" password="xx" roles="manager"/>
這樣就添加了一個使用者
注意,使用者許可權要是比較大的話,會出現安全問題.
4.虛擬主機
做自己的一個http://www.baidu.com
1.訪問一個網站的過程
http://www.baidu.com
http 協議
www 伺服器
.baidu.com 域名 IP
步驟
1.上網將baidu首頁下載下來
2.做一個自己的web site 首頁就是下載下來的頁面。
別忘記建立WEB-INF在它下面的web.xml檔案中
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
這句話的作用是預設訪問頁面是index.html
3.在tomcat中的conf資料夾下的server.xml中修改
<Host name="www.baidu.com" appBase="c:\baidu"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Context path="" docBase="c:\baidu"/>
</Host>
4.在windows/system32/drivers/etc/hosts中新增
127.0.0.1 www.baidu.com
目的是當訪問www.baidu.com時其實訪問的是本機。
5.開啟瀏覽器在位址列中輸入www.baidu.com
這時其時訪問的是我們自己
web site中的頁面。
5.使用myeclipse建立web project與tomcat整合
我們在myeclipse中建立web project有一個WebRoot目錄。
但是我們釋出到tomcat中沒有這個,它其時就是我們工程的名稱.
步驟
1.建立web工程
2.在eclipse中配置tomcat伺服器
window/屬性/myeclipse/service中配置自己的tomcat目錄.
注意到tomcat根目錄就可以了。不要到bin中。
如果不好使用,看一些jdk是否配置.
1. 將webproject部署到tomcat中
6.HTTP協議
HTTP是hypertext transfer protocol(超文字傳輸協議)的簡寫,它是TCP/IP協議的一個應用層協議,用於定義WEB瀏覽器與WEB伺服器之間交換資料的過程。
HTTP協議是學習JavaWEB開發的基石,不深入瞭解HTTP協議,就不能說掌握了WEB開發,更無法管理和維護一些複雜的WEB站點。
示例1
telnet怎樣使用
1.telnet localhost 8080
2 ctrl+]
3.按回車
注意 在裡面寫錯的內容不能修改
GET /index.html HTTP/1.1
host:localhost
4.要敲兩次回車
HTTP/1.0版本只能保持一次會話
HTTP/1.1版本可能保持多次會話.
是根據telnet得到的響應資訊
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
ETag: W/"7347-1184876416000"
Last-Modified: Thu, 19 Jul 2007 20:20:16 GMT
Content-Type: text/html
Content-Length: 7347
Date: Thu, 25 Apr 2013 08:06:53 GMT
Connection: close
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Apache Tomcat</title>
<style type="text/css">
..........
示例2
是根據httpwatch得到的請求資訊與響應資訊
請求
GET / HTTP/1.1
Accept: application/x-shockwave-flash, image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
響應
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
ETag: W/"7347-1184876416000"
Last-Modified: Thu, 19 Jul 2007 20:20:16 GMT
Content-Type: text/html
Content-Length: 7347
Date: Thu, 25 Apr 2013 08:12:57 GMT
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang
請求資訊詳解
GET /books/java.html HTTP/1.1 ---------->請求行
Get是請求方式 /books/java.html 請求資源 HTTp/1.1協議版本
POST與GET的區別
1.什麼樣是GET 請求 1)直接在位址列輸入 2.超連線 <a></a> 3.form表單中method=get
什麼樣是POSt請求 form表單中method=POST
2.以get方式提交請求時,在請求行中會將提交資訊直接帶過去
格式 /day03_1/login?username=tom&password=123
以post方式提交時,資訊會在正文中。
POST /day03_1/login HTTP/1.1
Accept: application/x-shockwave-flash, image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost/day03_1/login.html
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost
Content-Length: 25
Connection: Keep-Alive
Cache-Control: no-cache
username=tom&password=123
3. get方式最多能提交1kb
post可以提交大資料,做上傳時必須是post
Accept: */* 允許訪問mime型別,型別都在tomcat 的conf/web.xml檔案中定義了。
這個需要知道,因為做下載時要知道mime型別
Accept-Language: en-us 客戶端的語言
Connection: Keep-Alive 持續連線
Host: localhost 客戶端訪問資源
Referer: http://localhost/links.asp (重點) 防盜鏈。
User-Agent: Mozilla/4.0 得到瀏覽器版本 避免相容問題
Accept-Charset: ISO-8859-1 客戶端字元編碼集
Accept-Encoding: gzip, deflate gzip是壓縮編碼.
If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT 與Last-MOdified一起可以控制快取。
Date: Tue, 11 Jul 2000 18:23:51 GMT
示例1
防盜鏈程式
referer.htm頁面
<body>
<a href="referer">referer</a>
</body>
RefererServlet類似
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String msg = request.getHeader("Referer");
if (msg != null && "http://localhost/day03_1/referer.html".equals(msg)) {
// 如果你是正常訪問,我們給其一個友好資訊
response.getWriter().write("hello");
} else {
// 如果是盜鏈過來的,對不。罵它一句
response.getWriter().write("fuck...");
}
}
怎樣破解
URL url = new URL("http://localhost/day03_1/referer"); //得到一個url
URLConnection con = url.openConnection(); //訪問這個url,並獲得連線物件
con.addRequestProperty("Referer",
"http://localhost/day03_1/referer.html");
InputStream is = con.getInputStream(); // 讀取伺服器返回的資訊.
byte[] b = new byte[1024];
int len = is.read(b);
System.out.println(new String(b, 0, len));
http協議響應
HTTP/1.1 200 OK 響應狀態行
HTTP/1.1 200 OK
1xx 什麼都沒做直接返回
2xx 成功返回
3xx 做了一些事情,沒有全部完成。
4xx 客戶端錯誤
5xx 伺服器錯誤
200 正確
302 重定向
304 頁面沒有改變
404 未找到頁面
500 伺服器出錯.
Location: http://www.it315.org/index.jsp 響應路徑(重點)+302
Server:apache tomcat
Content-Encoding: gzip 響應編碼 gzip 壓縮
Content-Length: 80 響應長度
Content-Language: zh-cn 響應語言
Content-Type: text/html; charset=GB2312 響應字元編碼
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 要與請求中的 If-Modified-Since處理快取
Refresh: 1;url=http://www.it315.org 自動跳轉
Content-Disposition: attachment; filename=aaa.zip (重要) 檔案的下載
//下面三個是禁用瀏覽快取
Expires: -1
Cache-Control: no-cache
Pragma: no-cache
Connection: close/Keep-Alive
Date: Tue, 11 Jul 2000 18:23:51 GMT
重點
今天可以講
Location: http://www.it315.org/index.jsp 響應路徑(重點)+302
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 要與請求中的 If-Modified-Since處理快取
Refresh: 1;url=http://www.it315.org 自動跳轉
我們在得到響應資訊,經常得到的是壓縮後的。
這種操作
1.伺服器配置方式
tomcat配置實現壓縮
80埠沒有配置 00:00:00.000 0.228 7553 GET 200 text/html http://localhost/
8080埠配置 00:00:00.000 0.027 2715 GET 200 text/html http://localhost:8080/
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" compressableMimeType="text/html,text/xml,text/plain" compression="on"/>
2.通過我們程式設計實現.(後面會講)
後面會講
Content-Disposition: attachment; filename=aaa.zip (重要) 檔案的下載
//下面三個是禁用瀏覽快取
Expires: -1
Cache-Control: no-cache
Pragma: no-cache
4.啟動伺服器
5.在瀏覽器中訪問web資源.
Servlet
什麼是Servlet
l Servlet是一個功能,如果你希望你的專案功能多一些,那就要多寫一此Servlet;
l Servlet是JavaWeb三大元件之一,也是最重要的元件!
Ø 三大元件:Servlet、Filter、Listener
l Servlet是一個我們自定義的Java類,它必須要實現javax.servlet.Servlet介面。
l Servlet是動態資源!
l Servlet必須在web.xml中進行配置後,才能被訪問。(把Servlet與一個或多個路徑繫結在一起)
如何實現Servlet
l 實現Servlet有三種方式:
Ø 實現Servlet介面;
Ø 繼承GenericServlet類;
Ø 繼承HttpServlet類(最佳選擇)。
3 Servlet的helloworld專案
3.1 手動完成
看程式碼
3.2 MyEclipse完成
看程式碼
4 Servlet的生命週期
4.1 生命週期相關方法
l Servlet介面中一共是5個方法,其中有三個是生命週期方法。
Ø void init(ServletConfig):這個方法會在Servlet被建立後,馬上被呼叫。只會被呼叫一次!我們可以把一些初始化工作放到這個方法中,如果沒有什麼初始化工作要做,那麼這個方法就空著就可以了。
² Servlet有兩個時間點會被建立:一是在第一次被請求時,會被建立;二是Tomcat啟動時被建立,預設是第一種,如果希望在tomcat啟動時建立,這需要在web.xml中配置。
Ø void destroy():這個方法會在Servlet被銷燬之前被呼叫。如果你有一些需要釋放的資源,可以在這個方法中完成,如果沒有那麼就讓這個方法空著。這個方法也只會被呼叫一次!
² Servlet輕易不會被銷燬,通常會在Tomcat關閉時會被銷燬。
Ø void service(ServletRequest,ServletResponse):它會在每次被請求時呼叫!這個方法會被呼叫0~N次。
Ø String getServletInfo():它不是生命週期方法,也就是說它不會被tomcat呼叫。它可以由我們自己來呼叫,但我們一般也不呼叫它!你可以返回一個對當前Servlet的說明性字串。
Ø ServletConfig getServletConfig():這個方法返回的是ServletConfig,這個型別與init()方法的引數型別相同。它對應的是web.xml中的配置資訊,即<servlet>
4.2 ServletConfig、ServletContext、ServletRequest、ServletResponse
l ServletRequest:封裝了請求資訊;
l ServletResposne:用於向客戶端響應;
l ServletContext:它可以在多個Servlet中共享資料。
l ServletConfig:它與<servlet>對應!
Ø 在<servlet>中可以配置<init-param>,即初始化引數,可以使用ServletConfig的getInitParameter(String),方法的引數是初始化引數名,方法的返回值是初始化引數值。
Ø getInitParameterNames(),該方法返回一個Enumeration物件,即返回所有初始化引數的名稱。
Ø String getServletName(),它返回的是<servlet-name>元素的值
Ø ServletContext getServletContext(),它可以獲取Servlet上下文物件。
5 GenericServlet
l 它代理了ServletConfig的所有功能。所有使用ServletConfig才能呼叫的方法,都可以使用GenericServlet的同名方法來完成!
l 不能覆蓋父類的init(ServltConfig)方法,因為在父類中該方法內完成了this.config=config,其他的所有ServletConfig的代理方法都使用this.config來完成的。一旦覆蓋,那麼this.config就是null。
l 如果我們需要做初始化工作,那麼可以去覆蓋GenericServlet提供的init()方法。
6 HttpServlet
l 它提供了與http協議相關的一些功能。
l 只需要去覆蓋doGet()或doPost()即可。這兩個方法,如果沒有覆蓋,預設是響應405!
7 Servlet細節
7.1 Servlet單例、執行緒不案例
l Servlet是的單例的。所以一個Servlet物件可能同時處理多個請求;
l Servlet不是執行緒安全的。
Ø 儘可能不建立成員變數,因為成員變數多個執行緒會共享!
Ø 如果非要建立,那麼建立功能性的,只讀!
7.2 Servlet的建立時間:第一次被請求、啟動建立
* Servlet可以在第一次請求時被建立,還可以在容器啟動時被建立。預設是第一次請求時!
* 在<servlet>新增一個<load-on-startup>大於等於0的整數</load-on-startup>
* 如果有多個Servlet在容器啟動時建立,那麼<load-on-startup>的值就有用了,建立的順序使用它的值來排序!
7.3 <url-pattern>的配置
l <url-pattern>中可以使用“*”表示所有字元,但它不匹配“/”。它的使用要求:
Ø 它要麼在頭,要麼在尾。不能在中間;
Ø 如果不使用萬用字元,那麼必須使用“/”開頭。
l 如果一個訪問路徑,匹配了多個<url-pattern>,那麼誰更加明確就匹配誰。
7.4 web.xml的繼承
l 每個專案都有一個web.xml,但tomcat下也有一個web.xml,在${CATALINA_HOME}\conf\web.xml
l conf\web.xml是所有專案的web.xml父檔案,父檔案中的內容等於同寫在子檔案中。
ServletContext
Servlet三大域物件:
l ServletContext:範圍最大,應用範圍!
l HttpSession :會話範圍!
l HttpServletRequest:請求範圍!
域物件之一
域物件都有存取功能:
setAttribute(“attrName”, attrValue );//put
Object attrValue = getAttribute(“attrName”);//get
removeAttribute(“attrName”);//remove
1 ServletContext的作用
l 存取域屬性,ServletContext是一個域物件;
l 可以用來獲取應用初始化引數;
l 獲取資源
ServletContext的生命週期
l ServletContext在容器啟動時就被建立了;
l ServletContext在容器關閉時才會死!
l 一個專案只有一個ServletContext物件。
3 獲取ServletContext
l 通過ServletConfig的getServletContext()方法來獲取!
Ø ServletConfig是init()方法的引數,那隻能在init()方法中獲取了;
Ø GenericServlet代理了ServletConfig的所有方法,而且還提供了getServletConfig(),所以在GenericServlet的子類中可以使用如下方式來獲取ServletContext物件:
² this.getServletContext()
² this.getServletConfig().getServletContext()
Ø HttpSession也有這個方法,session.getServletContext()。
4 域物件:ServletContext
l void setAttribute(String name, Object value):儲存屬性;
l Object getAttribute(String name):獲取屬性;
l void removeAttribute(String name):移除屬性;
l Enumeration getAttributeNames():獲取所有屬性名稱;
5 獲取初始化引數
一個 專案不只是可以配置servlet的初始化引數,還可以配置應用初始化引數
下面就是在web.xml中配置應用的初始化引數,這些引數需要使用ServletContext來獲取
<context-param> <param-name>p1</param-name> <param-value>v1</param-value> </context-param> <context-param> <param-name>p2</param-name> <param-value>v2</param-value> </context-param> |
l String getInitParameter(String name):通過引數名獲取引數值;
l Enumeration getInitParameterNames():獲取所有引數的名稱;
6 獲取資源
l 獲取真實路徑:getRealPath(String path):路徑必須以“/”開頭!它相對當前專案所在路徑的。
l 獲取指定路徑下的所有資源路徑:Set set = sc.getResourcePaths(“/xxx”)
l 獲取資源流:InputStream in = sc.getResourceAsStream(“/xxx”)
7 Class和ClassLoader獲取資源
User.class如何變成Class<User>的呢,由ClassLoader完成的!把硬碟上的User.class載入到記憶體,變成Class物件。
使用它們獲取資源流!它們相對類路徑(classpath)
request&response 物件
response
1. response簡介
l response的型別為HttpServletResponse,它是Servlet的service()方法的引數。
l 當客戶端發出請求時,tomcat會建立request和rsponse來呼叫Servlet的service()方法,每次請求都會建立新的request和response。
l response是用來向客戶端完成響應。
2 response的兩個流,用來響應正文
l response.getWriter() ,返回值為PrintWriter,用響應字元資料。
l response.getOutputStream(),返回值為ServletOutputStream,用來響應位元組資料。
l 在一個請求範圍內,這兩個流不能同時使用!不然會輸出非法狀態異常。
3 response字元流的編碼問題
l response的字元流預設使用ISO-8859-1編碼,可以使用response.setCharaceterEncoding(“utf-8”)來設定編碼;
l 瀏覽器在沒有得到Content-Type頭時,會使用GBK來解讀字串,當如果你設定了Content-Type,會使用你指定編碼來解讀字串。response.setContentType(“html/texgt;charset=utf-8”);
4 response字元流的緩衝區
l response字元流緩衝區大小為8KB;
l 可以呼叫response.getWriter().flush()方法完成重新整理,這會把當前緩衝區中的資料傳送給客戶端。
l 當response一旦開始了傳送,那麼response的內部會有一個提交狀態為true。可以呼叫response的isCommitted()方法來檢視當前的提交狀態。
5 自動重新整理
l 有一個響應頭:Refresh,它的作用是在指定的時間後,自動重定向到指定路徑。例如:response.setHeader(“Refresh”, “5;URL=http://www.baidu.com”);,表示在5秒後自動跳轉到百度。
6 設定狀態碼
l response.sendError(404, “沒找到您訪問的資源”)
l response.sendStatus(302);
7 重定向
l 重定向:兩個請求。
Ø 第一個請求,伺服器響應碼:302
Ø 第一個請求的響應頭有一個Location頭,它說明了要重定向的URL;
Ø 第二個請求,瀏覽器重新向Location頭指定的URL發出。
l 重定向:可以重定向到本專案之外的頁面。例如可以重定向到百度!
l 重定向:可以重定向到本專案內的其他資源,可以使用相對路徑,以“/專案名”開頭
l 重定向:會使瀏覽器的位址列發生變化!
注意事項:
l 當response為以提交狀態,就不能再重定向了!
l 當使用了response的輸出流響應後,再重定向。如果沒有造成response提交,那麼說明資料還在緩衝區中,tomcat會把緩衝區清空,然後重定向。
request
post請求方式
l 有主體(正文)
l 有Content-Type,表示主體的型別,預設值為application/x-www-form-urlencoded;
2 request功能:
l 可以獲取請求方式:String getMethod()
l 可以獲取請求頭:String getHeader(String name)
l 可以獲取請求引數(包含主體或路徑後面的引數):String getParameter(String name)
3 請求編碼
l 位址列的引數是GBK的;
l 在頁面中點選連結或提交表單,引數都由當前頁面的編碼來決定,而頁面的編碼由當初伺服器響應的編碼來決定。
l 伺服器請求form.html,伺服器響應utf-8的頁面給瀏覽器,然後在form.html頁面上點選連結和提交表單傳送的引數都是utf-8。
l 如果伺服器的所有頁面都是utf-8的,那麼只要不在瀏覽器的位址列中給出中文,那麼其他的引數都是utf-8的。
伺服器:
l 伺服器預設使用ISO-8859-1來解讀請求資料。(tomcat7以前是這個編碼)
l 可以使用request.setCharacterEncoding(“utf-8”)設定編碼來解讀請求引數。這個方法只對請求主體有效,而GET請求沒有主體。說白了就是隻對POST請求有效!
l 設定Tomcat 其中GET請求的預設編碼:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/> |
l 因為編碼的設定不能依賴tomcat的配置,所以還是需要我們自己手動轉碼
Ø String name = request.getParamter(“username”);//使用預設的iso來解碼
Ø byte[] bytes = name.getBytes(“iso-8859-1”);//使用iso回退到位元組陣列
Ø name = new String(bytes, “utf-8”);//重新使用utf-8來解碼
4 獲取引數(詳細)
l *String getParameter(String name) :通過引數名稱獲取引數值!
l String[] getParameterValues(String name):通過引數名稱獲取多個引數值!一般複選框會出現一個名稱多個值的情況。
l *Map<String,String[]> getParameterMap():獲取所有引數,封裝到Map中,基引數名為key,引數值為value。
l Enumeration getParameterNames():獲取所有引數的名稱
5 request是Servlet三大域物件之
域功能:
l void setAttribute(String name,Object value)
l Object getAttribute(String name)
l void removeAttribute(String name)
request 的儲存範圍:整個請求鏈!如果一個請求經過了多個Servlet,那麼這些Servlet可以共享request域!
6 request獲取頭資訊
l String getHeader(String name):通過頭名稱,獲取頭資訊;
l Enumeration getHeaderNames() :獲取所有頭的名稱;
l Enumeration getHeaders(String name):通過頭名稱,獲取多個頭資訊;
l int getIntHeader(String name):通過頭名稱,獲取頭資訊,本方法再把String的頭資訊轉換成int型別。
7 reuqest的請求轉發
如何請求轉發
l 一個請求內經過多個資源(Servlet,還有jsp,而且經常是jsp)
l 請求轉發需要使用RequestDispatcher的forward(HttpServletRequest,HttpServletResponse)
l RequestDispatcher rd = request.getRequestDispatcher(“/BServlet”);//引數是要轉發的目標
l rd.forward(request,response);//轉發到BServlet
其實你可以理解成在一個Servlet中,呼叫另一個Servlet的service()方法。
請求轉發的注意事項
l 在第一個Servlet中可以使用request域儲存資料,在第二個Servlet中可以使用request域獲取資料。因為這兩個Servlet共享同一個request物件。
l
l 在轉發語句之後,其他語句是否會執行?答案是“可以”!
l 不能在一個Servlet中即重定向,又轉發。
請求轉發與重定向比較
l 請求轉發後,位址列中的地址不變!重定向變
l 請求轉發是一個請求,重定向是兩個請求;
l 請求轉發可以共享request域,而重定向因為是兩個請求,所以不能共享request。
l 一個請求,只有一個請求方式!所以轉發後還是原來的請求方式,如果一開始發出的是GET,那麼整個請求都是GET!重定向不同,因為是多個請求,第一個無論是什麼方式,第二個請求都是GET。
l 請轉轉發只能是本專案中的資源,而重定向可以其他專案。
如果要轉發,就不要輸出
l 如果輸出到緩衝區的資料,沒有提交,那麼在轉發時,緩衝區會被清空,如果已經提交,那麼在轉發時丟擲異常。這一點與重定向相同!
l 留頭不留體:在第一個Servlet中設定頭沒問題,會保留到下一個Servlet。如果在第一個Servlet中輸出資料,即設定響應體,那麼如果沒有提交,就被清空,如果已提交,就出異常。
8 請求包含
請求包含:
l RequestDispatcher rd = request.getRequestDispatcher(“/BServlet”);
l rd.include(request,response);
留頭又留體!
路徑
客戶端路徑:
1. 超連結:href=”/專案名/…”
2. 表單:action=”/專案名/…”
3. response.sendRedirect(“/專案名/…”);
如果客戶端路徑,沒有已“/專案名”開頭,那麼相對的是當前頁面所在路徑。
例如:http://localhost:8080/day10_3/a.html,當前頁面所在路徑是http://localhost:8080/day10_3/
以“/”開頭的客戶端路徑相對“http://localhost:8080”,<a href=”/hello/AServlet”>
伺服器端路徑:
轉發:必須使用“/”開頭,它相對當前專案,即http://localhost:8080/day10_3
包含:同上;
<url-pattern>:同上
ServletContext.getRealPath(“/a.jpg”):它是真對真實路徑,相對當前WebRoot
ServletContext.getResourceAsStream():同上
Class.getResourceAsStream():如果使用“/”開頭,相對classes,如果不使用“/”,相對當前.class檔案所在目錄。
ClassLoader. getResourceAsStream():無論使用不使用“/”開頭,都相對classes
編碼:
URL編碼
作用:為了在客戶端與伺服器之間傳遞中文!
把中文轉換成URL編碼:
Ø 首先你需要選擇一種字元編碼,然後把中文轉換成byte[]。
Ø 把每個位元組轉換成16進位制,前面新增上一個“%”。它不能顯負號,把得到的byte先加上128,這樣-128就是0了。正的127就是255了,它的範圍是%00~%FF
會話跟蹤技術Cookie &session
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()); cookie.setMaxAge(60 * 60); response.addCookie(cookie); Cookie[] cs = request.getCookies(); String s = "您是首次訪問本站!"; if(cs != null) { for(Cookie c : cs) { if(c.getName().equals("lasttime")) { s = "您上次的訪問時間是:" + c.getValue(); } } } response.getWriter().print(s); } |
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/jsp/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"); Cookie c = new Cookie(name, value); 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"); 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
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:登入頁面,提供登入表單;