servlet技術
1. HTTP協議
http 是一種應用層的通信協議,一般包括了client和server端。clietn端的過程一般由瀏覽器執行。服務器端是HTTP服務器。http協議定義客戶端和服務器端進行交互的方式,最主要的是HTTP請求和響應的報文格式。
HTTP報文分為三個部分,以請求為例:
- 請求行
- 報文頭
- 報文體
知道了大概的HTTP協議之后,下面介紹對HTTP報文進行處理的服務端組件---Servlet.
2. servlet
servlet 即 server applet, 所以可以說servlet是運行在服務端的java程序。 servlet是特殊的java類, 其運行在容器中。其特殊在Servlet中沒有main方法。所以Servlet只能由其他類調用執行。
servlet一個基本的定義如下:servlet就是一個java類,并提供基于請求和響應模式的web服務。 換句話說,其是用Java編寫的服務器端程序。其主要功能在于交互式地瀏覽和修改數據,生成動態Web內容。
Servlet沒有main()方法,他們受控于另外的一個JAVA應用,這個JAVA應用稱為容器。
2.1 servlet和servlet容器
servlet相當于真正對用戶請求進行處理的組件(類),而容器是對容器是對這些資源進行管理的。
其中tomcat就是一種web容器,其他的web容器有.....
容器提供的功能有:
- 通信支持
容器使得Servlet能夠輕松的與web服務器對話,而不用考慮通信細節, - 生命周期管理
- 容器控制Servlet的加載,初始化,以及銷毀
- 多線程支持
- 容器自動的為它接收到的Servlet請求創建一個線程。
- 聲明安全
- 使用容器,可以使用xml的方式對應用進行聲明式部署。
- JSP支持
2.2工作流程
下面描述一次web請求的工作流程。
- 用戶發送http請求到服務器端
- 服務器端的web容器接收到請求報文,對其進行解析
- 生成HttpServletRequest和HttpServletRequest實例
- 容器根據請求中的URL找到相應的Servlet, 并為這個請求創建或分配一個線程,并把請求和響應對象傳遞給Servlet線程
- 容器調用Servlet的Service()方法。該方法根據請求的不同類型,調用doGet方法或者doPost方法。
2.3 接口于實現類
servlet的接口,以及實現的類
2.4 servlet的生命周期
下面是整個的servlet的生命周期 P132
- 容器加載類,調Servlet的無參構造器,并調動Servlet的inti()方法,從而初始化Servlet
- Init方法,在Servlet一生中只調用一次,往往為Servlet為客戶請求提供服務前調用
- int()方法使得Servlet可以訪問ServletConfig和ServletContext
- 請求到來,Servlet執行service方法
- 對Servlet的每個請求都在一個單獨的線程中運行,任何特定的Servlet類都只有一個實例。
- 容器調用Servlet中的destroy方法結束Servlet的生命
Get于POST的區別
總體上說區別如下:
- 傳輸方式
- HTTP header 和HTTP body
- URL 可見和URL 不可見
- 設計目的
- 獲取數據 和發送數據
- 安全性
- 高和低。
具體上二者的區別如下:
- POST方法的消息報文擁有報文體,而Get方法的沒有。雖然二者都可以傳送參數,但是Get的參數被限制到請求行中。
- Get方法獲取數據時,參數直接顯示在瀏覽器地址欄中;而POST方法的參數不會顯示在地址欄中
- Get設計用于獲取數據,POST設計用于推送數據
- Get方法是冪等的,POST方法不是冪等的。
請求和響應
請求
請求對應著HTTP的請求報文,請求報文由三部分組成:請求行,請求頭部,請求體。
從請求中可以獲得的參數包含了這三部分的信息。
具體的API可以查看官方文檔。
響應
大多數時候,使用響應知識為了向客戶發送數據,以下兩個方法較為常見:
setContentType
getWriter
重定向和委托
請求重定向
即通過response對象發送給瀏覽器一個新的url地址,讓其重新請求。該過程包含了兩次請求,兩次響應。
該步驟如下:
- 客戶像瀏覽器地址鍵入一個URL
- 請求到達服務器/容器
- Servlet決定這個請求應當重定向到另一個完全不同的URL
- Servlet在響應上調用sendRedirect(astring)
- Http響應中含有一個狀態碼"301", 還有一個Location首部,該值是一個URL。
- 瀏覽器得到響應,發現了“301”狀態碼,并尋找Location首部
- 瀏覽器使用該Location中的值重新建立請求,此時瀏覽器地址欄的URL發生變化
- 用戶得到新的請求結果。
sendRedirect(String address)取一個String作為參數,而不是URL對象。
注意:: address是重定向的路徑,該路徑可以是絕對路徑也可以是相對路徑,因為重定向可以重定向到其他站點,所以使用絕對路徑時,需要寫明web站點的全稱,例如:"/web_project/send_redict".當使用相對路徑,默認的就是重定向到當前的站點的路徑下面。此時只用寫"send_redict".
請求分派/轉發
大致的工作流程如下:
- 用戶在瀏覽器的地址欄鍵入URL
- 請求到達服務器
- Servlet決定這個請求應該分配給web應用的另一部分
- Servlet調用如下代碼:
RequestDispatcher view= request.getRequestDispatcher("result.jsp")
view.forward(request, response);
- 此時Jsp 接管該請求和響應
- 瀏覽器以正常的方式得到響應,顯示給用戶,瀏覽器的地址欄并沒有變化,所以用戶不知道是由JSP生成的響應
上面中的result.jsp是處理該請求的新對象,其一般的是一個地址,其實轉發的路徑,其可以是相對路徑,也可以是絕對路徑,對于絕對路徑(該路徑在servlet-mapping中配置過,所以有相應的servlet進行處理)。例如上面的代碼同樣可以寫成:
RequestDispatcher view= request.getRequestDispatcher("/forwardExample")
view.forward(request, response);
<servlet-mapping>
<servlet-name>ServletForwardExample</servlet-name>
<url-pattern>forwardExample</url-pattern>
</servlet-mapping>
請求轉發對象不僅僅可以通過request對象獲得,也可以通過servletContext對象。下面是例子:
rd=this.getServletContext().getNamedDipather("ServletForwardExample") //這里的參數是servlet的名字,需要在web.xml中配置過的
rd=this.getServletContext().getRequestDispatcher("/forwardExample") //這里只能填寫絕對路徑
注意的是通過ServletContext獲取的話參數的設置。
RequestDispatcher 包含兩個方法:forward()和include方法。forward()方法較為常見。
區別
- 瀏覽器地址欄變化
轉發時地址不變化,重定向地址變化 - 請求范圍
重定向可以重定向到站外資源,轉發時不行 - 請求過程
- 轉發時一次請求轉發,重定向是兩次請求,兩次響應。
servlet 配置信息
分為兩種配置,局部配置 和全局配置
- servletConfig針對具體的Servlet的config
- ServletContext代表該web應用的config
上面的參數針對之前已知的信息,且因為參數只是容器啟動或者Servlet初始化調用才進行讀取,構造嗎,所以servletConfig,ServletContext中的配置信息在運行期間不變,除非重新啟動,部署。
如果不同的Servlet之間的共享信息不是事先知道的呢? 屬性信息
屬性
屬性就是一個對象,設置到另外的三個Servlet對象中-ServletContext, HttpServletRequest, HttpSession中去的。
屬性Vs參數
屬性是可變的,所以就意味著其存在安全你性問題。所以有下面對于servlet的并發運行的安全問題。
讀取外部資源配置文件信息,三個方法:
參見: http://blog.csdn.net/mr_li13/article/details/48598361
http://blog.csdn.net/u011702171/article/details/50908407
監聽器和過濾器
過濾器
- 過濾請求和響應
- 自定義過濾規則
- 用于對用戶請求進行預處理,和對請求響應進行后處理的web應用組件。
常用的場景
- 用戶認證
- 編解碼處理
- 數據壓縮處理
過濾器生命周期
只會創建一次
監聽器
- 監聽事件發生,在時間發生前做出相應處理的web組件
分類 - 監聽應用程序環境Servletcontext
- 監聽用戶請求對象 ServletRequest
- 監聽用戶會話對象Httpsession
監聽器的應用場景
- 應用統計
- 任務觸發
會話管理
使用場景
- 記錄用戶偏好
- 記錄用戶登錄狀態
- 瀏覽記錄
原理
客戶端或者服務器端保存用戶數據。因為Http協議是無狀態的。
兩種會話管理方式
- cookie: 會話數據保存在客戶端
- session. 會話數據保存在服務器端
cookie的工作原理
目的:: 因為Http協議是無狀態的,所以Cookie被設計用來保存和識別用戶。
形式:
- 會話數據
- 保存在客戶端
- key-value的形式
下面幾篇文章介紹了session和cookie的原理,參考我文獻也很重要:
http://blog.csdn.net/guoweimelon/article/details/50886092
http://www.sohu.com/a/100667614_448410
區別:
cookie 和session 的區別:
cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
cookie不是很安全,別人可以分析存放在本地的COOKIE并進行COOKIE欺騙
考慮到安全應當使用session。session會在一定時間內保存在服務器上。當訪問增多,會比較占用你服務器的性能
考慮到減輕服務器性能方面,應當使用COOKIE。單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
生命周期上的不同: cookie 是累計時間的,即到點就失效的, session是間隔性的失效的,比如設置20分鐘失效,這個時間是從最后一次訪問session的時間開始算的。
session也可以直接調用api來使session失效。
web 應用程序結構
- 靜態文件
- META-INF 元信息
- WEB-INF
- class
- lib
- web.xml 部署描述符,描述一個web程序
首先是個XML文件 ,
其次是設置web應用程序的組件部署信息
servlet容器需要支持部署描述符的所有元素
DD配置
映射
<load-on_startup>改變servlet默認的初始化時間。
<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并發處理
特點:
- 單實例
- 多線程
- 線程不安全
servlet線程安全
- 變量的線程安全
- 參數變量本地化
- 使用同步塊synchronized
- 屬性的線程安全
- ServletContext線程不安全
- HttpSession理論上線程安全
- ServletRequest線程安全的
- 避免在Servlet中創建線程
- 多個Servlet訪問外部對象加鎖
容器啟動組件順序: 監聽器,過濾器,servlet
JSP
JSP 中的六種指令
JSP指令
- 腳本代碼 <% code %>
- 指令 <%@ Instruction %>
- 表達式 <%= %>
- 聲明 <%! %>
- 注釋 <%% -- z注釋 -->
6種指令在生成代碼的不同。與注意事項。
下圖顯示了容器如何處理JSP:
JSP聲明
- 一個聲明語句可以聲明一個或多個變量,方法,供后面的JAVA代碼使用
- <% !%>
- 表達式元素中可以包含任何符合JAVA語言規范的表達式
- <% = % >
jsp 腳本
- 腳本程序可以包含任意的JAVA程序
JSP注釋
<% -- 注釋內容--%>
JSP指令
主要設置JSP頁面的屬性
- page指令
- 定義頁面的依賴屬性,比如腳本語言,error頁面,緩存需求等
- include指令
- 包含其他文件 - taglib指令
JSP內置對象
可以直接使用而不用申請