深入理解Servlet原理


Servlet介紹:

1. 如何返回一個網頁:

 a. 靜態網頁

    >新聞頁、百度百科

    >服務器保存一份HTML,直接返回給瀏覽器即可

 b. 動態網頁

    >淘寶、QQ空間、微博

    >服務器保存一個組件,通過它動態拼一個HTML

    >在Java中這個組件就是Servlet

2. Servlet特征:

  a. Servlet是服務器端組件,必須保存在服務器上。

  b. Servlet可以動態拼資源(HTML/IMG等),即處理HTTP協議。

  c. Servlet必須滿足Sun的規范。

  d. Servlet是什么:Servlet是Sun推出的,用來在服務器端處理HTTP協議的組件。

服務器:

1. 名稱:Java 服務器、Java Web 服務器、Servlet 容器;

2. 本質:是一個軟件,需要安裝在硬件上才能用和瀏覽器是平級的關系;

3. 舉例:Tomcat(Apache)、JBOSS、WebLogic、WebSphere。

Tomcat使用:

1. 啟動Tomcat:

   -Linux:打開/tomcat/bin,終端輸入命令./startup.sh

   -Windows:打開/tomcat/bin,雙擊startup.bat

2. 關閉Tomcat:

   -Linux:打開/tomcat/bin,終端輸入命名./shutdown.sh

   -Windows:打開/tomcat/bin,雙擊shutdown.bat

Servlet開發步驟:

1.創建WEB項目

  >目錄:webapp/WEB-INF/web.xml

2.導入jar包

  >通過maven導入jar包,搜javaee

  >使用服務器自帶的jar包,右鍵項目->target runtime->勾選tomcat

3.創建Servlet

  >實現Servlet接口

  >也可以繼承HttpSevlet,此類已實現了Servlet接口

  >實現/重寫service(),在此方法內動態拼HTML

4.注冊Servlet

  >注冊Servlet,並聲明別名

  >通過別名,給此Servlet注冊網名(以/開頭)

5.部署項目

  >在Servers下選擇Tomcat,右鍵Add and Remove

  >在彈出框內左側選中項目,雙擊移動到右側

  >部署:就是拷貝

6.訪問Servlet

  >啟動Tomcat

  >瀏覽器輸入地址 http://ip:port/項目名/Servlet網名

7.重新部署

  >修改代碼后,需要重新部署並重啟Tomcat才有效

  >點擊Servers下面的Tomcat7,右鍵publish

  >可以手動關閉Tomcat,再啟動它

  >也可以等待Eclipse自動重啟Tomcat(Reloading...)

Servlet執行原理:

 

HTTP協議:

1. 什么是HTTP協議:它規定了瀏覽器和服務器如何通信,以及通信時的數據格式。

2. 如何通信:

  >建立連接

  >發送請求

  >接收響應

  >關閉連接

3. 數據格式:

 a. 請求數據包

   >請求行:請求方式、Servlet網名、協議類型

   >消息頭:數據的描述信息

   >實體內容:瀏覽器發送給服務器的數據

 b. 響應數據包

   >狀態行:協議類型、狀態碼、狀態

   >消息頭:數據的描述信息

   >實體內容:服務器給瀏覽器發送的數據

4. 對開發的要求

  -通信的方式已經由瀏覽器和服務器完成;

  -請求數據的打包由瀏覽器實現;

  -響應數據的打包由服務器實現;

  -開發需要提供瀏覽器發送給服務器的數據,以及服務器返回的數據;

  -服務器通過request對象接收請求數據;

  -服務器通過response對象向瀏覽器發送數據;

注冊案例:

1. form的action屬性要寫上Servlet的訪問路徑(網名);

2. 在表單空間上,使用name屬性給該控件的數據命名,可以調用request的getParameter("name的指")來獲取值;

3. radio和checkbox需要設置value屬性的值,就是要傳遞給服務器的具體的值;

Servlet原理圖:

請求方式:

1. 介紹:瀏覽器向服務器發送數據的方式;

2. GET:

  >默認情況下所有的請求都是GET請求

  >采用路徑傳參,即通過路徑攜帶參數

  >傳參過程中參數可見,隱私性差

  >因為路徑大小有限制,所以能夠傳遞的參數很小

3. POST:

  >method="post"

  >采用實體內容傳參

  >在傳參的過程中,路徑上看不到參數,隱私性好

  >實體內容專門用於傳遞數據,因此大小不受限制

4. 使用場景:

  >瀏覽器向服務器索取(查詢)數據用GET請求

  >瀏覽器向服務器提交(保存)數據用POST請求

解決亂碼問題:

 

重定向:

 1. 格式:res.sendRedirect("findEmp");//findEmp是網名

 2. 原理圖如下:

 

項目路徑:

URI和URL:

1. 狹義(Java):

   - URI:絕對路徑;

   - URL:完整路徑;

   - URL包含了URI;

2. 廣義(Java/.net/php):

   - URI:資源的名稱;

   - URL:資源的真名;

   - URI包含了URL;  

 

Servlet路徑的配置方式及用途:

1. 精確匹配(/test):

    - 只有這唯一的路徑可以可以訪問此Servlet

    - 該Servlet只能處理一個請求 

2. 通配符(/*):

    - 所有的路徑都是可以訪問此Servlet

    - 該Servlet可以處理所有請求

3. 后綴匹配(*.test):

    - 所有以.test為后綴的路徑都可以訪問此Servlet

    - 該Servlet可以處理很多請求

注:

  a. 必須先通過規范約定正確的路徑;

  b. 按照規范判斷路徑,處理請求。對於不滿足規范的路徑,認為是用戶輸入的錯誤路徑,統一報錯;

 

Servlet生命周期:

1. 第1、2、4步只能執行一次,第3步可以執行多次;

2. 因為Servlet被Tomcat自動創建一次,因此它在Tomcat內是單例的(只有1個實例),即Servlet滿足單例模式;

3. 默認情況下,首次訪問Servlet時,Tomcat會創建它,也可以修改配置文件web.xml,使得Tomcat啟動時就直接創建Servlet;

4. 啟動時創建Servlet,數字1代表創建的次序:<load-on-startup>1</load-on-startup>;

 

ServletConfig和ServletContext:

1. Context:上下文,理解為環境。環境可以給其內部的個體提供資源。從編程的角度來說可以給內部的對象提供數據;
2. ServletConfig:它是Servlet的私有環境,可以為某一個Servlet提供數據;
3. ServletContext:它是Servlet的公有環境,可以為所有Servlet提供數據;
4. 使用ServletConfig和ServletContext給Servlet預置數據,不用寫單獨的配置文件,直接使用web.xml即可;另外這兩個對象可以在初始化Servlet之前自動讀取web.xml中的預置數據;
5. Servlet特殊用法:
    - 可以使用此對象存取一些變量;
    - 即在程序運行階段隨時向此對象存取數據;
    - 獲取對象:ServletContext ctx = getServletContext();
    - 取:ctx.getAttribute("user");
    - 存:ctx.setAttribute("user","admin");
 6. 通常在Tomcat啟動時,都要調用某Servlet重寫init(ServletConfig config)方法,專門用來在此階段初始化項目所需要的一些變量。

使用案例:

1. ServletConfig案例:
  a. 配置文件web.xml 

<servlet>

<servlet-name>login</servlet-name>
<servlet-class>web.LoginServlet</servlet-class>

<!-- 給當前Servlet預置一個數據 -->

<init-param>

<param-name>maxOnline</param-name>

<param-value>2000</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>login</servlet-name>

<url-pattern>/login</url-pattern>

</servlet-mapping>

  b. 在Servlet類中讀取參數
 

/**

* 1.Tomcat在創建此Servlet后,會自動創建ServletConfig對象。

* 2.Tomcat會調用此對象,讀取web.xml中給當前Servlet所配置的參數。

* 3.Tomcat會自動調用init方法,並傳入已創建好的ServletConfig對象。

* 歸納:調用init方法前,創建config並讀取數據。在init及其后面的方法內可以使用config。

*/

@Override

public void init(ServletConfig config) throws ServletException {

super.init(config);

String mo = config.getInitParameter("maxOnline");

System.out.println(mo);

}

@Override

protected void service(

HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

//從web.xml中讀取參數

ServletConfig cfg = getServletConfig();

String mo = cfg.getInitParameter("maxOnline");

System.out.println(mo);

}

2. ServletContext案例:

  a. 配置文件web.xml

 

<!--

給所有的Servlet預置一個數據。
1.Tomcat啟動時會自動創建ServletContext對象。

2.Tomcat調用context讀取此參數。

由於這件事是在調用Servlet之前完成的,所以在service()中可以通過context讀取參數。

-->

<context-param>

<param-name>size</param-name>

<param-value>10</param-value>

</context-param>

<servlet>

<servlet-name>findDept</servlet-name>

<servlet-class>web.FindDeptServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>findDept</servlet-name>

<url-pattern>/findDept</url-pattern>

</servlet-mapping>

 

  b. 在Servlet類中讀取參數

 

@Override

protected void service(
HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

//從web.xml中讀取分頁條件

ServletContext ctx = getServletContext();

String size = ctx.getInitParameter("size");

//分頁查詢

System.out.println(size);

}

線程安全:

1. 成員變量:

    - 成員變量存於堆內;

    - 堆內數據只有一份;

    - 多線程共用一份數據;

    - 存在並發問題;

2. 局部變量:

    - 成員變量存於棧內;

    - 棧內數據是多份;

    - 每個線程都有一份自己的數據;

    - 沒有並發問題;

3. 解決方案:

   - 不用成員;

   - 枷鎖synchronized (this) {//TODO};

HttpServlet:

1. 自定義的類繼承HttpServlet類,重寫service方法,Tomcat將HttpServletRequest,HttpServletResponse傳入此方法:

 

public class TestServlet extends HttpServlet {

@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

super.service(req, res);

}

//...

}

2. 調用父類,並將HttpServletRequest、HttpServletResponse兩個參數傳入:

 

public class HttpServlet {

public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res= (HttpServletResponse) response;
this.service(req, res);
}
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
String m = req.getMethod();
if(m.equals("GET")) {
doGet(req, res);
} else if(m.equals("POST")) {
doPost(req, res);
}
}
private void doPost(HttpServletRequest req, HttpServletResponse res) {
// TODO
}
private void doGet(HttpServletRequest req, HttpServletResponse res) {
// TODO
}
//...
}
3. doGet()和doPost()默認的代碼直接拋出了異常,為了強制開發者去重寫他們。若要調用它們,就必須重寫;

4. service()內去掉super.service()的目的就是不掉用它們,從而避免異常;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM