Servlet的原理、周期、創建方法、Servlet的線程安全、ServletConfig以及重要的ServletContext

1.什么是servlet

servlet是一個Java類,是用來專門處理請求和響應的,是部署在服務器上工作的小程序,之所以叫小程序,是因為它只要部署上去就自動運行工作了可以處理事情了。servlet 通常通過 HTTP(超文本傳輸協議)接收和響應來自 Web 客戶端的請求。
HTTP:
★ HTTP是HyperText Transfer Protocol(超文本傳輸協議)的簡寫,傳輸HTML文件。
★ 用于定義WEB瀏覽器與WEB服務器之間交換數據的過程及數據本身的格式。

2.操作步驟:

a.創建一個實現servlet接口的Java類(ServletDemo1)。
ServletDemo1爆紅是因為實現了Servlet接口就需要重寫里面的方法。實現接口所定義的方法。
在service方法里添加輸出語句

@Override
  public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
      // TODO Auto-generated method stub
      System.out.println("執行Servlet里的方法");
      
  }

b.在web.xml中配置servlet的信息。
我們的目的就是讓用戶通過url來訪問我們的剛剛實現了servlet接口的類,然后在這個類里面做一些處理。但是我們的類是寫在src中,然后編譯成字節碼.class文件是存放在WEB-INF中的,我們部署應用的時候就把WEB-INF的東西部署到服務器上,而WEB-INF文件中的東西是不允許外部訪問的,所以如果想要訪問的這個類(嚴格意義上說是這個類生成的字節碼文件),我們就需要通過一些配置來告訴服務器某個URL地址是用來訪問某個類的。這就是我們為什么要配置web.xml的原因。(服務器Tomcat啟動后加載項目最先掃描執行web.xml文件)

image.png

web.xml主要代碼:

<servlet>
  <!-- 一般把類名首字母變小寫作為servlet-name-->
    <servlet-name>ServelDemo1</servlet-name>
    <servlet-class>com.szy.web.servlet.ServelDemo1</servlet-class>
  </servlet>

這里的訪問邏輯是,我們在瀏覽器輸入localhost:8080/應用名/demo1后,它就會找到中相應的url(在中),然后根據這個url找到對應的叫servletDemo1,然后就在這個節點里再找到該對應的。至此,就自動找到這個類,去執行相應的任務了。
  <servlet>
    <servlet-name>servelDemo1</servlet-name>
    <servlet-class>com.cms.Demo1.Service.ServelDemo1</servlet-class>
  <!-- 2,填數字越小優先級越高,越先執行,讓該servlet在服務器啟動時就創建,不建議寫零 -->
    <load-on-startup>2</load-on-startup>
  </servlet>
 <!-- 給Servlet映射一個可訪問的URI :http://localhost:8080/項目名/demo1即可通過servelDemo1映射到ServelDemo1訪問該類-->
  <servlet-mapping>
    <servlet-name>servelDemo1</servlet-name>
    <url-pattern>/demo1</url-pattern>
  </servlet-mapping>

com.szy.web.servlet.ServelDemo1路徑的獲得操作如下圖:


image.png

執行結果:

瀏覽器顯示空白頁面但是控制臺輸出了ServletDemo1類里的執行結果。

image.png

3.Servlet的生命周期

此接口定義了初始化 servlet 的方法 init()、為請求提供服務的方法 service()和從服務器移除 servlet 的方法 destroy()。這些方法稱為生命周期方法,它們是按以下順序調用的:

a .初始化階段 :
構造 servlet,然后使用 init 方法將其初始化。
b.響應客戶請求階段:
處理來自客戶端的對 service 方法的所有調用。
c.終止階段:
從服務中取出 servlet,然后調用 destroy 方法銷毀它,最后進行垃圾回收并終止它。

除了生命周期方法之外,此接口還提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一種方法獲得任何啟動信息,而后一種方法允許 servlet 返回有關其自身的基本信息,比如作者、版本和版權。

package com.szy.web.servlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ServelDemo1  implements Servlet {  
    public  ServelDemo1() {
        // 實例化方法
    }
    @Override
    public void init(ServletConfig arg0) throws ServletException {
        // 初始化      
    }
    @Override
    public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
        // 服務
        System.out.println("執行Servlet里的方法");        
    }
    @Override
    public void destroy() {
        //銷毀        
    }
    @Override
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }
}

注意:
Servlet何時被創建:
  ★ 默認情況下,當WEB客戶第一次請求訪問某個Servlet的時候,WEB容器將創建這個Servlet的實例。
  ★ 當web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素時,Servlet容器在啟動web服務器時,將按照順序創建并初始化Servlet對象。
  ★ 在web.xml文件中,某些Servlet只有<serlvet>元素,沒有<servlet-mapping>元素,這樣我們無法通過url的方式訪問這些Servlet,這種Servlet通常會在<servlet>元素中配置一個<load-on-startup>子元素,讓容器在啟動的時候自動加載這些Servlet并調用init()方法,完成一些全局性的初始化工作。

4.servlet的三種創建方式

Servlet --> GenericServlet --> HttpServlet -->我們定義的繼承HttpServlet的類
曾祖父 爺爺 爸爸 孫子

方法如下:
a. 實現javax.servlet.Servlet接口(參見:編寫一個servlet程序)
要實現此接口,還可以編寫一個擴展 javax.servlet.GenericServlet 的一般 servlet,或者編寫一個擴展 javax.servlet.http.HttpServlet 的 HTTP servlet。

image.png

b. 繼承javax.servet.GenericServlet類(適配器模式)

image.png

只需重寫抽象 service 方法,因為它里面只有一個抽象方法。

image.png
image.png

c. 繼承javax.servlet.http.HttpServlet類(模板方法設計模式)
我們自己寫Servlet的時候,處理請求的時候實現Service()就好。不重寫Service()方法,而是重寫doGet和doPost2個方法,在HttpServlet抽象類中,已經實現了Service方法了,在有請求進來Servlet的時候首先從請求中獲取到請求提交的方式,所以我們直接重寫doGet和doPost方法就好。通常來說不確定是什么請求的情況下,默認是Get請求,在doGet和doPost中實現一個就夠了,如果方法的實現寫在
HTTP的請求方式包括DELETE,GET,OPTIONS,POST,PUT和TRACE,在HttpServlet類中分別提供了相應的服務方法,它們是,doDelete(),doGet(),doOptions(),doPost(), doPut()和doTrace().
項目開發一般都用這種方式創建Servlet;
第一步:創建Servlet類文件
Ctrl+N;輸入Servlet:

image.png

第二步:輸入類名

image.png

第三步:映射路徑的名字,默認為類名,可點擊Edit編輯


image.png

第三步:勾選需要重寫的方法:都默認勾選Doget和Dopost方法,點擊Finish:
繼承HttpServlet后不要重寫service的方法,因為service方法里包含調用doget跟dopost的方法,重寫了那兩方法不執行就作廢了


image.png

第五步:檢查生成的類和Web.xml的Servlet配置信息

package com.cms.Demo1.Service;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ServletDemo4
 */
public class ServletDemo4 extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ServletDemo4() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

    <servlet>
        <display-name>ServletDemo4</display-name>
        <servlet-name>ServletDemo4</servlet-name>
        <servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
    </servlet>
 
  <servlet-mapping>
    <servlet-name>ServletDemo4</servlet-name>
    <url-pattern>/ServletDemo4</url-pattern>
  </servlet-mapping>

注意:查看GenericServlet 的源碼包導Tomcat的源碼包,apache-tomcat-7.0.81-src.zip。Outline的窗口帶三角的說明是繼承過來重寫的方法,沒有的才是自己本身的。

image.png

servet映射細節

通配符* 代表任意字符串
url-pattern: *.do 以.字符串的請求都可以訪問 注:不要加/
url-pattern: /* 任意字符串都可以訪問
url-pattern: /action/
以/action開頭的請求都可以訪問
匹配規則:
優先級:從高到低
絕對匹配--> /開頭匹配 --> 擴展名方式匹配

如果url-pattern的值是/,表示執行默認映射。所有資源都是servlet

5. Servlet的線程安全

★ 單實例:每次訪問多線程
★ 解決線程安全問題的最佳辦法,不要寫全局變量,而寫局部變量。
★ Servlet的線程安全問題只有在大量的并發訪問時才會顯現出來,并且很難發現,因此在編寫Servlet程序時要特別注意。
★ servlet處于服務器進程中,它通過多線程方式運行其service方法,一個實例可以服務于多個請求,并且其實例一般不會銷毀,所以你的項目中如果只有一個servlet,那么web容器就只會創建一個實例。所以其默認非線程安全,如果需要線程安全需要指明。

6.ServletConfig

作用:
★ 可以獲取servlet配置信息
★ 可以獲得ServletContext對象

6.1Servlet配置信息的獲取:

當servlet配置了初始化參數后,web容器在創建servlet實例對象時,會自動將這些初始化參數封裝到ServletConfig對象中,并在調用servlet的init方法時,將ServletConfig對象傳遞給servlet。進而,程序員通過ServletConfig對象就可以得到當前servlet的初始化參數信息。
web.xml。只要有ServletConfig對象就能調用getInitParameter方法。

<servlet>
        <display-name>servletDemo4</display-name>
        <servlet-name>ServletDemo4</servlet-name>
        <servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
        <!-- 初始化參數 -->
        <init-param>
        <param-name>encoding</param-name>
        <param-value>GBK</param-value>
        </init-param>
    </servlet>

獲取配置信息:GBK

package com.cms.Demo1.Service;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Servlet implementation class ServletDemo4
*/
public class ServletDemo4 extends HttpServlet {
  private ServletConfig config;//config對象專門操作配置文件信息

  @Override
  public void init(ServletConfig config) throws ServletException {
      // TODO Auto-generated method stub
      this.config = config;
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      String encoding = config.getInitParameter("encoding");//獲得配置文件中的信息
      System.out.println(encoding);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}

總結:
這樣做的好處是:如果將數據庫信息、編碼方式等配置信息放在web.xml中,如果以后數據庫的用戶名、密碼改變了,則直接很方便地修改web.xml就行了,避免了直接修改源代碼的麻煩。
獲取Servlet配置信息的方式(關鍵得到ServletConfig對象):

方式一:


image.png

方式二:

image.png

方式三:

image.png

7. ServletContext

ServletContext: 代表的是整個應用。一個應用只有一個ServletContext對象。單實例。

ServletContext與ServletConfig的區別:

image.png

作用:

a. 作為 域對象:在一定范圍內(當前應用),使多個Servlet共享數據。

★ 域對象:在一個可以被看見的范圍內共享數據用到對象
★ 作用范圍:整個web應用范圍內共享數據
★ 生命周期:當服務器啟動web應用加載后創建出ServletContext對象后,域產生。當web應用被移除出容器或服務器關閉,隨著web應用的銷毀域銷毀。
常用方法:
void setAttribute(String name,object value);//向ServletContext對象的map中添加數據
Object getAttribute(String name);//從ServletContext對象的map中取數據
void rmoveAttribute(String name);//根據name去移除數據
把數據添加到ServletContext的map里:

package com.cms.Demo1.Service;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ServletDemo5
 */
public class ServletDemo5 extends HttpServlet {

    /**
     * @see HttpServoGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通過GenericServlet類 繼承的的getServletContext()方法得到ServletContext對象
    ServletContext application = this.getServletContext();//輸完this.getServletContext() 后Ctrl+回車,對象ServletContext通常用application(應用)表示。
//向ServletContext添加一個鍵值對
    application.setAttribute("name", "value");
    
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

取出:

package com.cms.Demo1.Service;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ServletDemo6
 */
public class ServletDemo6 extends HttpServlet {


    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = (String) this.getServletContext().getAttribute("name");
        System.out.println(name);
        if(name==null){
            System.out.println("你無權訪問");
        }
        System.out.println();
    
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

b. 獲取全局配置信息:

web.xml文件:
String類型--getInitParameter(String name) //根據配置文件中的key得到value

image.png

Java文件:

image.png
c.獲取資源路徑:

String getRealPath(String path);//根據資源名稱得到資源的絕對路徑.
可以得到當前應用任何位置的任何資源。

image.png

注意:
getRealPath的路徑是參考部署后(publish)的文件路徑
'/'代表當前項目部署后的根目錄:D:\apache-tomcat-7.0.52\webapps\webService

實現Servlet的轉發:
image.png

注意:
RequestDispatcher getRequestDispatcher(String path) ;//參數表示要跳轉到哪去

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容