Web基礎瞭解版05-Servlet

Servlet

Servlet?

  • 從廣義上來說,Servlet規範是Sun公司制定的一套技術標準,包含與Web應用相關的一系列接口,是Web應用實現方式的宏觀解決方案。而具體的Servlet容器負責提供標準的實現。css

  • 從狹義上來說,Servlet指的是javax.servlet.Servlet接口及其子接口,也能夠指實現了Servlet接口的實現類。html

  • Servlet(Server Applet)做爲服務器端的一個組件,它的本意是「服務器端的小程序」。java

    • Servlet的實例對象由Servlet容器負責建立;web

    • Servlet的方法由容器在特定狀況下調用;數據庫

    • Servlet容器會在Web應用卸載時銷燬Servlet對象的實例。小程序

操做步驟

使用Servlet接口的方式:瀏覽器

① 搭建Web開發環境緩存

② 建立動態Web工程tomcat

③ 建立javax.servlet.Servlet接口的實現類:com.atguigu.servlet.MyFirstServlet服務器

④ 在service(ServletRequest, ServletResponse)方法中編寫代碼

⑤ 在web.xml配置文件中註冊MyFirstServlet

<!-- 聲明一個Servlet,配置的是Servlet的類信息 -->
<servlet>
    <!-- 這是Servlet的別名,一個名字對應一個Servlet。至關於變量名 -->
    <servlet-name>MyFirstServlet</servlet-name>
    <!-- Servlet的全類名,服務器會根據全類名找到這個Servlet -->
    <servlet-class>com.servlet.MyFirstServlet</servlet-class>
</servlet>

<!-- 創建Servlet的請求映射信息 -->
<servlet-mapping>
    <!-- Servlet的別名,說明這個Servlet將會響應下面url-pattern的請求 -->
    <servlet-name>MyFirstServlet</servlet-name>
    <!-- Servlet響應的請求路徑。若是訪問這個路徑,這個Servlet就會響應 -->
    <url-pattern>/MyFirstServlet</url-pattern>
</servlet-mapping>

說明:

  • <url-pattern>:這個url-pattern能夠配置多個,這時表示的就是訪問這些url都會觸發這個Servlet進行響應,運行瀏覽器,訪問剛纔配置的url路徑,Servlet的service方法就會被調用。

  • <url-pattern>中的文本內容必須以 / 或 *. 開始書寫路徑。至關於將資源映射到項目根目錄下造成虛擬的資源文件。

  • <servlet-mapping>中的<url-pattern>能夠聲明多個,能夠經過任意一個均可以訪問。可是開發中通常只會配置一個。

⑥ 在WebContent目錄下建立index.html

⑦ 在index.html中加入超連接 <a href="MyFirstServlet">To Servlet</a>

⑧ 點擊超連接測試Servlet

 若是配置文件一旦修改,須要重啓服務器來從新部署web項目。

Servlet做用

  • 接收請求 【解析請求報文中的數據:請求參數】

  • 處理請求 【DAO和數據庫交互】

  • 完成響應 【設置響應報文】

Servlet生命週期

 簡單的敘述生命週期,就是對象在容器中從開始建立到銷燬的過程。

 Servlet對象是Servlet容器建立的,生命週期方法都是由容器調用的。這裏指的就是Tomcat

① Servlet對象的建立:構造器

  • 默認狀況下,Servlet容器第一次收到HTTP請求時建立對應Servlet對象。

  • 容器之因此能作到這一點是因爲咱們在註冊Servlet時提供了全類名,容器使用反射技術建立了Servlet的對象。

② Servlet對象初始化:init()

  • Servlet容器建立Servlet對象以後,會調用init(ServletConfig config)方法。

  • 做用:是在Servlet對象建立後,執行一些初始化操做。例如,讀取一些資源文件、配置文件,或創建某種鏈接(好比:數據庫鏈接)

  • init()方法只在建立對象時執行一次,之後再接到請求時,就不執行了

  • 在javax.servlet.Servlet接口中,public void init(ServletConfig config)方法要求容器將ServletConfig的實例對象傳入,這也是咱們獲取ServletConfig的實例對象的根本方法。

③ 處理請求:service()

  • 在javax.servlet.Servlet接口中,定義了service(ServletRequest req, ServletResponse res)方法處理HTTP請求。

  • 在每次接到請求後都會執行。

  • Servlet的做用,主要在此方法中體現。

  • 同時要求容器將ServletRequest對象和ServletResponse對象傳入。

④ Servlet對象銷燬:destroy()

  • 服務器重啓、服務器中止執行或Web應用卸載時會銷燬Servlet對象,會調用public void destroy()方法。

  • 此方法用於銷燬以前執行一些諸如釋放緩存、關閉鏈接、保存內存數據持久化等操做。

Servlet請求過程

  • 第一次請求

    • 調用構造器,建立對象

    • 執行init()方法

    • 執行service()方法

  • 後面請求

    • 執行service()方法

  • 對象銷燬前

    • 執行destroy()方法

ServletConfig接口

  • ServletConfig接口封裝了Servlet配置信息,這一點從接口的名稱上就可以看出來。

  • 每個Servlet都有一個惟一對應的ServletConfig對象,表明當前Servlet的配置信息。

  • 對象由Servlet容器建立,並傳入生命週期方法init(ServletConfig config)中。能夠直接獲取使用。

  • 表明當前Web應用的ServletContext對象也封裝到了ServletConfig對象中,使ServletConfig對象成爲了獲取ServletContext對象的一座橋樑。

  • ServletConfig對象的主要功能

    • 獲取Servlet名稱:getServletName()

    • 獲取全局上下文ServletContext對象:getServletContext()

    • 獲取Servlet初始化參數:getInitParameter(String) / getInitParameterNames()。

ServletContext接口

  • Web容器在啓動時,它會爲每一個Web應用程序都建立一個惟一對應的ServletContext對象,意思是Servlet上下文,表明當前Web應用。

  • 因爲一個Web應用程序中的全部Servlet都共享同一個ServletContext對象,因此ServletContext對象也被稱爲 application 對象(Web應用程序對象)。

  • 對象由Servlet容器在項目啓動時建立,經過ServletConfig對象的getServletContext()方法獲取。在項目卸載時銷燬。

  • ServletContext對象的主要功能

① 獲取項目的上下文路徑(帶/的項目名): getContextPath()

② 獲取虛擬路徑所映射的本地真實路徑:getRealPath(String path)

  • 虛擬路徑:瀏覽器訪問Web應用中資源時所使用的路徑。

  • 本地路徑:資源在文件系統中的實際保存路徑。

  • 做用:將用戶上傳的文件經過流寫入到服務器硬盤中。

③ 獲取WEB應用程序的全局初始化參數(基本不用)

  • 設置Web應用初始化參數的方式是在web.xml的根標籤下加入以下代碼

<web-app>
    <!-- Web應用初始化參數 -->
    <context-param>
        <param-name>ParamName</param-name>
        <param-value>ParamValue</param-value>
    </context-param>
</web-app>

獲取Web應用初始化參數

④ 做爲域對象共享數據

  • 做爲最大的域對象在整個項目的不一樣web資源內共享數據。

  • setAttribute(key,value):之後能夠在任意位置取出並使用

  • getAttribute(key):取出設置的value值

實現類

  • 實現類體系

    • GenericServlet實現Servlet接口

    • HttpServlet繼承GenericServlet

  • 建立Servlet的最終方式

    • 繼承HttpServlet

GenericServlet抽象類

  • GenericServlet對Servlet功能進行了封裝和完善,重寫了init(ServletConfig config)方法,用來獲取ServletConfig對象。此時若是GenericServlet的子類(一般是自定義Servlet)又重寫了init(ServletConfig config)方法有可能致使ServletConfig對象獲取不到,因此子類不該該重寫帶參數的這個init()方法。

  • 若是想要進行初始化操做,能夠重寫GenericServlet提供的無參的init()方法,這樣就不會影響ServletConfig對象的獲取。

  • 將service(ServletRequest req,ServletResponse res)保留爲抽象方法,讓使用者僅關心業務實現便可。

HttpServlet抽象類

  • 專門用來處理Http請求的Servlet。

  • 對GenericServlet進行進一步的封裝和擴展,在service(ServletRequest req, ServletResponse res)方法中,將ServletRequest和ServletResponse轉換爲HttpServletRequest和HttpServletResponse,根據不一樣HTTP請求類型調用專門的方法進行處理。

  • 從此在實際使用中繼承HttpServlet抽象類建立本身的Servlet實現類便可。重寫doGet(HttpServletRequest req, HttpServletResponse resp)和doPost(HttpServletRequest req, HttpServletResponse resp)方法實現請求處理,再也不須要重寫service(ServletRequest req, ServletResponse res)方法了。

  • 又由於咱們業務中get,post的處理方式又都是同樣的,因此咱們只須要寫一種方法便可,使用另一種方法調用咱們寫好的doXXX方法。web.xml配置與以前相同。

HttpServletRequest接口

  • 該接口是ServletRequest接口的子接口,封裝了HTTP請求的相關信息。

  • 瀏覽器請求服務器時會封裝請求報文交給服務器,服務器接受到請求會將請求報文解析生成request對象。

  • 由Servlet容器建立其實現類對象並傳入service(HttpServletRequest req, HttpServletResponse res)方法中。

 功能

  1.使用HttpServletRequest對象獲取請求參數,即瀏覽器向服務器提交的數據

//一個name對應一個值
String userId = request.getParameter("userId");
//一個name對應一組值
String[] soccerTeams = request.getParameterValues("soccerTeam");
for(int i = 0; i < soccerTeams.length; i++){
    System.out.println("team "+i+"="+soccerTeams[i]);
}

  2.獲取url地址參數

String path = request.getContextPath();//重要
System.out.println("上下文路徑:"+path);
System.out.println("端口號:"+request.getServerPort());
System.out.println("主機名:"+request.getServerName());
System.out.println("協議:"+request.getScheme());

  3.獲取請求頭信息

String header = request.getHeader("User-Agent");
System.out.println("user-agent:"+header);
String referer = request.getHeader("Referer");
System.out.println("上個頁面的地址:"+referer);//登陸失敗,返回登陸頁面讓用戶繼續登陸

  4.請求的轉發

//獲取請求轉發對象
RequestDispatcher dispatcher = request.getRequestDispatcher("success.html");
dispatcher.forward(request, response);//發起轉發

  5.向請求域中保存數據

//將數據保存到request對象的屬性域中
request.setAttribute("attrName", "attrValueInRequest");
//兩個Servlet要想共享request對象中的數據,必須是轉發的關係
request.getRequestDispatcher("/ReceiveServlet").forward(request, response);
//從request屬性域中獲取數據
Object attribute = request.getAttribute("attrName");
System.out.println("attrValue="+attribute);

HttpServletResponse接口

  • 該接口是ServletResponse接口的子接口,封裝了服務器針對於HTTP響應的相關信息。(暫時只有服務器的配置信息,沒有具體的和響應體相關的內容)

  • 由Servlet容器建立其實現類對象,並傳入service(HttpServletRequest req, HttpServletResponse res)方法中。

功能

  1.使用PrintWriter對象向瀏覽器輸出數據

//經過PrintWriter對象向瀏覽器端發送響應信息
PrintWriter writer = res.getWriter();
writer.write("Servlet response");
writer.close();
  • 寫出的數據能夠是頁面、頁面片斷、字符串等

  • 當寫出的數據包含中文時,瀏覽器接收到的響應數據就可能有亂碼。爲了不亂碼,可使用Response對象在向瀏覽器輸出數據前設置響應頭。

  2.設置響應頭

response.setHeader("Content-Type", "text/html;charset=UTF-8");
  • 設置好之後,會在瀏覽器的響應報文中看到設置的響應頭中的信息。

  3.重定向請求

//注意路徑問題,加上/會失敗,會以主機地址爲起始,重定向通常須要加上項目名
response.sendRedirect(「success.html」);
  •  經過重定向將頁面的地址交給瀏覽器並設置響應狀態碼爲302,瀏覽器會自動進行跳轉。

轉發與重定向

 

請求轉發

  1.  第一個Servlet接收到了瀏覽器端的請求,進行了必定的處理,而後沒有當即對請求進行響應,而是將請求「交給下一個Servlet」繼續處理,下一個Servlet處理完成以後對瀏覽器進行了響應。在服務器內部將請求「交給」其它組件繼續處理就是請求的轉發。
  2.  轉發的狀況下,兩個Servlet能夠共享同一個Request對象中保存的數據。
  3.  當須要將後臺獲取的數據傳送到JSP上顯示的時候,就能夠先將數據存放到Request對象中,再轉發到JSP從屬性域中獲取。此時因爲是「轉發」,因此它們兩者共享Request對象中的數據。
  4.  轉發的狀況下,能夠訪問WEB-INF下的資源。
  5.  轉發以「/」開始表示項目根路徑,重定向以」/」開始表示主機地址。
    //1.使用RequestDispatcher對象封裝目標資源的虛擬路徑
    RequestDispatcher dispatcher = request.getRequestDispatcher("/index.html");
    //2.調用RequestDispatcher對象的forward()方法「前往」目標資源
    //[注意:傳入的參數必須是傳遞給當前Servlet的service方法的
    //那兩個ServletRequest和ServletResponse對象]
    dispatcher.forward(request, response);
}

請求重定向

  1. 第一個Servlet接收到了瀏覽器端的請求,進行了必定的處理,而後給瀏覽器一個特殊的響應消息,這個特殊的響應消息會通知瀏覽器去訪問另一個資源,這個動做是服務器和瀏覽器自動完成的。整個過程當中瀏覽器端會發出兩次請求,且在瀏覽器地址欄裏面可以看到地址的改變,改變爲下一個資源的地址。
  2. 重定向的狀況下,原Servlet和目標資源之間就不能共享請求域數據了。
  3. HttpServletResponse表明HTTP響應,對象由Servlet容器建立。
   //1.調用HttpServletResponse對象的sendRedirect()方法
    //2.傳入的參數是目標資源的虛擬路徑
    response.sendRedirect("index.html");

對比請求的轉發與重定向

  轉發 重定向
瀏覽器感知 在服務器內部完成,瀏覽器感知不到 服務器以302狀態碼通知瀏覽器訪問新地址,瀏覽器有感知
瀏覽器地址欄 不改變 改變
整個過程發送請求次數 一次 兩次
執行效率 效率高 效率低
API(或發起者) Request對象 Response對象
可否共享request對象數據
WEB-INF下的資源 能訪問 不能訪問
目標資源 必須是當前web應用中的資源 不侷限於當前web應用

說明:默認狀況下,瀏覽器是不能訪問服務器web-inf下的資源的,而服務器是能夠訪問的。

字符編碼問題

解決亂碼的方法:就是統一字符編碼

GET請求亂碼

  • GET請求參數是在地址後面的。咱們須要修改tomcat的配置文件。須要在server.xml文件修改Connector標籤,添加URIEncoding="utf-8"屬性。
  • 一旦配置好之後,能夠解決當前工做空間中全部的GET請求的亂碼問題。

POST請求亂碼

  • POSTt請求服務器解析出現問題,解決方法:在獲取參數值以前,設置請求的解碼格式,使其和頁面保持一致。

request.setCharacterEncoding("utf-8");
  • POST請求亂碼問題的解決,只適用於當前的操做所在的類中。不能相似於GET請求同樣統一解決。由於請求體有可能會上傳文件。

響應亂碼

  • 向瀏覽器發送響應的時候,要告訴瀏覽器,我使用的字符集是哪一個,瀏覽器就會按照這種方式來解碼
//方法一:
response.setHeader("Content-Type", "text/html;charset=utf-8");
//方法二:
response.setContentType("text/html;charset=utf-8");

路徑設置問題

相對路徑和絕對路徑

相對路徑:虛擬路徑若是不以「/」開始,就是相對路徑,瀏覽器會以當前資源所在的虛擬路徑爲基準對相對路徑進行解析,從而生成最終的訪問路徑。

絕對路徑:虛擬路徑以「/」開始,就是絕對路徑。

① 在服務器端:虛擬路徑最開始的「/」表示當前Web應用的根目錄。只要是服務端解析的絕對路徑,都是以web根目錄爲起始的。由服務器解析的路徑包括:(1) web.xml的配置路徑、(2)request轉發的路徑。

② 在瀏覽器端:虛擬路徑最開始的「/」表示當前主機地址。

例如:連接地址「/Path/dir/b.html」通過瀏覽器解析後爲: 至關於http://localhost:8989/Path/dir/b.html

由瀏覽器解析的路徑包括:

(1)重定向操做:response.sendRedirect("/xxx") (2)全部HTML標籤:<a href="/xxx"> 、<form action="/xxx"> 、link、img、script等

  • 在瀏覽器端,除了使用絕對路徑以外,咱們還可使用base標籤+相對路徑的方式來肯定資源的訪問有效。

  • base標籤影響當前頁面中的全部相對路徑,不會影響絕對路徑。至關於給相對路徑設置了一個基準地址。

<!-- 給頁面中的相對路徑設置基準地址 -->
<base href="http://localhost:8080/Test_Path/"/>

 

總結:

* /的有無
* 有: 採用的是絕對路徑
* 無: 採用的是相對路徑
* /的含義:
* 用服務器解析表明:當前項目下 (http://localhost:8080/上下文項目名/)
* 用瀏覽器解析表明:當前主機下(http://localhost:8080/)
* /的幾種使用位置:
* 用在轉發:採用服務器解析 (相對和絕對沒有區別)
* 用在重定向:採用瀏覽器解析
* 相對路徑:response.sendRedirect("pages/user/login_success.html");
* 局對路徑:response.sendRedirect(request.getContextPath()+"/pages/user/login_success.html");
* 用在頁面上:採用瀏覽器解析
* 建議採用絕對路徑去加載靜態資源(css/js/image/video...)
* 方式一:<link href="/上下文項目名/static/css/style.css" type="text/css" rel="stylesheet" >
* 方式二:在head標籤中新增一個base標籤並設置href屬性 ★
* <base href="/BookStore02/"> 在當前頁面中全部的路徑錢統一添加指定前綴

導入外部工程

相關文章
相關標籤/搜索