理解Servlet工作原理

什么是Servlet

Servlet的作用是為Java程序提供一個統(tǒng)一的web應用的規(guī)范他匪,方便程序員統(tǒng)一的使用這種規(guī)范來編寫程序岖圈,應用容器可以使用提供的規(guī)范來實現(xiàn)自己的特性。比如tomcat的代碼和jetty的代碼就不一樣,但作為程序員你只需要了解servlet規(guī)范就可以從request中取值,你可以操作session等等癌压。不用在意應用服務器底層的實現(xiàn)的差別而影響你的開發(fā)。

HTTP 協(xié)議只是一個規(guī)范荆陆,定義服務請求和響應的大致式樣滩届。Java servlet 類將HTTP中那些低層的結構包裝在 Java 類中,這些類所包含的便利方法使其在 Java 語言環(huán)境中更易于處理被啼。

正如您正使用的特定 servlet 容器的配置文件中所定義的帜消,當用戶通過 URL 發(fā)出一個請求時,這些 Java servlet 類就將之轉(zhuǎn)換成一個 HttpServletRequest浓体,并發(fā)送給 URL 所指向的目標泡挺。當服務器端完成其工作時,Java 運行時環(huán)境(Java Runtime Environment)就將結果包裝在一個 HttpServletResponse 中命浴,然后將原 HTTP 響應送回給發(fā)出該請求的客戶機娄猫。在與 Web 應用程序進行交互時,通常會發(fā)出多個請求并獲得多個響應生闲。所有這些都是在一個會話語境中媳溺,Java 語言將之包裝在一個 HttpSession 對象中。在處理響應時碍讯,您可以訪問該對象悬蔽,并在創(chuàng)建響應時向其添加事件。它提供了一些跨請求的語境捉兴。

容器(如 Tomcat)將為 servlet 管理運行時環(huán)境蝎困。您可以配置該容器,定制 J2EE 服務器的工作方式倍啥,以便將 servlet 暴露給外部世界禾乘。正如我們將看到的,通過該容器中的各種配置文件虽缕,您在 URL(由用戶在瀏覽器中輸入)與服務器端組件之間搭建了一座橋梁始藕,這些組件將處理您需要該 URL 轉(zhuǎn)換的請求。在運行應用程序時彼宠,該容器將加載并初始化 servlet鳄虱,管理其生命周期弟塞。

Servlet體系結構

Servlet頂級類關聯(lián)圖

Servlet

Servlet的框架是由兩個Java包組成的:javax.servlet與javax.servlet.http凭峡。在javax.servlet包中定義了所有的Servlet類都必須實現(xiàn)或者擴展的通用接口和類。在javax.servlet.http包中定義了采用Http協(xié)議通信的HttpServlet類决记。Servlet的框架的核心是javax.servlet.Servlet接口摧冀,所有的Servlet都必須實現(xiàn)這個接口。

Servlet接口

在Servlet接口中定義了5個方法:

1. init(ServletConfig)方法:負責初始化Servlet對象,在Servlet的生命周期中索昂,該方法執(zhí)行一次建车;該方法執(zhí)行在單線程的環(huán)境下,因此開發(fā)者不用考慮線程安全的問題椒惨;
2. service(ServletRequest req,ServletResponse res)方法:負責響應客戶的請求缤至;為了提高效率,Servlet規(guī)范要求一個Servlet實例必須能夠同時服務于多個客戶端請求康谆,即service()方法運行在多線程的環(huán)境下领斥,Servlet開發(fā)者必須保證該方法的線程安全性;
3. destroy()方法:當Servlet對象退出生命周期時沃暗,負責釋放占用的資源月洛;
4. getServletInfo:就是字面意思,返回Servlet的描述孽锥;
5. getServletConfig:這個方法返回由Servlet容器傳給init方法的ServletConfig嚼黔。

ServletRequest & ServletResponse

對于每一個HTTP請求,servlet容器會創(chuàng)建一個封裝了HTTP請求的ServletRequest實例傳遞給servlet的service方法惜辑,ServletResponse則表示一個Servlet響應唬涧,其隱藏了將響應發(fā)給瀏覽器的復雜性。通過ServletRequest的方法你可以獲取一些請求相關的參數(shù)盛撑,而ServletResponse則可以將設置一些返回參數(shù)信息爵卒,并且設置返回內(nèi)容。

ServletConfig

ServletConfig封裝可以通過@WebServlet或者web.xml傳給一個Servlet的配置信息撵彻,以這種方式傳遞的每一條信息都稱做初始化信息钓株,初始化信息就是一個個K-V鍵值對。為了從一個Servlet內(nèi)部獲取某個初始參數(shù)的值陌僵,init方法中調(diào)用ServletConfig的getinitParameter方法或getinitParameterNames方法獲取轴合,除此之外,還可以通過getServletContext獲取ServletContext對象碗短。

ServletContext

ServletContext是代表了Servlet應用程序受葛。每個Web應用程序只有一個context。在分布式環(huán)境中偎谁,一個應用程序同時部署到多個容器中总滩,并且每臺Java虛擬機都有一個ServletContext對象。有了ServletContext對象后巡雨,就可以共享能通過應用程序的所有資源訪問的信息闰渔,促進Web對象的動態(tài)注冊,共享的信息通過一個內(nèi)部Map中的對象保存在ServiceContext中來實現(xiàn)铐望。保存在ServletContext中的對象稱作屬性冈涧。操作屬性的方法:

GenericServlet

前面編寫的Servlet應用中通過實現(xiàn)Servlet接口來編寫Servlet茂附,但是我們每次都必須為Servlet中的所有方法都提供實現(xiàn),還需要將ServletConfig對象保存到一個類級別的變量中督弓,GenericServlet抽象類就是為了為我們省略一些模板代碼营曼,實現(xiàn)了Servlet和ServletConfig,完成了一下幾個工作:

將init方法中的ServletConfig賦給一個類級變量愚隧,使的可以通過getServletConfig來獲取蒂阱。

public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
}

同時為避免覆蓋init方法后在子類中必須調(diào)用super.init(servletConfig),GenericServlet還提供了一個不帶參數(shù)的init方法狂塘,當ServletConfig賦值完成就會被第帶參數(shù)的init方法調(diào)用蒜危。這樣就可以通過覆蓋不帶參數(shù)的init方法編寫初始化代碼,而ServletConfig實例依然得以保存

為Servlet接口中的所有方法提供默認實現(xiàn)睹耐。

提供方法來包裝ServletConfig中的方法辐赞。

HTTPServlet

在編寫Servlet應用程序時,大多數(shù)都要用到HTTP硝训,也就是說可以利用HTTP提供的特性响委,javax.servlet.http包含了編寫Servlet應用程序的類和接口,其中很多覆蓋了javax.servlet中的類型窖梁,我們自己在編寫應用時大多時候也是繼承的HttpServlet赘风。

Servlet工作原理

當Web服務器接收到一個HTTP請求時,它會先判斷請求內(nèi)容——如果是靜態(tài)網(wǎng)頁數(shù)據(jù)纵刘,Web服務器將會自行處理邀窃,然后產(chǎn)生響應信息;如果牽涉到動態(tài)數(shù)據(jù)假哎,Web服務器會將請求轉(zhuǎn)交給Servlet容器瞬捕。此時Servlet容器會找到對應的處理該請求的Servlet實例來處理,結果會送回Web服務器舵抹,再由Web服務器傳回用戶端肪虎。

針對同一個Servlet,Servlet容器會在第一次收到http請求時建立一個Servlet實例惧蛹,然后啟動一個線程扇救。第二次收到http請求時,Servlet容器無須建立相同的Servlet實例香嗓,而是啟動第二個線程來服務客戶端請求迅腔。所以多線程方式不但可以提高Web應用程序的執(zhí)行效率,也可以降低Web服務器的系統(tǒng)負擔靠娱。

Web服務器工作流程

接著我們描述一下Tomcat與Servlet是如何工作的沧烈,首先看下面的時序圖:

Servlet工作原理時序圖
  1. Web Client 向Servlet容器(Tomcat)發(fā)出Http請求;

  2. Servlet容器接收Web Client的請求饱岸;

  3. Servlet容器創(chuàng)建一個HttpRequest對象掺出,將Web Client請求的信息封裝到這個對象中;

  4. Servlet容器創(chuàng)建一個HttpResponse對象苫费;

  5. Servlet容器調(diào)用HttpServlet對象的service方法汤锨,把HttpRequest對象與HttpResponse對象作為參數(shù)傳給 HttpServlet對象;

  6. HttpServlet調(diào)用HttpRequest對象的有關方法百框,獲取Http請求信息闲礼;

  7. HttpServlet調(diào)用HttpResponse對象的有關方法,生成響應數(shù)據(jù)铐维;

  8. Servlet容器把HttpServlet的響應結果傳給Web Client柬泽;

Servlet生命周期

在Servlet接口中定義了5個方法,其中3個方法代表了Servlet的生命周期:

1. init(ServletConfig)方法:負責初始化Servlet對象嫁蛇,在Servlet的生命周期中锨并,該方法執(zhí)行一次;該方法執(zhí)行在單線程的環(huán)境下睬棚,因此開發(fā)者不用考慮線程安全的問題第煮;
2. service(ServletRequest req,ServletResponse res)方法:負責響應客戶的請求;為了提高效率抑党,Servlet規(guī)范要求一個Servlet實例必須能夠同時服務于多個客戶端請求包警,即service()方法運行在多線程的環(huán)境下,Servlet開發(fā)者必須保證該方法的線程安全性底靠;
3. destroy()方法:當Servlet對象退出生命周期時害晦,負責釋放占用的資源;

編程注意事項說明:

  1. 當Server Thread線程執(zhí)行Servlet實例的init()方法時暑中,所有的Client Service Thread線程都不能執(zhí)行該實例的service()方法壹瘟,更沒有線程能夠執(zhí)行該實例的destroy()方法,因此Servlet的init()方法是工作在單線程的環(huán)境下鳄逾,開發(fā)者不必考慮任何線程安全的問題俐筋。
  2. 當服務器接收到來自客戶端的多個請求時,服務器會在單獨的Client Service Thread線程中執(zhí)行Servlet實例的service()方法服務于每個客戶端严衬。此時會有多個線程同時執(zhí)行同一個Servlet實例的service()方法澄者,因此必須考慮線程安全的問題。
  3. 雖然service()方法運行在多線程的環(huán)境下请琳,并不一定要同步該方法粱挡。而是要看這個方法在執(zhí)行過程中訪問的資源類型及對資源的訪問方式。分析如下:
1. 如果service()方法沒有訪問Servlet的成員變量也沒有訪問全局的資源比如靜態(tài)變量俄精、文件询筏、數(shù)據(jù)庫連接等,而是只使用了當前線程自己的資源竖慧,比如非指向全局資源的臨時變量嫌套、request和response對象等逆屡。該方法本身就是線程安全的,不必進行任何的同步控制踱讨。

2. 如果service()方法訪問了Servlet的成員變量魏蔗,但是對該變量的操作是只讀操作,該方法本身就是線程安全的痹筛,不必進行任何的同步控制莺治。

3. 如果service()方法訪問了Servlet的成員變量,并且對該變量的操作既有讀又有寫帚稠,通常需要加上同步控制語句谣旁。

4. 如果service()方法訪問了全局的靜態(tài)變量,如果同一時刻系統(tǒng)中也可能有其它線程訪問該靜態(tài)變量滋早,如果既有讀也有寫的操作榄审,通常需要加上同步控制語句。

5. 如果service()方法訪問了全局的資源杆麸,比如文件瘟判、數(shù)據(jù)庫連接等,通常需要加上同步控制語句角溃。

在創(chuàng)建一個 Java servlet 時拷获,一般需要子類 HttpServlet。該類中的方法允許您訪問請求和響應包裝器(wrapper)减细,您可以用這個包裝器來處理請求和創(chuàng)建響應匆瓜。Servlet的生命周期,簡單的概括這就分為四步:

Servlet類加載--->實例化--->服務--->銷毀未蝌;
Servlet生命周期

創(chuàng)建Servlet對象的時機:

  1. 默認情況下驮吱,在Servlet容器啟動后:客戶首次向Servlet發(fā)出請求,Servlet容器會判斷內(nèi)存中是否存在指定的Servlet對象萧吠,如果沒有則創(chuàng)建它左冬,然后根據(jù)客戶的請求創(chuàng)建HttpRequest、HttpResponse對象纸型,從而調(diào)用Servlet對象的service方法拇砰;
  2. Servlet容器啟動時:當web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素時,Servlet容器在啟動web服務器時狰腌,將按照順序創(chuàng)建并初始化Servlet對象除破;
  3. Servlet的類文件被更新后,重新創(chuàng)建Servlet琼腔。Servlet容器在啟動時自動創(chuàng)建Servlet瑰枫,這是由在web.xml文件中為Servlet設置的<load-on-startup>屬性決定的。從中我們也能看到同一個類型的Servlet對象在Servlet容器中以單例的形式存在丹莲;

注意:在web.xml文件中光坝,某些Servlet只有<serlvet>元素尸诽,沒有<servlet-mapping>元素,這樣我們無法通過url的方式訪問這些Servlet盯另,這種Servlet通常會在<servlet>元素中配置一個<load-on-startup>子元素性含,讓容器在啟動的時候自動加載這些Servlet并調(diào)用init(ServletConfig config)方法來初始化該Servlet。其中方法參數(shù)config中包含了Servlet的配置信息土铺,比如初始化參數(shù)胶滋,該對象由服務器創(chuàng)建板鬓。

銷毀Servlet對象的時機:

Servlet容器停止或者重新啟動:Servlet容器調(diào)用Servlet對象的destroy方法來釋放資源悲敷。以上所講的就是Servlet對象的生命周期。那么Servlet容器如何知道創(chuàng)建哪一個Servlet對象俭令?Servlet對象如何配置后德?實際上這些信息是通過讀取web.xml配置文件來實現(xiàn)的。

<servlet>
    <!-- Servlet對象的名稱 -->
    <servlet-name>action<servlet-name>
    <!-- 創(chuàng)建Servlet對象所要調(diào)用的類 -->
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
        <!-- 參數(shù)名稱 -->
        <param-name>config</param-name>
        <!-- 參數(shù)值 -->
        <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
        <param-name>detail</param-name>
        <param-value>2</param-value>
    </init-param>
    <init-param>
        <param-name>debug</param-name>
        <param-value>2</param-value>
    </init-param>
    <!-- Servlet容器啟動時加載Servlet對象的順序 -->
    <load-on-startup>2</load-on-startup>
</servlet>
<!-- 要與servlet中的servlet-name配置節(jié)內(nèi)容對應 -->
<servlet-mapping>
    <servlet-name>action</servlet-name>
    <!-- 客戶訪問的Servlet的相對URL路徑 -->
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

當Servlet容器啟動的時候讀取<servlet>配置節(jié)信息抄腔,根據(jù)<servlet-class>配置節(jié)信息創(chuàng)建Servlet對象瓢湃,同時根據(jù)<init-param>配置節(jié)信息創(chuàng)建HttpServletConfig對象,然后執(zhí)行Servlet對象的init方法赫蛇,并且根據(jù)<load-on-startup>配置節(jié)信息來決定創(chuàng)建Servlet對象的順序绵患,如果此配置節(jié)信息為負數(shù)或者沒有配置,那么在Servlet容器啟動時悟耘,將不加載此Servlet對象落蝙。當客戶訪問Servlet容器時,Servlet容器根據(jù)客戶訪問的URL地址暂幼,通過<servlet-mapping>配置節(jié)中的<url-pattern>配置節(jié)信息找到指定的Servlet對象筏勒,并調(diào)用此Servlet對象的service方法。

在整個Servlet的生命周期過程中旺嬉,創(chuàng)建Servlet實例管行、調(diào)用實例的init()和destroy()方法都只進行一次,當初始化完成后邪媳,Servlet容器會將該實例保存在內(nèi)存中捐顷,通過調(diào)用它的service()方法,為接收到的請求服務雨效。下面給出Servlet整個生命周期過程的UML序列圖套菜,如圖所示:

Servlet生命周期

如果需要讓Servlet容器在啟動時即加載Servlet,可以在web.xml文件中配置<load-on-startup>元素设易。

Servlet中的Listener

Listener 使用的非常廣泛逗柴,它是基于觀察者模式設計的,Listener 的設計對開發(fā) Servlet 應用程序提供了一種快捷的手段顿肺,能夠方便的從另一個縱向維度控制程序和數(shù)據(jù)戏溺。目前 Servlet 中提供了 5 種兩類事件的觀察者接口渣蜗,它們分別是:4 個 EventListeners 類型的,ServletContextAttributeListener旷祸、ServletRequestAttributeListener耕拷、ServletRequestListener、HttpSessionAttributeListener 和 2 個 LifecycleListeners 類型的托享,ServletContextListener骚烧、HttpSessionListener。如下圖所示:

Servlet中的Listener

它們基本上涵蓋了整個 Servlet 生命周期中闰围,你感興趣的每種事件赃绊。這些 Listener 的實現(xiàn)類可以配置在 web.xml 中的 <listener> 標簽中。當然也可以在應用程序中動態(tài)添加 Listener羡榴,需要注意的是 ServletContextListener 在容器啟動之后就不能再添加新的碧查,因為它所監(jiān)聽的事件已經(jīng)不會再出現(xiàn)。掌握這些 Listener 的使用校仑,能夠讓我們的程序設計的更加靈活忠售。

Cookie與Session

Servlet 能夠給我們提供兩部分數(shù)據(jù),一個是在 Servlet 初始化時調(diào)用 init 方法時設置的 ServletConfig迄沫,這個類基本上含有了 Servlet 本身和 Servlet 所運行的 Servlet 容器中的基本信息稻扬。還有一部分數(shù)據(jù)是由 ServletRequest 類提供,從提供的方法中發(fā)現(xiàn)主要是描述這次請求的 HTTP 協(xié)議的信息羊瘩。關于這一塊還有一個讓很多人迷惑的 Session 與 Cookie泰佳。

Session 與 Cookie 的作用都是為了保持訪問用戶與后端服務器的交互狀態(tài)。它們有各自的優(yōu)點也有各自的缺陷困后。然而具有諷刺意味的是它們優(yōu)點和它們的使用場景又是矛盾的乐纸,例如使用 Cookie 來傳遞信息時,隨著 Cookie 個數(shù)的增多和訪問量的增加摇予,它占用的網(wǎng)絡帶寬也也會越來越大汽绢。所以大訪問量的時候希望用 Session,但是 Session 的致命弱點是不容易在多臺服務器之間共享侧戴,所以這也限制了 Session 的使用宁昭。

不管 Session 和 Cookie 有什么不足,我們還是要用它們酗宋。下面詳細講一下叁熔,Session 如何基于 Cookie 來工作悼尾。實際上有三種方式能可以讓 Session 正常工作:

  • 基于 URL Path Parameter,默認就支持
  • 基于 Cookie,如果你沒有修改 Context 容器個 cookies 標識的話耳贬,默認也是支持的
  • 基于 SSL,默認不支持,只有 connector.getAttribute("SSLEnabled") 為 TRUE 時才支持

第一種情況下,當瀏覽器不支持 Cookie 功能時漱挚,瀏覽器會將用戶的 SessionCookieName 重寫到用戶請求的 URL 參數(shù)中,它的傳遞格式如:

 /path/Servlet?name=value&name2=value2&JSESSIONID=value3

接著 Request 根據(jù)這個 JSESSIONID 參數(shù)拿到 Session ID 并設置到 request.setRequestedSessionId 中渺氧。

請注意如果客戶端也支持 Cookie 的話旨涝,Tomcat 仍然會解析 Cookie 中的 Session ID,并會覆蓋 URL 中的 Session ID侣背。

如果是第三種情況的話將會根據(jù) javax.servlet.request.ssl_session 屬性值設置 Session ID白华。

有了 Session ID 服務器端就可以創(chuàng)建 HttpSession 對象了,第一次觸發(fā)是通過 request. getSession() 方法贩耐,如果當前的 Session ID 還沒有對應的 HttpSession 對象那么就創(chuàng)建一個新的弧腥,并將這個對象加到 org.apache.catalina. Manager 的 sessions 容器中保存,Manager 類將管理所有 Session 的生命周期憔杨,Session 過期將被回收鸟赫,服務器關閉蒜胖,Session 將被序列化到磁盤等消别。只要這個 HttpSession 對象存在,用戶就可以根據(jù) Session ID 來獲取到這個對象台谢,也就達到了狀態(tài)的保持寻狂。

Session相關類圖

上從圖中可以看出從 request.getSession 中獲取的 HttpSession 對象實際上是 StandardSession 對象的門面對象,這與前面的 Request 和 Servlet 是一樣的原理朋沮。下圖是 Session 工作的時序圖:

Session工作的時序圖

還有一點與 Session 關聯(lián)的 Cookie 與其它 Cookie 沒有什么不同蛇券,這個配置的配置可以通過 web.xml 中的 session-config 配置項來指定。

參考

WEB請求處理三:Servlet容器請求處理

Java Servlet 技術簡介

Servlet 工作原理解析

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末樊拓,一起剝皮案震驚了整個濱河市纠亚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌筋夏,老刑警劉巖蒂胞,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異条篷,居然都是意外死亡骗随,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門赴叹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸿染,“玉大人,你說我怎么就攤上這事乞巧≌墙罚” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蚕冬。 經(jīng)常有香客問我柱宦,道長,這世上最難降的妖魔是什么播瞳? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任掸刊,我火速辦了婚禮,結果婚禮上赢乓,老公的妹妹穿的比我還像新娘忧侧。我一直安慰自己,他們只是感情好牌芋,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布蚓炬。 她就那樣靜靜地躺著,像睡著了一般躺屁。 火紅的嫁衣襯著肌膚如雪肯夏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天犀暑,我揣著相機與錄音驯击,去河邊找鬼。 笑死耐亏,一個胖子當著我的面吹牛徊都,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播广辰,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼暇矫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了择吊?” 一聲冷哼從身側(cè)響起李根,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎几睛,沒想到半個月后房轿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡枉长,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年冀续,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片必峰。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡洪唐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吼蚁,到底是詐尸還是另有隱情凭需,我是刑警寧澤问欠,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站粒蜈,受9級特大地震影響顺献,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枯怖,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一注整、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧度硝,春花似錦肿轨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至藻茂,卻和暖如春驹暑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辨赐。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工优俘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肖油。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓兼吓,卻偏偏與公主長得像臂港,于是被迫代替她去往敵國和親森枪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

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

  • 從三月份找實習到現(xiàn)在审孽,面了一些公司县袱,掛了不少,但最終還是拿到小米佑力、百度式散、阿里、京東打颤、新浪暴拄、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,194評論 11 349
  • 一 servlet概述 狹義的Servlet指javax.servlet包中的一個接口编饺,而廣義的Servlet則是...
    靜慎獨閱讀 450評論 0 0
  • 1. Java基礎部分 基礎部分的順序:基本語法乖篷,類相關的語法,內(nèi)部類的語法透且,繼承相關的語法撕蔼,異常的語法,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 這部分主要是與Java Web和Web Service相關的面試題。 96鲸沮、闡述Servlet和CGI的區(qū)別? 答...
    雜貨鋪老板閱讀 1,397評論 0 10
  • 復習復習A章狻!讼溺!搞起來i购拧!Servlet和JSP是Java EE規(guī)范最基本成員怒坯,他們是Java Web開發(fā)的重點知識...
    JackFrost_fuzhu閱讀 2,829評論 1 71