servlet技術(shù)
1. HTTP協(xié)議
http 是一種應(yīng)用層的通信協(xié)議,一般包括了client和server端。clietn端的過程一般由瀏覽器執(zhí)行。服務(wù)器端是HTTP服務(wù)器。http協(xié)議定義客戶端和服務(wù)器端進(jìn)行交互的方式,最主要的是HTTP請求和響應(yīng)的報文格式。
HTTP報文分為三個部分,以請求為例:
- 請求行
- 報文頭
- 報文體
知道了大概的HTTP協(xié)議之后,下面介紹對HTTP報文進(jìn)行處理的服務(wù)端組件---Servlet.
2. servlet
servlet 即 server applet, 所以可以說servlet是運行在服務(wù)端的java程序。 servlet是特殊的java類, 其運行在容器中。其特殊在Servlet中沒有main方法。所以Servlet只能由其他類調(diào)用執(zhí)行。
servlet一個基本的定義如下:servlet就是一個java類,并提供基于請求和響應(yīng)模式的web服務(wù)。 換句話說,其是用Java編寫的服務(wù)器端程序。其主要功能在于交互式地瀏覽和修改數(shù)據(jù),生成動態(tài)Web內(nèi)容。
Servlet沒有main()方法,他們受控于另外的一個JAVA應(yīng)用,這個JAVA應(yīng)用稱為容器。
2.1 servlet和servlet容器
servlet相當(dāng)于真正對用戶請求進(jìn)行處理的組件(類),而容器是對容器是對這些資源進(jìn)行管理的。
其中tomcat就是一種web容器,其他的web容器有.....
容器提供的功能有:
- 通信支持
容器使得Servlet能夠輕松的與web服務(wù)器對話,而不用考慮通信細(xì)節(jié), - 生命周期管理
- 容器控制Servlet的加載,初始化,以及銷毀
- 多線程支持
- 容器自動的為它接收到的Servlet請求創(chuàng)建一個線程。
- 聲明安全
- 使用容器,可以使用xml的方式對應(yīng)用進(jìn)行聲明式部署。
- JSP支持
2.2工作流程
下面描述一次web請求的工作流程。
- 用戶發(fā)送http請求到服務(wù)器端
- 服務(wù)器端的web容器接收到請求報文,對其進(jìn)行解析
- 生成HttpServletRequest和HttpServletRequest實例
- 容器根據(jù)請求中的URL找到相應(yīng)的Servlet, 并為這個請求創(chuàng)建或分配一個線程,并把請求和響應(yīng)對象傳遞給Servlet線程
- 容器調(diào)用Servlet的Service()方法。該方法根據(jù)請求的不同類型,調(diào)用doGet方法或者doPost方法。
2.3 接口于實現(xiàn)類
servlet的接口,以及實現(xiàn)的類
2.4 servlet的生命周期
下面是整個的servlet的生命周期 P132
- 容器加載類,調(diào)Servlet的無參構(gòu)造器,并調(diào)動Servlet的inti()方法,從而初始化Servlet
- Init方法,在Servlet一生中只調(diào)用一次,往往為Servlet為客戶請求提供服務(wù)前調(diào)用
- int()方法使得Servlet可以訪問ServletConfig和ServletContext
- 請求到來,Servlet執(zhí)行service方法
- 對Servlet的每個請求都在一個單獨的線程中運行,任何特定的Servlet類都只有一個實例。
- 容器調(diào)用Servlet中的destroy方法結(jié)束Servlet的生命
Get于POST的區(qū)別
總體上說區(qū)別如下:
- 傳輸方式
- HTTP header 和HTTP body
- URL 可見和URL 不可見
- 設(shè)計目的
- 獲取數(shù)據(jù) 和發(fā)送數(shù)據(jù)
- 安全性
- 高和低。
具體上二者的區(qū)別如下:
- POST方法的消息報文擁有報文體,而Get方法的沒有。雖然二者都可以傳送參數(shù),但是Get的參數(shù)被限制到請求行中。
- Get方法獲取數(shù)據(jù)時,參數(shù)直接顯示在瀏覽器地址欄中;而POST方法的參數(shù)不會顯示在地址欄中
- Get設(shè)計用于獲取數(shù)據(jù),POST設(shè)計用于推送數(shù)據(jù)
- Get方法是冪等的,POST方法不是冪等的。
請求和響應(yīng)
請求
請求對應(yīng)著HTTP的請求報文,請求報文由三部分組成:請求行,請求頭部,請求體。
從請求中可以獲得的參數(shù)包含了這三部分的信息。
具體的API可以查看官方文檔。
響應(yīng)
大多數(shù)時候,使用響應(yīng)知識為了向客戶發(fā)送數(shù)據(jù),以下兩個方法較為常見:
setContentType
getWriter
重定向和委托
請求重定向
即通過response對象發(fā)送給瀏覽器一個新的url地址,讓其重新請求。該過程包含了兩次請求,兩次響應(yīng)。
該步驟如下:
- 客戶像瀏覽器地址鍵入一個URL
- 請求到達(dá)服務(wù)器/容器
- Servlet決定這個請求應(yīng)當(dāng)重定向到另一個完全不同的URL
- Servlet在響應(yīng)上調(diào)用sendRedirect(astring)
- Http響應(yīng)中含有一個狀態(tài)碼"301", 還有一個Location首部,該值是一個URL。
- 瀏覽器得到響應(yīng),發(fā)現(xiàn)了“301”狀態(tài)碼,并尋找Location首部
- 瀏覽器使用該Location中的值重新建立請求,此時瀏覽器地址欄的URL發(fā)生變化
- 用戶得到新的請求結(jié)果。
sendRedirect(String address)取一個String作為參數(shù),而不是URL對象。
注意:: address是重定向的路徑,該路徑可以是絕對路徑也可以是相對路徑,因為重定向可以重定向到其他站點,所以使用絕對路徑時,需要寫明web站點的全稱,例如:"/web_project/send_redict".當(dāng)使用相對路徑,默認(rèn)的就是重定向到當(dāng)前的站點的路徑下面。此時只用寫"send_redict".
請求分派/轉(zhuǎn)發(fā)
大致的工作流程如下:
- 用戶在瀏覽器的地址欄鍵入URL
- 請求到達(dá)服務(wù)器
- Servlet決定這個請求應(yīng)該分配給web應(yīng)用的另一部分
- Servlet調(diào)用如下代碼:
RequestDispatcher view= request.getRequestDispatcher("result.jsp")
view.forward(request, response);
- 此時Jsp 接管該請求和響應(yīng)
- 瀏覽器以正常的方式得到響應(yīng),顯示給用戶,瀏覽器的地址欄并沒有變化,所以用戶不知道是由JSP生成的響應(yīng)
上面中的result.jsp是處理該請求的新對象,其一般的是一個地址,其實轉(zhuǎn)發(fā)的路徑,其可以是相對路徑,也可以是絕對路徑,對于絕對路徑(該路徑在servlet-mapping中配置過,所以有相應(yīng)的servlet進(jìn)行處理)。例如上面的代碼同樣可以寫成:
RequestDispatcher view= request.getRequestDispatcher("/forwardExample")
view.forward(request, response);
<servlet-mapping>
<servlet-name>ServletForwardExample</servlet-name>
<url-pattern>forwardExample</url-pattern>
</servlet-mapping>
請求轉(zhuǎn)發(fā)對象不僅僅可以通過request對象獲得,也可以通過servletContext對象。下面是例子:
rd=this.getServletContext().getNamedDipather("ServletForwardExample") //這里的參數(shù)是servlet的名字,需要在web.xml中配置過的
rd=this.getServletContext().getRequestDispatcher("/forwardExample") //這里只能填寫絕對路徑
注意的是通過ServletContext獲取的話參數(shù)的設(shè)置。
RequestDispatcher 包含兩個方法:forward()和include方法。forward()方法較為常見。
區(qū)別
- 瀏覽器地址欄變化
轉(zhuǎn)發(fā)時地址不變化,重定向地址變化 - 請求范圍
重定向可以重定向到站外資源,轉(zhuǎn)發(fā)時不行 - 請求過程
- 轉(zhuǎn)發(fā)時一次請求轉(zhuǎn)發(fā),重定向是兩次請求,兩次響應(yīng)。
servlet 配置信息
分為兩種配置,局部配置 和全局配置
- servletConfig針對具體的Servlet的config
- ServletContext代表該web應(yīng)用的config
上面的參數(shù)針對之前已知的信息,且因為參數(shù)只是容器啟動或者Servlet初始化調(diào)用才進(jìn)行讀取,構(gòu)造嗎,所以servletConfig,ServletContext中的配置信息在運行期間不變,除非重新啟動,部署。
如果不同的Servlet之間的共享信息不是事先知道的呢? 屬性信息
屬性
屬性就是一個對象,設(shè)置到另外的三個Servlet對象中-ServletContext, HttpServletRequest, HttpSession中去的。
屬性Vs參數(shù)

屬性是可變的,所以就意味著其存在安全你性問題。所以有下面對于servlet的并發(fā)運行的安全問題。
讀取外部資源配置文件信息,三個方法:
參見: http://blog.csdn.net/mr_li13/article/details/48598361
http://blog.csdn.net/u011702171/article/details/50908407
監(jiān)聽器和過濾器
過濾器
- 過濾請求和響應(yīng)
- 自定義過濾規(guī)則
- 用于對用戶請求進(jìn)行預(yù)處理,和對請求響應(yīng)進(jìn)行后處理的web應(yīng)用組件。
常用的場景
- 用戶認(rèn)證
- 編解碼處理
- 數(shù)據(jù)壓縮處理
過濾器生命周期
只會創(chuàng)建一次
監(jiān)聽器
- 監(jiān)聽事件發(fā)生,在時間發(fā)生前做出相應(yīng)處理的web組件
分類 - 監(jiān)聽?wèi)?yīng)用程序環(huán)境Servletcontext
- 監(jiān)聽用戶請求對象 ServletRequest
- 監(jiān)聽用戶會話對象Httpsession
監(jiān)聽器的應(yīng)用場景
- 應(yīng)用統(tǒng)計
- 任務(wù)觸發(fā)
會話管理
使用場景
- 記錄用戶偏好
- 記錄用戶登錄狀態(tài)
- 瀏覽記錄
原理
客戶端或者服務(wù)器端保存用戶數(shù)據(jù)。因為Http協(xié)議是無狀態(tài)的。
兩種會話管理方式
- cookie: 會話數(shù)據(jù)保存在客戶端
- session. 會話數(shù)據(jù)保存在服務(wù)器端
cookie的工作原理
目的:: 因為Http協(xié)議是無狀態(tài)的,所以Cookie被設(shè)計用來保存和識別用戶。
形式:
- 會話數(shù)據(jù)
- 保存在客戶端
- key-value的形式
下面幾篇文章介紹了session和cookie的原理,參考我文獻(xiàn)也很重要:
http://blog.csdn.net/guoweimelon/article/details/50886092
http://www.sohu.com/a/100667614_448410
區(qū)別:
cookie 和session 的區(qū)別:
cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上。
cookie不是很安全,別人可以分析存放在本地的COOKIE并進(jìn)行COOKIE欺騙
考慮到安全應(yīng)當(dāng)使用session。session會在一定時間內(nèi)保存在服務(wù)器上。當(dāng)訪問增多,會比較占用你服務(wù)器的性能
考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用COOKIE。單個cookie保存的數(shù)據(jù)不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
生命周期上的不同: cookie 是累計時間的,即到點就失效的, session是間隔性的失效的,比如設(shè)置20分鐘失效,這個時間是從最后一次訪問session的時間開始算的。
session也可以直接調(diào)用api來使session失效。
web 應(yīng)用程序結(jié)構(gòu)
- 靜態(tài)文件
- META-INF 元信息
- WEB-INF
- class
- lib
- web.xml 部署描述符,描述一個web程序
首先是個XML文件 ,
其次是設(shè)置web應(yīng)用程序的組件部署信息
servlet容器需要支持部署描述符的所有元素
DD配置
映射
<load-on_startup>改變servlet默認(rèn)的初始化時間。
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<welcome-file-list>
</welcome-file-list>
參考:http://blog.csdn.net/guihaijinfen/article/details/8363839
在web.xml文件中同樣可以配置<mime-mapping>,其可以對制定的文件制定打開方式。
可以參考:http://jxdwuao.iteye.com/blog/1637809
Servlet并發(fā)處理

特點:
- 單實例
- 多線程
- 線程不安全
servlet線程安全
- 變量的線程安全
- 參數(shù)變量本地化
- 使用同步塊synchronized
- 屬性的線程安全
- ServletContext線程不安全
- HttpSession理論上線程安全
- ServletRequest線程安全的
- 避免在Servlet中創(chuàng)建線程
- 多個Servlet訪問外部對象加鎖
容器啟動組件順序: 監(jiān)聽器,過濾器,servlet
JSP
JSP 中的六種指令
JSP指令
- 腳本代碼 <% code %>
- 指令 <%@ Instruction %>
- 表達(dá)式 <%= %>
- 聲明 <%! %>
- 注釋 <%% -- z注釋 -->
6種指令在生成代碼的不同。與注意事項。
下圖顯示了容器如何處理JSP:

JSP聲明
- 一個聲明語句可以聲明一個或多個變量,方法,供后面的JAVA代碼使用
- <% !%>
- 表達(dá)式元素中可以包含任何符合JAVA語言規(guī)范的表達(dá)式
- <% = % >
jsp 腳本
- 腳本程序可以包含任意的JAVA程序
JSP注釋
<% -- 注釋內(nèi)容--%>
JSP指令
主要設(shè)置JSP頁面的屬性
- page指令
- 定義頁面的依賴屬性,比如腳本語言,error頁面,緩存需求等
- include指令
- 包含其他文件 - taglib指令
JSP內(nèi)置對象
可以直接使用而不用申請
