Servlet的原理、周期夫偶、創(chuàng)建方法界睁、Servlet的線程安全、ServletConfig以及重要的ServletContext

1.什么是servlet

servlet是一個(gè)Java類兵拢,是用來專門處理請求和響應(yīng)的翻斟,是部署在服務(wù)器上工作的小程序,之所以叫小程序说铃,是因?yàn)樗灰渴鹕先ゾ妥詣?dòng)運(yùn)行工作了可以處理事情了访惜。servlet 通常通過 HTTP(超文本傳輸協(xié)議)接收和響應(yīng)來自 Web 客戶端的請求嘹履。
HTTP:
★ HTTP是HyperText Transfer Protocol(超文本傳輸協(xié)議)的簡寫,傳輸HTML文件债热。
★ 用于定義WEB瀏覽器與WEB服務(wù)器之間交換數(shù)據(jù)的過程及數(shù)據(jù)本身的格式砾嫉。

2.操作步驟:

a.創(chuàng)建一個(gè)實(shí)現(xiàn)servlet接口的Java類(ServletDemo1)。
ServletDemo1爆紅是因?yàn)閷?shí)現(xiàn)了Servlet接口就需要重寫里面的方法窒篱。實(shí)現(xiàn)接口所定義的方法焕刮。
在service方法里添加輸出語句

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

b.在web.xml中配置servlet的信息。
我們的目的就是讓用戶通過url來訪問我們的剛剛實(shí)現(xiàn)了servlet接口的類墙杯,然后在這個(gè)類里面做一些處理配并。但是我們的類是寫在src中,然后編譯成字節(jié)碼.class文件是存放在WEB-INF中的高镐,我們部署應(yīng)用的時(shí)候就把WEB-INF的東西部署到服務(wù)器上溉旋,而WEB-INF文件中的東西是不允許外部訪問的,所以如果想要訪問的這個(gè)類(嚴(yán)格意義上說是這個(gè)類生成的字節(jié)碼文件)嫉髓,我們就需要通過一些配置來告訴服務(wù)器某個(gè)URL地址是用來訪問某個(gè)類的观腊。這就是我們?yōu)槭裁匆渲脀eb.xml的原因。(服務(wù)器Tomcat啟動(dòng)后加載項(xiàng)目最先掃描執(zhí)行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/應(yīng)用名/demo1后梧油,它就會找到中相應(yīng)的url(在中),然后根據(jù)這個(gè)url找到對應(yīng)的叫servletDemo1州邢,然后就在這個(gè)節(jié)點(diǎn)里再找到該對應(yīng)的婶溯。至此,就自動(dòng)找到這個(gè)類偷霉,去執(zhí)行相應(yīng)的任務(wù)了迄委。
  <servlet>
    <servlet-name>servelDemo1</servlet-name>
    <servlet-class>com.cms.Demo1.Service.ServelDemo1</servlet-class>
  <!-- 2,填數(shù)字越小優(yōu)先級越高类少,越先執(zhí)行叙身,讓該servlet在服務(wù)器啟動(dòng)時(shí)就創(chuàng)建,不建議寫零 -->
    <load-on-startup>2</load-on-startup>
  </servlet>
 <!-- 給Servlet映射一個(gè)可訪問的URI :http://localhost:8080/項(xiàng)目名/demo1即可通過servelDemo1映射到ServelDemo1訪問該類-->
  <servlet-mapping>
    <servlet-name>servelDemo1</servlet-name>
    <url-pattern>/demo1</url-pattern>
  </servlet-mapping>

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


image.png

執(zhí)行結(jié)果:

瀏覽器顯示空白頁面但是控制臺輸出了ServletDemo1類里的執(zhí)行結(jié)果硫狞。

image.png

3.Servlet的生命周期

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

a .初始化階段 :
構(gòu)造 servlet财忽,然后使用 init 方法將其初始化。
b.響應(yīng)客戶請求階段:
處理來自客戶端的對 service 方法的所有調(diào)用泣侮。
c.終止階段:
從服務(wù)中取出 servlet即彪,然后調(diào)用 destroy 方法銷毀它,最后進(jìn)行垃圾回收并終止它活尊。

除了生命周期方法之外隶校,此接口還提供了 getServletConfig 方法和 getServletInfo 方法漏益,servlet 可使用前一種方法獲得任何啟動(dòng)信息,而后一種方法允許 servlet 返回有關(guān)其自身的基本信息深胳,比如作者绰疤、版本和版權(quán)。

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() {
        // 實(shí)例化方法
    }
    @Override
    public void init(ServletConfig arg0) throws ServletException {
        // 初始化      
    }
    @Override
    public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
        // 服務(wù)
        System.out.println("執(zhí)行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何時(shí)被創(chuàng)建:
  ★ 默認(rèn)情況下舞终,當(dāng)WEB客戶第一次請求訪問某個(gè)Servlet的時(shí)候轻庆,WEB容器將創(chuàng)建這個(gè)Servlet的實(shí)例。
  ★ 當(dāng)web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素時(shí)敛劝,Servlet容器在啟動(dòng)web服務(wù)器時(shí)榨了,將按照順序創(chuàng)建并初始化Servlet對象。
  ★ 在web.xml文件中攘蔽,某些Servlet只有<serlvet>元素,沒有<servlet-mapping>元素呐粘,這樣我們無法通過url的方式訪問這些Servlet满俗,這種Servlet通常會在<servlet>元素中配置一個(gè)<load-on-startup>子元素,讓容器在啟動(dòng)的時(shí)候自動(dòng)加載這些Servlet并調(diào)用init()方法作岖,完成一些全局性的初始化工作唆垃。

4.servlet的三種創(chuàng)建方式

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

方法如下:
a. 實(shí)現(xiàn)javax.servlet.Servlet接口(參見:編寫一個(gè)servlet程序)
要實(shí)現(xiàn)此接口,還可以編寫一個(gè)擴(kuò)展 javax.servlet.GenericServlet 的一般 servlet痘儡,或者編寫一個(gè)擴(kuò)展 javax.servlet.http.HttpServlet 的 HTTP servlet辕万。

image.png

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

image.png

只需重寫抽象 service 方法,因?yàn)樗锩嬷挥幸粋€(gè)抽象方法沉删。

image.png
image.png

c. 繼承javax.servlet.http.HttpServlet類(模板方法設(shè)計(jì)模式)
我們自己寫Servlet的時(shí)候渐尿,處理請求的時(shí)候?qū)崿F(xiàn)Service()就好。不重寫Service()方法矾瑰,而是重寫doGet和doPost2個(gè)方法砖茸,在HttpServlet抽象類中,已經(jīng)實(shí)現(xiàn)了Service方法了殴穴,在有請求進(jìn)來Servlet的時(shí)候首先從請求中獲取到請求提交的方式凉夯,所以我們直接重寫doGet和doPost方法就好。通常來說不確定是什么請求的情況下采幌,默認(rèn)是Get請求劲够,在doGet和doPost中實(shí)現(xiàn)一個(gè)就夠了,如果方法的實(shí)現(xiàn)寫在
HTTP的請求方式包括DELETE,GET,OPTIONS,POST,PUT和TRACE,在HttpServlet類中分別提供了相應(yīng)的服務(wù)方法,它們是,doDelete(),doGet(),doOptions(),doPost(), doPut()和doTrace().
項(xiàng)目開發(fā)一般都用這種方式創(chuàng)建Servlet;
第一步:創(chuàng)建Servlet類文件
Ctrl+N休傍;輸入Servlet:

image.png

第二步:輸入類名

image.png

第三步:映射路徑的名字征绎,默認(rèn)為類名,可點(diǎn)擊Edit編輯


image.png

第三步:勾選需要重寫的方法:都默認(rèn)勾選Doget和Dopost方法磨取,點(diǎn)擊Finish:
繼承HttpServlet后不要重寫service的方法炒瘸,因?yàn)閟ervice方法里包含調(diào)用doget跟dopost的方法淤堵,重寫了那兩方法不執(zhí)行就作廢了


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 的源碼包導(dǎo)Tomcat的源碼包,apache-tomcat-7.0.81-src.zip顷扩。Outline的窗口帶三角的說明是繼承過來重寫的方法拐邪,沒有的才是自己本身的。

image.png

servet映射細(xì)節(jié)

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

如果url-pattern的值是/隘截,表示執(zhí)行默認(rèn)映射扎阶。所有資源都是servlet

5. Servlet的線程安全

★ 單實(shí)例:每次訪問多線程
★ 解決線程安全問題的最佳辦法,不要寫全局變量婶芭,而寫局部變量东臀。
★ Servlet的線程安全問題只有在大量的并發(fā)訪問時(shí)才會顯現(xiàn)出來,并且很難發(fā)現(xiàn)犀农,因此在編寫Servlet程序時(shí)要特別注意惰赋。
★ servlet處于服務(wù)器進(jìn)程中濒募,它通過多線程方式運(yùn)行其service方法禽最,一個(gè)實(shí)例可以服務(wù)于多個(gè)請求,并且其實(shí)例一般不會銷毀,所以你的項(xiàng)目中如果只有一個(gè)servlet,那么web容器就只會創(chuàng)建一個(gè)實(shí)例净宵。所以其默認(rèn)非線程安全孟害,如果需要線程安全需要指明拒炎。

6.ServletConfig

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

6.1Servlet配置信息的獲取:

當(dāng)servlet配置了初始化參數(shù)后挨务,web容器在創(chuàng)建servlet實(shí)例對象時(shí)击你,會自動(dòng)將這些初始化參數(shù)封裝到ServletConfig對象中,并在調(diào)用servlet的init方法時(shí)谎柄,將ServletConfig對象傳遞給servlet丁侄。進(jìn)而,程序員通過ServletConfig對象就可以得到當(dāng)前servlet的初始化參數(shù)信息朝巫。
web.xml绒障。只要有ServletConfig對象就能調(diào)用getInitParameter方法。

<servlet>
        <display-name>servletDemo4</display-name>
        <servlet-name>ServletDemo4</servlet-name>
        <servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
        <!-- 初始化參數(shù) -->
        <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);
  }

}

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

方式一:


image.png

方式二:

image.png

方式三:

image.png

7. ServletContext

ServletContext: 代表的是整個(gè)應(yīng)用变逃。一個(gè)應(yīng)用只有一個(gè)ServletContext對象必逆。單實(shí)例。

ServletContext與ServletConfig的區(qū)別:

image.png

作用:

a. 作為 域?qū)ο螅涸谝欢ǚ秶鷥?nèi)(當(dāng)前應(yīng)用),使多個(gè)Servlet共享數(shù)據(jù)名眉。

★ 域?qū)ο螅涸谝粋€(gè)可以被看見的范圍內(nèi)共享數(shù)據(jù)用到對象
★ 作用范圍:整個(gè)web應(yīng)用范圍內(nèi)共享數(shù)據(jù)
★ 生命周期:當(dāng)服務(wù)器啟動(dòng)web應(yīng)用加載后創(chuàng)建出ServletContext對象后粟矿,域產(chǎn)生。當(dāng)web應(yīng)用被移除出容器或服務(wù)器關(guān)閉损拢,隨著web應(yīng)用的銷毀域銷毀陌粹。
常用方法:
void setAttribute(String name,object value);//向ServletContext對象的map中添加數(shù)據(jù)
Object getAttribute(String name);//從ServletContext對象的map中取數(shù)據(jù)
void rmoveAttribute(String name);//根據(jù)name去移除數(shù)據(jù)
把數(shù)據(jù)添加到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(應(yīng)用)表示福压。
//向ServletContext添加一個(gè)鍵值對
    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("你無權(quán)訪問");
        }
        System.out.println();
    
    }

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

}

b. 獲取全局配置信息:

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

image.png

Java文件:

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

String getRealPath(String path);//根據(jù)資源名稱得到資源的絕對路徑.
可以得到當(dāng)前應(yīng)用任何位置的任何資源掏秩。

image.png

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

實(shí)現(xiàn)Servlet的轉(zhuǎn)發(fā):
image.png

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市荆姆,隨后出現(xiàn)的幾起案子蒙幻,更是在濱河造成了極大的恐慌,老刑警劉巖胆筒,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邮破,死亡現(xiàn)場離奇詭異,居然都是意外死亡仆救,警方通過查閱死者的電腦和手機(jī)抒和,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來派桩,“玉大人,你說我怎么就攤上這事蚌斩∶螅” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵送膳,是天一觀的道長员魏。 經(jīng)常有香客問我,道長叠聋,這世上最難降的妖魔是什么撕阎? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮碌补,結(jié)果婚禮上虏束,老公的妹妹穿的比我還像新娘。我一直安慰自己厦章,他們只是感情好镇匀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著袜啃,像睡著了一般汗侵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天晰韵,我揣著相機(jī)與錄音发乔,去河邊找鬼。 笑死雪猪,一個(gè)胖子當(dāng)著我的面吹牛栏尚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播浪蹂,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抵栈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了坤次?” 一聲冷哼從身側(cè)響起古劲,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缰猴,沒想到半個(gè)月后产艾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滑绒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年闷堡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疑故。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杠览,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纵势,到底是詐尸還是另有隱情踱阿,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布钦铁,位于F島的核電站软舌,受9級特大地震影響佛点,放射性物質(zhì)發(fā)生泄漏黎比。R本人自食惡果不足惜超营,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一聊闯、第九天 我趴在偏房一處隱蔽的房頂上張望蚪腐。 院中可真熱鬧,春花似錦芥永、人聲如沸篡殷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽板辽。三九已至,卻和暖如春棘催,著一層夾襖步出監(jiān)牢的瞬間劲弦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工醇坝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留邑跪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像画畅,于是被迫代替她去往敵國和親砸琅。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容