Servlet

什么是Servlet

  • sun公司制定一種擴展Web服務器功能的組件規(guī)范

擴展Web服務器功能

  • web服務器只能夠處理靜態(tài)的資源請求(需要事先將HTML文件寫好),不能夠處理動態(tài)資源請求(需要計算生成HTML),所有需要擴展??梢允褂肧ervlet來擴展web服務器功能,當web服務器收到請求之后,如果需要計算,則交給Servlet來處理。
  • 注:常見的文本服務器:Apache,iis,nginx等。

組件規(guī)范

  • 什么是組件:符合規(guī)范,實現(xiàn)部分功能,并且部署到相應的容器里面才能運行的軟件模塊。Servlet就是一個組件,需要部署到Servlet容器里面才能運行。
  • 什么是容器:符合規(guī)范,提供組件的運行環(huán)境的程序。Tomcat就是一個Servlet容器,為Servlet提供運行環(huán)境(提供網(wǎng)絡相關的服務)

如何寫Servlet

1、寫一個java類,實現(xiàn)Servlet接口或者繼承HttpServlet類(通常繼承HttpServlet)。
2、編譯。
3、打包。即創(chuàng)建一個具有如下結構的文件夾。
appname(應用名)
WEB-INF
classes(.class)
lib(.jar)
web.xml(部署描述文件)
html文件
4、部署。將第三步創(chuàng)建好的文件夾拷貝到容器響應的位置。[可以將整個文件夾使用jar先壓縮成.war為后綴的文件,然后在拷貝。]
5、啟動容器,訪問Servlet。
http://ip:port/appname/url-pattern
url-pattern在web.xml當中配置

Servlet是如何運行的

比如,在瀏覽器輸入 http://ip:port/day01/hello
1、瀏覽器依據(jù)ip和port建立連接。
2、瀏覽器將相關數(shù)據(jù)放到請求數(shù)據(jù)包中,然后發(fā)送給服務器。
3、服務器解析請求數(shù)據(jù)包,將解析到的數(shù)據(jù)添加到request對象,同時創(chuàng)建一個response對象。
4、服務器創(chuàng)建Servlet對象,然后調(diào)用該對象的service方法。
注:服務器會將request和response對象作為參數(shù)傳遞過來,開發(fā)人員只需要調(diào)用這兩個對象的方法就可以了,不用考慮網(wǎng)絡相關問題。比如,要讀取請求數(shù)據(jù)包中的數(shù)據(jù),只需要調(diào)用request對象的方法就可以了。類似的,要向瀏覽器發(fā)送處理結果,只需要調(diào)用response對象的方法就可以了。
5、服務器從response對象中獲得處理結果,然后創(chuàng)建響應數(shù)據(jù)包并發(fā)送給瀏覽器。
6、瀏覽器解析響應數(shù)據(jù)包,生成相應的頁面。

常見的問題

  • 404
    1、含義:服務器依據(jù)請求路徑找不到對應的資源。
    2、產(chǎn)業(yè)原因:a、請求路徑寫錯。b、應用沒有部署或者部署失敗。
  • 500
    1、含義:系統(tǒng)出錯。
    2、產(chǎn)生原因:a、沒有嚴格按照規(guī)范些代碼(包括部署描述寫錯)b、代碼不嚴謹(比如請求參數(shù)不做檢查,直接類型轉換)
  • 405
    1、含義:找不到處理方法
    2、產(chǎn)生原因:service方法沒有正確重寫

http協(xié)議

  • 什么是http協(xié)議
    是一種網(wǎng)絡應用層協(xié)議,規(guī)定了瀏覽器與web服務器之間如何通信以及相應的數(shù)據(jù)結構。
    a、tcp/ip協(xié)議:屬于傳遞層和網(wǎng)絡層協(xié)議,保證數(shù)據(jù)可靠的傳遞。http協(xié)議屬于應用層協(xié)議,需要依賴tcp/ip協(xié)議來傳遞數(shù)據(jù)包。
    b、瀏覽器與web服務器之間如何通信:建立連接,發(fā)送請求,發(fā)送響應,關閉連接
    特點:一次請求,一次連接
    這樣做的好處是服務器可以利用有限的連接做盡可能多的請求服務

  • 數(shù)據(jù)包的結構
    1)請求數(shù)據(jù)包
    a、請求行(請求方式,請求資源路徑,協(xié)議版本)

     b、消息頭
         消息頭四一些鍵值對(使用“: ”分隔),瀏覽器與web服務器之間可以通過消息頭來傳遞一些特點的信息。比如,瀏覽器可以通過發(fā)送“user-age”消息頭,告訴瀏覽器的類型和版本。
         
     c、實體類容
         只有當請求方式有post時,實體內(nèi)容才會有數(shù)據(jù),請求方式為get時,實體內(nèi)容為空。
    

    2)響應數(shù)據(jù)包
    a、狀態(tài)行(協(xié)議版本和狀態(tài)碼,狀態(tài)描述)
    200 :正常
    500 :系統(tǒng)出錯
    404 :請求路徑出錯
    b、消息頭
    服務器也可以發(fā)送一些消息頭給瀏覽器,比如,可以發(fā)送“content-Type”消息頭,告訴瀏覽器,服務器返回的數(shù)據(jù)類型
    c、實體內(nèi)容
    程序處理結果,瀏覽器會解析出來,生成相應的頁面。

  • 兩種請求方式
    (1)get請求
    a、哪些情況瀏覽器會發(fā)送get請求?
    在瀏覽器地址欄直接輸入某個地址
    點擊鏈接
    表單默認的提交方式
    b、特點
    會將請求參數(shù)添加到請求資源路徑的后面,只能提交少量的數(shù)據(jù)(2k)給服務器。
    會將請求參數(shù)顯示在瀏覽器地址欄,不安全
    (2)post請求
    a、哪些情況下,瀏覽器會發(fā)送post請求
    將表單的method屬性設置為post
    b、特點
    會將請求參數(shù)添加到實體類容中,可以提交大量的數(shù)據(jù)給服務器
    不會將請求參數(shù)顯示在瀏覽器地址欄,相對安全
    (http協(xié)議并不會對數(shù)據(jù)加密,所有對于敏感數(shù)據(jù)需要進行加密)

Servlet輸出中文如何處理

  • 為什么吹產(chǎn)生亂碼?
    out.println()默認使用ISO-8859-1來編碼(不支持中文)
  • 處理response.setContentType("text/html;charset=utf-8");

如何讀取參數(shù)值

request.getParameter(String paramName)

  • 如果請求參數(shù)名寫錯,獲得null
  • 表單提交時,不填寫任何數(shù)據(jù),會獲得空字符串

String[] request.getParameterValues(String paramName)

  • 當有多個請求參數(shù)名相同時,使用此方法
  • 對于多選框和單選框,如果一個都不選,會獲得null值

表單包含有中文參數(shù),如何處理

  • 為什么會有亂碼
    當提交表單時,瀏覽器會按照打開該表單所在的頁面時的字符集來對中文參數(shù)進行編碼。比如使用utf-8來編碼,而服務器端默認使用ISO-8859-1來解碼。所有會產(chǎn)生亂碼
  • 如何處理
    -- get請求:可以修改服務器端的配置,在servers中的server.xml添加URIEncoding="utf-8"
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="utf-8" />
    -- post請求:request.setCharacterEncoding(String charset);

DAO (Data Access Object )

  • 什么是DAO:封裝了數(shù)據(jù)訪問邏輯的對象
  • 如何寫DAO:
    1、寫一個java類,用于存放從數(shù)據(jù)庫中查詢得到的數(shù)據(jù)。
    2、寫DAO類,該類封裝了數(shù)據(jù)庫訪問邏輯。
  • DAO的優(yōu)點:
    a、方便測試:比如,如果將數(shù)據(jù)庫訪問代碼寫在Servlet里面,需要部署應用才能測試。而將數(shù)據(jù)庫訪問代碼寫在DAO類里面,可以直接測試。
    b、方便分工協(xié)作
    c、方便代碼的維護:比如,數(shù)據(jù)訪問邏輯發(fā)送改變,不會影響到Servlet。

重定向

  • 什么是重定向:服務器通知瀏覽器向某個地址欄發(fā)送請求。
    服務器通過發(fā)送302狀態(tài)碼和Location消息頭(該消息頭的值是一個地址,一般稱為重定向地址),瀏覽器收到之后,會立即向重定向地址發(fā)送請求。
  • 如何重定向:response.sendRedirect(String url);
  • 重定向的細節(jié):重定向之前,容器會先清空response對象上存放的所有數(shù)據(jù)。(實體內(nèi)容為空)
  • 特點:
    a、重定向的地址是任意的。
    b、重定向之后,瀏覽器地址欄會發(fā)送變化。

jsp

  • jsp是什么:jsp是sun公司制定的一種服務端的動態(tài)技術規(guī)范。
    因為雖然可以使用Servlet生成動態(tài)頁面,但是過于繁瑣,不好維護,所以sun才制訂jsp規(guī)范。jsp是一個以.jsp為后綴的文件(主要內(nèi)容為HTML和少量的java代碼),容器會將jsp文件轉換為一個對應的Servlet然后執(zhí)行。
    jsp本質就是一個Servlet!
  • jsp文件中可以添加哪些內(nèi)容
    1、html(css,javascript)直接寫即可。
    2、java代碼
    方式一:java代碼片段
    <% java代碼 %>
    方式二:jsp表達式
    <%= java表達式 %>
  • jsp是如何執(zhí)行的
    1、階段1:容器先將jsp轉換成一個對應的Servlet
    html(css,JavaScript)------>在service方法里面,使用out.write輸出。
    <% %> ------->在service方法里面,照搬。
    <%= %> ---------->在service方法里面,使用out.print輸出
    2、階段2:容器調(diào)用該Servlet
    需要將Servlet編譯,然后實例化,調(diào)用對應的service方法。
  • 隱含對象
    a、什么是隱含對象:直接可以使用的對象。
    b、為什么可以直接使用隱含對象:容器在將jsp轉換成對應的Servlet時,會自動添加獲得這些對象代碼。

指令

  • 什么是指令:通過指令,可以告訴容器在將jsp轉換成Servlet時做一些額外的處理。
  • 語法:<%@ 指令名 屬性="值" %>
    注:如果有多個屬性,使用空格隔開
  • page指令
    import屬性:指定要導入的包名
    <%@ page import="java.util.,java.text." %>
    contentType屬性:指定response.setContentType方法的屬性值
    pageEncoding屬性:告訴容器,在讀取jsp文件的內(nèi)容時,使用該屬性指定的字符集編碼

轉發(fā)

  • 什么是轉發(fā):一個web組件將未完成的處理,通過容器交給另外一個web組件繼續(xù)做。
    注:web組件指的是servlet或者jsp。
  • 如何轉發(fā):
    1、綁定數(shù)據(jù)到request對象上。
    request.setAttribute(String name,Object);
    注:name:綁定名 obj:綁定值
    String request.getAttribute(String name);
    2、獲得轉發(fā)器
    RequestDispatcher rd = request.getRequestDispatcher(String url);
    注:url是轉發(fā)的地址,通常是一個jsp
    3、轉發(fā)
    rd.forward(request,response);
  • 轉發(fā)的特點:
    1、轉發(fā)的地址是有限制的,要求時同一個web應用。
    2、轉發(fā)之后,瀏覽器地址沒有改變。

轉發(fā)與重定向的區(qū)別

  • 能否共享request對象
    轉發(fā)可以,重定向不可以
    當請求到達容器,容器會創(chuàng)建request對象和response對象,當響應發(fā)送完畢,容器會銷毀這兩個對象。也就是說,request對象和response對象的生存時間是一次請求和響應期間存在的。
  • 目的地是否有限制
    轉發(fā)有限制,重定向沒有。
    轉發(fā)地址要求屬于同一個web應用,重定向地址是任意的。
  • 瀏覽器的地址欄的地址有無變化
    轉發(fā)沒有,重定向有變化。
  • 一件事是否已經(jīng)做完
    轉發(fā)是一件事沒有做完,讓另外一個web組件繼續(xù)做;而重定向是一件事已經(jīng)做完,再做另外一件事。

狀態(tài)管理

  • 什么是狀態(tài)管理
    將瀏覽器與web服務器之間多次交互當做一個整體來處理,并且將多次交互所涉及的數(shù)據(jù)(即狀態(tài))保存下來。
  • 如何進行狀態(tài)管理
    a、將狀態(tài)保存在瀏覽器(Cookie)
    b、將狀態(tài)保存在服務端(Session)

Cookie

  • 什么是Cookie
    服務器臨時存放在瀏覽器端的少量數(shù)據(jù),用于跟蹤用戶的狀態(tài)。
  • 工作原理
    當瀏覽器訪問服務器時,服務器會將少量數(shù)據(jù)以set-cookie消息頭的方式發(fā)生給瀏覽器,瀏覽器會將這些數(shù)據(jù)臨時保存下來;當瀏覽器再次訪問服務器時,會將這些數(shù)據(jù)以cookie消息頭的方式發(fā)生給服務器。
  • 添加Cookie
    Cookie c = new Cookie(STring name,String value);
    response.addCookie(c);
    注:cookie只能存放字符串
  • 讀取COokie
    Cookie[] request.getCookies();
    String cookie.getName();
    String cookie.getValue();
  • cookie的生存時間
    默認情況下,瀏覽器會將cookie保存在內(nèi)存里。瀏覽器關閉,則cookie會被刪除
    cookie.setMaxAge(int seconds);
    注:a、單位是秒
    b、當seconds>0時,瀏覽器會將cookie保存在硬盤上,當超過指定時間,cookie會被刪除。
    c、當seconds<0時,瀏覽器會將cookie保存在內(nèi)存里面。
    d、當seconds=0時,瀏覽器會立即刪除cookie。
  • cookie編碼問題
    a、什么是cookie的編碼問題:cookie只能存放合法的ASCII字符中文需要轉換成合法的ASCII字符的形式才能存放。
    b、如何處理
    String URLEncoding.encoding(String str,String charset);
    String uRLDecoder.decode(String str,String charset);
    c、建議:不管是否為中文,最好統(tǒng)一編碼處理。
  • cookie的路徑問題
    a、什么是cookie的路徑問題
    瀏覽器訪問服務器時,會比較請求地址是否與cookie的路徑匹配,只有匹配的cookie才會被發(fā)送。
    b、cookie的默認路徑
    cookie的默認路徑等于添加該cookie的web組件的路徑。
    c、匹配規(guī)則:請求路徑必須等于cookie的路徑或者是其子路徑,只有滿足該條件的cookie才會被發(fā)送
    d、修改cookie的路徑:cookie.setPath(String path);
  • cookie可以被用戶進制
    a、cookie可以被用戶進制
    b、cookie不安全。對于敏感數(shù)據(jù),盡量避免存放在cookie里,如果一定要存放,要加密之后再存放。
    c、cookie只能存放少量的數(shù)據(jù)(約4k)
    d、cookie個數(shù)有限制
    e、cookie只能存放字符串

session(會話)

  • 什么是session:服務器端為了保存用戶狀態(tài)而創(chuàng)建的一個特殊的對象
  • session工作原理:當瀏覽器訪問服務器時,服務器創(chuàng)建session對象(該對象有一個唯一的ID,以便稱為sessionId),服務器會將sessionId以cookie的方式發(fā)生給瀏覽器,當瀏覽器再次訪問服務器時,會將sessionID發(fā)生過來,服務器依據(jù)sessionID找到對應的session。
  • 如何獲得session對象:
    方式一:HttPSession session = request.getSession(boolean flag);
    注:HttpSession是一個接口,session對象是一個符合該接口的對象。
    當flag為true時,先查看請求中有無sessionId,如果沒有則創(chuàng)建一個session,有則依據(jù)該sessionId查找對應的session對象,如果找到了則返回該對象,如果找不到,則創(chuàng)建一個新的session對象。
    當flag為false時,先查看請求中有沒有sessionId,如果沒有,返回null,如果有,依據(jù)sessionId查找對應的session,如果找到返回session,找不到返回null。
    方式二:HttPSession session = request.getSession();
    等價于request.getSession(true);
  • 常用方法:
    setAttribute(String name,Object obj);
    Object getAttribute(String name);//不存在返回null
    removeAttribute(String name);
    String getId(String name);
  • session超時
    1、服務器會將空閑時間過長的session對象刪掉。(一般是30分鐘)
    2、如何修改超時時間長度
    方式一:修改web.xml
    方式二:session.setMaxInactiveInterval(int seconds);
    兩次請求之間的最大間隔
  • 刪除session
    session.invalidate();
  • session驗證
    1、在登錄成功之后綁定一些數(shù)據(jù)到session對象上
    session.setAttribute("user",user);
    2、當用戶訪問需要保護的資源時,進行session驗證:
    Object user = session.getAttribute("user");
    if(user == null){
    //沒有登錄
    response.sendRedirect("login.jsp");
    }

Cookie和Session比較

  • session相對于cookie的優(yōu)點:更安全,能存放更多的數(shù)據(jù),支持更豐富的數(shù)據(jù)類型。但是session會占用服務端的內(nèi)存空間,如果用戶量很大,就需要占用大量的內(nèi)存空間

路徑問題

指的鏈接、表單提交、重定向和轉發(fā)時,如何填寫路徑

  • 相對路徑
    不以"/"開頭的路徑。
  • 絕對路徑
    以"/"開頭的路徑。
  • 如何寫絕對路徑
    鏈接、表單提交、重定向從應用名開始寫,轉發(fā)從應用名之后開始寫。
    注:一定不要將應用名直接寫在路徑里,使用request.getContextPath()獲得應用名

Servlet的生命周期

  • 什么是Servlet的生命周期
    Servlet容器如何創(chuàng)建Servlet對象,如何對該對象進行初始化處理、如何調(diào)用該對象的方法來處理請求、以及如何銷毀該對象的整個過程。

  • Servlet的生命周期分為哪幾個階段
    1、實例化
    a、什么是實例化:容器調(diào)用Servlet的構造器,創(chuàng)建Servlet對象。
    b、什么時候實例化:
    情形1:容器收到請求之后
    情形2:容器啟動之后,立即創(chuàng)建相應的實例(需要額外的配置)
    <load-on-startup>1</load-on-startup>(值小的先創(chuàng)建)

2、初始化
a、什么是初始化
容器調(diào)用servlet對象的init方法(執(zhí)行一次)
b、GenericServlet已經(jīng)提供了init方法的實現(xiàn)
會將容器傳遞過來的ServletConfig對象保存下來,并且提供了getServletConfig來獲得該對象。
如果要實現(xiàn)自己的初始化處理邏輯,只需要override GenericServlet的init方法
c、初始化參數(shù)
配置初始化參數(shù)
讀取初始化參數(shù)

3、就緒
a、什么是就緒:容器調(diào)用Servlet的service方法來處理請求
b、HttpServlet已經(jīng)提供了service方法的實現(xiàn)
該方法會依據(jù)請求類型(get/post)調(diào)用對應的doXXX方法。
doXXX方法只拋出一個異常。
開發(fā)人員只有兩個選擇:
override doXXX方法
override service方法

4、銷毀
a、什么是銷毀:容器在刪除servlet對象之前,會調(diào)用該對象的destory方法(值執(zhí)行一次)
b、GenericServlet已經(jīng)提供了destory方法的實現(xiàn)。
該方法實際上什么都沒有做,我們可以override該方法,來實現(xiàn)自己的銷毀處理邏輯。

  • 相關的接口與類
    a、Servlet接口
    init(ServerConfig config)
    service(ServletRequest req, ServletResponse resp)
    destory()
    b、GenericServlet抽象類
    實現(xiàn)了Servlet接口中的部分方法(init,destory)
    c、HttpServlet抽象類
    繼承了GenericServlet,實現(xiàn)了service方法。

過濾器

  • 過濾器是什么:Servlet規(guī)范當中定義的一種特殊的組件,用來攔截Servlet容器的調(diào)用過程。
    注:Servlet容器收到容器請求之后,如果有過濾器,會先調(diào)用過濾器。
  • 如何寫過濾器:
    1、寫一個java類實現(xiàn)Filter接口。
    2、在接口方法當中,實現(xiàn)攔截處理邏輯。
    3、配置過濾器(web.xml)。
  • 過濾器的優(yōu)先級:當有多個過濾器攔截的要求,則容器會依據(jù)<filter-mapping>的先后順序倆執(zhí)行。
  • 初始化參數(shù):

監(jiān)聽器

  • 什么是監(jiān)聽器:Servlet規(guī)范當中定義的一種特殊組件,用來監(jiān)聽容器產(chǎn)生的事件并進行相關的處理。
    注:容器產(chǎn)生的事件主要分為兩類,分別是
    1)、生命周期相關的事件:容器創(chuàng)建或者銷毀request、session、servlet上下文產(chǎn)生的事件
    2)、綁定數(shù)據(jù)相關的事件:調(diào)用了request、session、servlet上下文的setAttribute和removeAttribute方法時產(chǎn)生的事件.

Servlet上下文

  • 什么是Servlet上下文:容器啟動之后,會為每一個web應用創(chuàng)建唯一的一個符合ServletContext接口要求的對象(即Servlet上下文),該對象會一直存在,除非容器關閉。
  • 如何創(chuàng)建Servlet上下文:ServletConfig、FilterConfig、GenericServlet、HttPSession都提供了getServletContext方法。
  • 作用:
    1)綁定數(shù)據(jù)
    setAttribute、getAttribute、removeAttribute
    比較request、session、servlet上下文綁定數(shù)據(jù)的區(qū)別:
    a、在滿足使用條件的情況下,優(yōu)先使用生命周期短的。(request<session<servlet上下文)
    b、綁定到session對象的數(shù)據(jù),只有與該session對應的用戶能訪問;而綁定到servlet上下文的數(shù)據(jù),所有用戶都能共享。

使用上下文讀取全局的初始化參數(shù)

如何開發(fā)一個監(jiān)聽器

1、寫一個java類,然后實現(xiàn)相應的監(jiān)聽接口
注:要依據(jù)監(jiān)聽的事件類型,選擇實現(xiàn)相應的接口,比如,要監(jiān)聽session對象的創(chuàng)建和銷毀,實現(xiàn)HttpSessionListener接口。
2、在接口方法中,實現(xiàn)監(jiān)聽處理邏輯。
3、配置監(jiān)聽器。

容器如何處理請求資源路徑

  • 容器默認訪問的是一個Servlet,所以,會查看web.xml配置,看有沒有匹配的servlet。
    有三種<url-pattern>寫法:
    精確配置
    通配符匹配:使用""匹配零個或多個任意字符
    后綴匹配:使用"
    ."開頭,后接一個后綴
  • 如果沒有查到匹配的servlet,容器會查看相應位置的文件

如何讓一個Servlet處理多種請求

1、 采用后綴匹配
2、 分析請求資源路徑,進行相應的處理

Servlet的線程安全問題

  • 為什么說Servlet會有線程安全問題
    a、容器對于某個Servlet,只會創(chuàng)建一個實例。
    b、容器收到一個請求,就會啟動一個線程安全,由該線程來調(diào)用對應的Servlet實例的方法來處理請求。
    這樣,就有可能產(chǎn)生線程安全問題,比如多個線程去修改servlet的某個屬性值。
  • 如何解決:使用synchronize對有可能產(chǎn)生線程安全問題的代碼塊加鎖。
    使用synchronize加鎖會影響性能。

Servlet小結

1、Servlet基礎
2、Servlet核心
3、數(shù)據(jù)庫訪問
4、過濾器與監(jiān)聽器
5、典型案例

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

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

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