Java Web從如何啟動(dòng)到Servlet&Tomcat

平時(shí)我們?cè)趯?xiě)一般的應(yīng)用程序的時(shí)候,無(wú)論如何都會(huì)有一個(gè)main函數(shù)入口。而在進(jìn)行web開(kāi)發(fā)的時(shí)候喳钟,從頭到尾我們都沒(méi)有寫(xiě)過(guò)一個(gè)main函數(shù)。最后部署時(shí)在岂,打了一個(gè)war包奔则,傳到web容器下面就可以了。到底這后面發(fā)生了什么蔽午,帶著疑問(wèn)讓我開(kāi)始吧易茬。

基礎(chǔ)知識(shí)

先了解一下java web應(yīng)用目錄組織結(jié)構(gòu):

  • WebRoot :Web應(yīng)用所在目錄,一般情況下虛擬目錄要配置到此文件夾當(dāng)中及老。
  • WEB-INF:此文件夾必須位WebRoot文件夾里面抽莱,而且必須以這樣的形式去命名,字母都要大寫(xiě)骄恶。
  • Web.xml:配置文件食铐,有格式要求,此文件必須以這樣的形式去命名僧鲁,并且必須放置到WEB-INF文件夾中虐呻。

在看看一個(gè)瀏覽器與服務(wù)器交互的流程:

Servlet

在java web項(xiàng)目中,我們無(wú)論是用什么框架寞秃,Spring MVC也好斟叼,Spring Boot也好,最后都是Servlet在起著決定性的作用春寿。

Servlet是什么朗涩?

Servlet 是運(yùn)行在 Web 服務(wù)器或應(yīng)用服務(wù)器上的程序,它是作為來(lái)自瀏覽器或其他 HTTP 客戶(hù)端的請(qǐng)求和 HTTP 服務(wù)器上的數(shù)據(jù)庫(kù)或應(yīng)用程序之間的中間層绑改。

Servlet在Web應(yīng)用程序的位置如下圖所示:

image

Servlet程序是由web容器調(diào)用馋缅,也就解釋了為什么我們所寫(xiě)的web應(yīng)用程序不需要main函數(shù)的原因,它是由web容器根據(jù)請(qǐng)然后創(chuàng)建的绢淀。

Servlet主要作用有:

  • 讀取客戶(hù)端(瀏覽器)發(fā)送的數(shù)據(jù) 。
  • 處理數(shù)據(jù)并生成結(jié)果瘾腰。這個(gè)過(guò)程可能需要訪問(wèn)數(shù)據(jù)庫(kù)皆的,調(diào)用 Web 服務(wù),或者直接計(jì)算得出對(duì)應(yīng)的響應(yīng)蹋盆。平時(shí)的業(yè)務(wù)邏輯就是在這個(gè)部分實(shí)現(xiàn)费薄。
  • 發(fā)送處理過(guò)后的數(shù)據(jù)給客戶(hù)端(瀏覽器)硝全。

Servlet的運(yùn)行過(guò)程

web容器收到客戶(hù)端的訪問(wèn)請(qǐng)求后將進(jìn)行如下處理:

  1. Web容器首先檢查是否已經(jīng)裝載并創(chuàng)建了該Servlet的實(shí)例對(duì)象。如果是楞抡,則直接執(zhí)行第4步伟众,否則,執(zhí)行第2步召廷。
  2. 裝載并創(chuàng)建該Servlet的一個(gè)實(shí)例對(duì)象凳厢。
  3. 調(diào)用Servlet實(shí)例對(duì)象的init()方法。
  4. 創(chuàng)建一個(gè)用于封裝HTTP請(qǐng)求消息的HttpServletRequest對(duì)象和一個(gè)代表HTTP響應(yīng)消息的HttpServletResponse對(duì)象竞慢,然后調(diào)用Servlet的service()方法并將請(qǐng)求和響應(yīng)對(duì)象作為參數(shù)傳遞進(jìn)去先紫。
  5. WEB應(yīng)用程序被停止或重新啟動(dòng)之前,Servlet引擎將卸載Servlet筹煮,并在卸載之前調(diào)用Servlet的destroy()方法遮精。

具體來(lái)講可以用下面的圖說(shuō)明:

其時(shí)序圖可以用下圖表示:

一個(gè)Servlet例子

有了上面的理論基礎(chǔ)我們就可以寫(xiě)一個(gè)例子加深理解。最終實(shí)現(xiàn)一個(gè)現(xiàn)實(shí)header的效果败潦。

源碼如下:

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

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

public class DisplayHeaderServlet extends HttpServlet {
    // 處理 GET 方法請(qǐng)求的方法
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        // 設(shè)置響應(yīng)內(nèi)容類(lèi)型
        response.setContentType("text/html;charset=UTF-8");

        PrintWriter out = response.getWriter();
        String title = "HTTP Header 請(qǐng)求";
        String docType =
                "<!DOCTYPE html> \n";
        out.println(docType +
                "<html>\n" +
                "<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + title + "</h1>\n" +
                "<table width=\"100%\" border=\"1\" align=\"center\">\n" +
                "<tr bgcolor=\"#949494\">\n" +
                "<th>Header 名稱(chēng)</th><th>Header 值</th>\n"+
                "</tr>\n");

        Enumeration headerNames = request.getHeaderNames();

        while(headerNames.hasMoreElements()) {
            String paramName = (String)headerNames.nextElement();
            out.print("<tr><td>" + paramName + "</td>\n");
            String paramValue = request.getHeader(paramName);
            out.println("<td> " + paramValue + "</td></tr>\n");
        }
        out.println("</table>\n</body></html>");
    }
    // 處理 POST 方法請(qǐng)求的方法
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

寫(xiě)完之后本冲,還需要將文件便以為class文件,項(xiàng)目部署到tomcat目錄下劫扒。啟動(dòng)tomcat Web容器訪問(wèn)對(duì)應(yīng)路徑即可檬洞。

在web.xml中配置一下加載的Servlet

    <servlet>
        <!-- servlet名,一般寫(xiě)成類(lèi)名粟关,并不一定嚴(yán)格是類(lèi)名 -->
        <servlet-name>DisplayHeaderServlet</servlet-name>
        <!-- 所在的包 -->
        <servlet-class>com.xxx.xxx.DisplayHeaderServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- 與上面的servlet-name相對(duì)應(yīng)-->
        <servlet-name>DisplayHeaderServlet</servlet-name>
        <!-- 訪問(wèn)的網(wǎng)址 -->
        <url-pattern>/TomcatTest/DisplayHeaderServlet</url-pattern>
    </servlet-mapping>

Servlet需要注意

Servlet訪問(wèn)URL映射配置

由于客戶(hù)端是通過(guò)URL地址訪問(wèn)web服務(wù)器中的資源疮胖,所以Servlet程序若想被外界訪問(wèn),必須把servlet程序映射到一個(gè)URL地址上闷板。

這個(gè)工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成澎灸。<servlet>元素用于注冊(cè)Servlet,它包含有兩個(gè)主要的子元素:<servlet-name><servlet-class>遮晚,分別用于設(shè)置Servlet的注冊(cè)名稱(chēng)和Servlet的完整類(lèi)名性昭。

一個(gè)<servlet-mapping>元素用于映射一個(gè)已注冊(cè)的Servlet的一個(gè)對(duì)外訪問(wèn)路徑,它包含有兩個(gè)子元素:<servlet-name><url-pattern>县遣,分別用于指定Servlet的注冊(cè)名稱(chēng)和Servlet的對(duì)外訪問(wèn)路徑糜颠。

  • 同一個(gè)Servlet可以被映射到多個(gè)URL上,即多個(gè)<servlet-mapping>元素的<servlet-name>子元素的設(shè)置值可以是同一個(gè)Servlet的注冊(cè)名萧求。
  • 同一個(gè)Url不能對(duì)應(yīng)多個(gè)Servlet其兴。否則會(huì)報(bào)錯(cuò)Caused by: java.lang.IllegalArgumentException: The servlets named [xxx] and [xxx] are both mapped to the url-pattern xxx

Servlet訪問(wèn)URL使用*通配符映射

在Servlet映射到的URL中也可以使用*通配符,但是只能有兩種固定的格式:一種格式是"*.擴(kuò)展名"夸政,另一種格式是以正斜杠(/)開(kāi)頭并以"/*"結(jié)尾

但是如果存在了沖突元旬,比如都有*。規(guī)則又是怎樣的呢?

請(qǐng)求Url Url1 Url2 規(guī)則
/abc/a.html /abc/* /* Servlet引擎將調(diào)用/abc/*
/abc /abc/* /abc Servlet引擎將調(diào)用/abc
/abc/a.do /abc/* *.do Servlet引擎將調(diào)用/abc/*
/a.do /* *.do Servlet引擎將調(diào)用/*
/xxx/yyy/a.do /* *.do Servlet引擎將調(diào)用/*

匹配的原則就是"誰(shuí)長(zhǎng)得更像就找誰(shuí)" 匀归。但是當(dāng)請(qǐng)求url完全匹配的時(shí)候就走完全匹配的rul坑资。如上面的第二條。

Servlet與普通Java類(lèi)的區(qū)別

Servlet是一個(gè)供其他Java程序(Servlet引擎穆端,比如tomcat web容器)調(diào)用的Java類(lèi)袱贮,它不能獨(dú)立運(yùn)行,它的運(yùn)行完全由Servlet引擎來(lái)控制和調(diào)度体啰。這也是開(kāi)發(fā)Web項(xiàng)目沒(méi)有些main方法的原因攒巍。

針對(duì)客戶(hù)端的多次Servlet請(qǐng)求,通常情況下狡赐,服務(wù)器只會(huì)創(chuàng)建一個(gè)Servlet實(shí)例對(duì)象窑业,也就是說(shuō)Servlet實(shí)例對(duì)象一旦創(chuàng)建,它就會(huì)駐留在內(nèi)存中枕屉,為后續(xù)的其它請(qǐng)求服務(wù)常柄,直至web容器退出,servlet實(shí)例對(duì)象才會(huì)銷(xiāo)毀搀擂。

在Servlet的整個(gè)生命周期內(nèi)西潘,Servlet的init方法只被調(diào)用一次。而對(duì)一個(gè)Servlet的每次訪問(wèn)請(qǐng)求都導(dǎo)致Servlet引擎調(diào)用一次servlet的service方法哨颂。

對(duì)于每次訪問(wèn)請(qǐng)求喷市,Servlet引擎都會(huì)創(chuàng)建一個(gè)新的HttpServletRequest請(qǐng)求對(duì)象和一個(gè)新的HttpServletResponse響應(yīng)對(duì)象,然后將這兩個(gè)對(duì)象作為參數(shù)傳遞給它調(diào)用的Servlet的service()方法威恼,service方法再根據(jù)請(qǐng)求方式分別調(diào)用doXXX方法品姓。

如果在<servlet>元素中配置了一個(gè)<load-on-startup>元素,那么WEB應(yīng)用程序在啟動(dòng)時(shí)箫措,就會(huì)裝載并創(chuàng)建Servlet的實(shí)例對(duì)象腹备、以及調(diào)用Servlet實(shí)例對(duì)象的init()方法。

    <servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>
            org.apache.catalina.servlets.InvokerServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

可以用于為web應(yīng)用寫(xiě)一個(gè)InitServlet斤蔓,這個(gè)servlet配置為啟動(dòng)時(shí)裝載植酥,為整個(gè)web應(yīng)用創(chuàng)建必要的數(shù)據(jù)庫(kù)表和數(shù)據(jù)。很多第三方框架也需要在應(yīng)用一加載就實(shí)例化Serlvet弦牡,比如SpringMVC中的org.springframework.web.servlet.DispatcherServlet

<!-- springMVC的核心控制器 -->
<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:springMVC-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

缺省Servlet

如果某個(gè)Servlet的映射路徑僅僅為一個(gè)正斜杠(/)友驮,那么這個(gè)Servlet就成為當(dāng)前Web應(yīng)用程序的缺省Servlet。

凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL驾锰,它們的訪問(wèn)請(qǐng)求都將交給缺省Servlet處理卸留,也就是說(shuō),缺省Servlet用于處理所有其他Servlet都不處理的訪問(wèn)請(qǐng)求椭豫。

比如在tomcat中\(zhòng)conf\web.xml文件中耻瑟,注冊(cè)了一個(gè)名稱(chēng)為org.apache.catalina.servlets.DefaultServlet的Servlet买喧,并將這個(gè)Servlet設(shè)置為了缺省Servlet。

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

 <!-- The mapping for the default servlet -->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

當(dāng)訪問(wèn)Tomcat服務(wù)器中的某個(gè)靜態(tài)HTML文件和圖片時(shí)匆赃,實(shí)際上是在訪問(wèn)這個(gè)缺省Servlet。

Servlet的線(xiàn)程安全問(wèn)題

當(dāng)多個(gè)客戶(hù)端并發(fā)訪問(wèn)同一個(gè)Servlet時(shí)今缚,web服務(wù)器會(huì)為每一個(gè)客戶(hù)端的訪問(wèn)請(qǐng)求創(chuàng)建一個(gè)線(xiàn)程算柳,并在這個(gè)線(xiàn)程上調(diào)用Servlet的service方法,因此service方法內(nèi)如果訪問(wèn)了同一個(gè)資源的話(huà)姓言,就有可能引發(fā)線(xiàn)程安全問(wèn)題瞬项。

所有在Servlet中盡量避免使用實(shí)例變量 ,最好使用局部變量何荚。

Servlet如何處理多個(gè)請(qǐng)求訪問(wèn)

Servlet容器默認(rèn)是采用單實(shí)例多線(xiàn)程的方式處理多個(gè)請(qǐng)求的:

  • 當(dāng)web服務(wù)器啟動(dòng)的時(shí)候(或客戶(hù)端發(fā)送請(qǐng)求到服務(wù)器時(shí))囱淋,Servlet就被加載并實(shí)例化(只存在一個(gè)Servlet實(shí)例)
  • 容器初始化化Servlet主要就是讀取配置文件(例如tomcat,可以通過(guò)servlet.xml的<Connector>設(shè)置線(xiàn)程池中線(xiàn)程數(shù)目,初始化線(xiàn)程池通過(guò)web.xml,初始化每個(gè)參數(shù)值等等餐塘。
  • 當(dāng)請(qǐng)求到達(dá)時(shí)妥衣,Servlet容器通過(guò)調(diào)度線(xiàn)程(Dispatchaer Thread) 調(diào)度它管理下線(xiàn)程池中等待執(zhí)行的線(xiàn)程(Worker Thread)給請(qǐng)求者。
  • 線(xiàn)程執(zhí)行Servlet的service方法戒傻。
  • 請(qǐng)求結(jié)束税手,放回線(xiàn)程池,等待被調(diào)用需纳;

從上面可以看出(好處):

  1. Servlet單實(shí)例芦倒,減少了產(chǎn)生servlet的開(kāi)銷(xiāo);
  2. 通過(guò)線(xiàn)程池來(lái)響應(yīng)多個(gè)請(qǐng)求不翩,提高了請(qǐng)求的響應(yīng)時(shí)間兵扬;
  3. Servlet容器并不關(guān)心到達(dá)的Servlet請(qǐng)求訪問(wèn)的是否是同一個(gè)Servlet還是另一個(gè)Servlet,直接分配給它一個(gè)新的線(xiàn)程口蝠。
  4. 如果是同一個(gè)Servlet的多個(gè)請(qǐng)求器钟,那么Servlet的service方法將在多線(xiàn)程中并發(fā)的執(zhí)行;
  5. 每一個(gè)請(qǐng)求由ServletRequest對(duì)象來(lái)接受請(qǐng)求亚皂,由ServletResponse對(duì)象來(lái)響應(yīng)該請(qǐng)求俱箱;

Servlet相關(guān)對(duì)象

ServletConfig

上面講了可以設(shè)置Servlet對(duì)應(yīng)的url,那么如何需要配置Serlvet初始化參數(shù)怎么辦,這就需要用到ServletConfig灭必。在Servlet的配置文件web.xml中狞谱,可以使用一個(gè)或多個(gè)<init-param>標(biāo)簽為servlet配置一些初始化參數(shù)。

<servlet>
    <servlet-name>ServletConfigDemo1</servlet-name>
    <servlet-class>com.xxx.xxx.xxx</servlet-class>
    <!--配置ServletConfig的初始化參數(shù) -->
    <init-param>
        <param-name>name</param-name>
        <param-value>xxx</param-value>
    </init-param>
     <init-param>
        <param-name>password</param-name>
        <param-value>123</param-value>
    </init-param>
    <init-param>
        <param-name>charset</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</servlet>

當(dāng)servlet配置了初始化參數(shù)后禁漓,web容器在創(chuàng)建servlet實(shí)例對(duì)象時(shí)跟衅,會(huì)自動(dòng)將這些初始化參數(shù)封裝到ServletConfig對(duì)象中,并在調(diào)用servlet的init方法時(shí)播歼,將ServletConfig對(duì)象傳遞給servlet伶跷。進(jìn)而掰读,我們通過(guò)ServletConfig對(duì)象就可以得到當(dāng)前servlet的初始化參數(shù)信息。

獲取方式如下:

    /**
     * 定義ServletConfig對(duì)象來(lái)接收配置的初始化參數(shù)
     */
    private ServletConfig config;
    
    /**
     * 當(dāng)servlet配置了初始化參數(shù)后叭莫,web容器在創(chuàng)建servlet實(shí)例對(duì)象時(shí)蹈集,
     * 會(huì)自動(dòng)將這些初始化參數(shù)封裝到ServletConfig對(duì)象中,并在調(diào)用servlet的init方法時(shí)雇初,
     * 將ServletConfig對(duì)象傳遞給servlet拢肆。進(jìn)而,程序員通過(guò)ServletConfig對(duì)象就可以
     * 得到當(dāng)前servlet的初始化參數(shù)信息靖诗。
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //獲取在web.xml中配置的初始化參數(shù)
        //獲取指定的初始化參數(shù)
        String paramVal = this.config.getInitParameter("name");
        response.getWriter().print(paramVal);
        
        response.getWriter().print("<hr/>");
        //獲取所有的初始化參數(shù)
        Enumeration<String> e = config.getInitParameterNames();
        while(e.hasMoreElements()){
            String name = e.nextElement();
            String value = config.getInitParameter(name);
            response.getWriter().print(name + "=" + value + "<br/>");
        }
    }

比如在使用SpringMVC的時(shí)候郭怪,在web.xml就使用到了ServletConfig

    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--配置ServletConfig的初始化參數(shù) -->
        <init-param>
            <description>SpringMVC</description>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-mvc.xml</param-value>
        </init-param>
        <!--web容器一旦加載就會(huì)創(chuàng)建這個(gè)servlet,并且會(huì)調(diào)用init方法-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

ServletContext

對(duì)于ServletContext需要我們注意一下幾點(diǎn):

  • WEB容器在啟動(dòng)時(shí)刊橘,它會(huì)為每個(gè)WEB應(yīng)用程序都創(chuàng)建一個(gè)對(duì)應(yīng)的ServletContext對(duì)象鄙才,它代表當(dāng)前web應(yīng)用。
  • ServletConfig對(duì)象中維護(hù)了ServletContext對(duì)象的引用促绵,開(kāi)發(fā)人員在編寫(xiě)servlet時(shí)攒庵,可以通過(guò)ServletConfig.getServletContext方法獲得ServletContext對(duì)象。
  • 由于一個(gè)WEB應(yīng)用中的所有Servlet共享同一個(gè)ServletContext對(duì)象绞愚,因此Servlet對(duì)象之間可以通過(guò)ServletContext對(duì)象來(lái)實(shí)現(xiàn)通訊叙甸。ServletContext對(duì)象通常也被稱(chēng)之為context域?qū)ο蟆?/li>

類(lèi)似于ServletContext(應(yīng)用上下文)這種設(shè)計(jì)思想,很多地方都有類(lèi)似的應(yīng)用位衩。比如iOS中的畫(huà)圖CGContext 裆蒸。

來(lái)一個(gè)數(shù)據(jù)共享的例子:

存儲(chǔ)數(shù)據(jù):

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String data = "data";
        /**
         * ServletConfig對(duì)象中維護(hù)了ServletContext對(duì)象的引用,開(kāi)發(fā)人員在編寫(xiě)servlet時(shí)糖驴,
         * 可以通過(guò)ServletConfig.getServletContext方法獲得ServletContext對(duì)象僚祷。
         */
         //獲得ServletContext對(duì)象
        ServletContext context = this.getServletConfig().getServletContext();
         //將data存儲(chǔ)到ServletContext對(duì)象中
         //將data存儲(chǔ)到ServletContext對(duì)象中
        context.setAttribute("data", data);  
    }

讀取數(shù)據(jù):

 public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext context = this.getServletContext();\
        //從ServletContext對(duì)象中取出數(shù)據(jù)
        String data = (String) context.getAttribute("data");
        response.getWriter().print("data="+data);
    }

更多的情況下是通過(guò)web.xml中讀取初始化參數(shù)。如下:

    <!-- 配置WEB應(yīng)用的初始化參數(shù) -->
    <context-param>
        <param-name>url</param-name>
        <param-value>xxx.xxx.xxxx</param-value>
    </context-param>

讀取web.xml中的初始化參數(shù)

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        ServletContext context = this.getServletContext();
        //獲取整個(gè)web站點(diǎn)的初始化參數(shù)
        String contextInitParam = context.getInitParameter("url");
        response.getWriter().print(contextInitParam);
    }

除了讀取web.xml中的初始化參數(shù)贮缕,還可以通過(guò)ServletContext讀取對(duì)象文件辙谜。比如常見(jiàn)在項(xiàng)目中使用的xxx.properties文件。很多第三方也是用的這種方式來(lái)讀取對(duì)應(yīng)的配置文件

 /**
     * 讀取src目錄下的com.xxx.xxx包中的xxx.properties配置文件
     * @param response
     * @throws IOException
     */
    private void readPropCfgFile2(HttpServletResponse response)
            throws IOException {
        InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/xxx/xxx/xxx.properties");
        Properties prop = new Properties();
        prop.load(in);
        String driver = prop.getProperty("driver");
        String url = prop.getProperty("url");
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        response.getWriter().println("讀取src目錄下的com.xxx.xxx包中的xxx.properties配置文件:");
        response.getWriter().println(
                MessageFormat.format(
                        "driver={0},url={1},username={2},password={3}", 
                        driver,url, username, password));
    }

除了通過(guò)ServletContext讀取資源文件感昼,還可以通過(guò)類(lèi)裝載器讀取資源文件装哆。也有很多第三方是通過(guò)這樣的方式讀取資源文件

   /**
     * 讀取類(lèi)路徑下的資源文件
     * @param response
     * @throws IOException
     */
    private void test1(HttpServletResponse response) throws IOException {
        //獲取到裝載當(dāng)前類(lèi)的類(lèi)裝載器
        ClassLoader loader = ServletContextDemo7.class.getClassLoader();
        //用類(lèi)裝載器讀取src目錄下的db1.properties配置文件
        InputStream in = loader.getResourceAsStream("db1.properties");
        Properties prop = new Properties();
        prop.load(in);
        String driver = prop.getProperty("driver");
        String url = prop.getProperty("url");
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        response.getWriter().println("用類(lèi)裝載器讀取src目錄下的db1.properties配置文件:");
        response.getWriter().println(
                MessageFormat.format(
                        "driver={0},url={1},username={2},password={3}", 
                        driver,url, username, password));
    }

Web容器

上一篇講了Servlet,提到Servlet由容器調(diào)用定嗓。拿么Web容器是干嘛的呢蜕琴。

比較權(quán)威的解釋?zhuān)?/p>

web容器是一種服務(wù)程序,在服務(wù)器一個(gè)端口就有一個(gè)提供相應(yīng)服務(wù)的程序宵溅,而這個(gè)程序就是處理從客戶(hù)端發(fā)出的請(qǐng)求凌简,如JAVA中的Tomcat容器,ASP的IIS或PWS都是這樣的容器恃逻。比如tomcat容器雏搂,它提供的接口嚴(yán)格遵守 J2EE 規(guī)范中的 WEB APPLICATION 標(biāo)準(zhǔn)藕施。我們把遵守該標(biāo)準(zhǔn)的 WEB 服務(wù)器就叫做 J2EE 中的 WEB 容器。 這套標(biāo)準(zhǔn)就是當(dāng)有客戶(hù)端請(qǐng)求凸郑,自動(dòng)調(diào)用對(duì)應(yīng)的Servlet的標(biāo)準(zhǔn)

為了加強(qiáng)理解這里再次說(shuō)明一下:

servlet沒(méi)有main方法裳食,那我們?nèi)绾螁?dòng)一個(gè)servlet,如何結(jié)束一個(gè)servlet芙沥,如何尋找一個(gè)servlet等等胞谈,都受控于另一個(gè)java應(yīng)用,這個(gè)應(yīng)用我們就稱(chēng)之為web容器憨愉。

比如tomcat就是這樣一個(gè)容器。如果web服務(wù)器應(yīng)用得到一個(gè)指向某個(gè)servlet的請(qǐng)求卿捎,此時(shí)服務(wù)器不是把servlet交給servlet本身配紫,而是交給部署該servlet的容器。要有容器向servlet提供http請(qǐng)求和響應(yīng)午阵,而且要由容器調(diào)用servlet的方法躺孝,如doPost或者doGet。

接下來(lái)就以Tomcat為例子

Tomcat

Tomcat是Apache 軟件基金會(huì)(Apache Software Foundation)的Jakarta 項(xiàng)目中的一個(gè)核心項(xiàng)目底桂,由Apache植袍、Sun 和其他一些公司及個(gè)人共同開(kāi)發(fā)而成。由于有了Sun 的參與和支持籽懦,最新的Servlet 和JSP 規(guī)范總是能在Tomcat 中得到體現(xiàn)于个,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 規(guī)范。因?yàn)門(mén)omcat 技術(shù)先進(jìn)暮顺、性能穩(wěn)定厅篓,而且免費(fèi),因而深受Java 愛(ài)好者的喜愛(ài)并得到了部分軟件開(kāi)發(fā)商的認(rèn)可捶码,成為目前比較流行的Web 應(yīng)用服務(wù)器羽氮。

體系結(jié)構(gòu)

  • Tomcat服務(wù)器的啟動(dòng)是基于一個(gè)server.xml文件的,Tomcat啟動(dòng)的時(shí)候首先會(huì)啟動(dòng)一個(gè)Server惫恼,Server里面就會(huì)啟動(dòng)Service档押,Service里面就會(huì)啟動(dòng)多個(gè)Connector(連接器)。
  • 每一個(gè)Connector(連接器)都在等待客戶(hù)機(jī)的連接祈纯,當(dāng)有用戶(hù)使用瀏覽器去訪問(wèn)服務(wù)器上面的web資源時(shí)令宿,首先是連接到Connector(連接器),Connector(連接器)是不處理用戶(hù)的請(qǐng)求的盆繁,而是將用戶(hù)的請(qǐng)求交給一個(gè)Engine(引擎)去處理掀淘。
  • Engine(引擎)接收到請(qǐng)求后就會(huì)解析用戶(hù)想要訪問(wèn)的Host,然后將請(qǐng)求交給相應(yīng)的Host油昂。
  • Host收到請(qǐng)求后就會(huì)解析出用戶(hù)想要訪問(wèn)這個(gè)Host下面的哪一個(gè)Web應(yīng)用,一個(gè)web應(yīng)用對(duì)應(yīng)一個(gè)Context革娄。

一個(gè)簡(jiǎn)單的配置例子倾贰,對(duì)照著上面的體系結(jié)構(gòu)來(lái)看

<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="conf/.keystore" keystorePass="123456"/>
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      <!-- host對(duì)應(yīng)的根目錄 --> 
      <Host name="www.xxx.xxx" appBase="F:\JavaWebApps">
        <!-- 具體context對(duì)應(yīng)的目錄 --> 
        <Context path="" docBase="F:\JavaWebApps\xxxx"/>
      </Host>

    </Engine>
  </Service>
</Server>

Tomcat web.xml

應(yīng)用服務(wù)器啟動(dòng)時(shí)web.xml加載過(guò)程,至于這些節(jié)點(diǎn)在xml文件中的前后順序沒(méi)有關(guān)系拦惋,不過(guò)有些應(yīng)用服務(wù)器,比如websphere就嚴(yán)格要求web.xml的節(jié)點(diǎn)順序,否則部署不成功匆浙,所以還是最好按照web.xml標(biāo)準(zhǔn)格式寫(xiě) :

具體的配置和加載順序:content-param --> listener --> filter --> servlet

結(jié)合上面所講的ServletConfig及ServletContext。

  1. 啟動(dòng)WEB項(xiàng)目的時(shí)候,應(yīng)用服務(wù)器會(huì)去讀它的配置文件web.xml.讀兩個(gè)節(jié)點(diǎn):<context-param></context-param><listener></listener>
  2. 緊接著,容器創(chuàng)建一個(gè)ServletContext(上下文),這個(gè)WEB項(xiàng)目所有部分都將共享這個(gè)上下文厕妖。
  3. 容器將<context-param></context-param>轉(zhuǎn)化為鍵值對(duì),并交給ServletContext首尼。
  4. 容器創(chuàng)建<listener></listener>中的類(lèi)實(shí)例,即創(chuàng)建監(jiān)聽(tīng)。
  5. 在監(jiān)聽(tīng)中會(huì)有contextInitialized(ServletContextEvent args)初始化方法,在這個(gè)方法中獲得:ServletContext = ServletContextEvent.getServletContext(); context-param的值 = ServletContext.getInitParameter("context-param的鍵");
  6. 得到這個(gè)context-param的值之后,你就可以做一些操作了.注意,這個(gè)時(shí)候你的WEB項(xiàng)目還沒(méi)有完全啟動(dòng)完成言秸,這個(gè)動(dòng)作會(huì)比所有的Servlet都要早软能。換句話(huà)說(shuō),這個(gè)時(shí)候,你對(duì)<context-param>中的鍵值做的操作,將在你的WEB項(xiàng)目完全啟動(dòng)之前被執(zhí)行.如果想在項(xiàng)目啟動(dòng)之前就打開(kāi)數(shù)據(jù)庫(kù),那么這里就可以在<context-param>中設(shè)置數(shù)據(jù)庫(kù)的連接方式,在監(jiān)聽(tīng)類(lèi)中初始化數(shù)據(jù)庫(kù)的連接,這個(gè)監(jiān)聽(tīng)是自己寫(xiě)的一個(gè)類(lèi),除了初始化方法,它還有銷(xiāo)毀方法.用于關(guān)閉應(yīng)用前釋放資源.比如說(shuō)數(shù)據(jù)庫(kù)連接的關(guān)閉。

順序

以 filter 為例举畸,web.xml 中當(dāng)然可以定義多個(gè) filter查排,與 filter 相關(guān)的一個(gè)配置節(jié)是 filter-mapping,這里一定要注意抄沮,對(duì)于擁有相同 filter-name 的 filter 和 filter-mapping 配置節(jié)而言跋核,filter-mapping 必須出現(xiàn)在 filter 之后,否則當(dāng)解析到 filter-mapping 時(shí)叛买,它所對(duì)應(yīng)的 filter-name 還未定義砂代。

web 容器啟動(dòng)時(shí)初始化每個(gè) filter 時(shí),是按照 filter 配置節(jié)出現(xiàn)的順序來(lái)初始化的率挣,當(dāng)請(qǐng)求資源匹配多個(gè) filter-mapping 時(shí)刻伊,filter 攔截資源是按照 filter-mapping 配置節(jié)出現(xiàn)的順序來(lái)依次調(diào)用 doFilter() 方法的。 servlet 同 filter 類(lèi)似椒功!

比如filter 需要用到 bean 娃圆,但加載順序是: 先加載filter 后加載spring,則filter中初始化操作中的bean為null蛾茉;所以讼呢,如果過(guò)濾器中要使用到 bean,可以將spring 的加載 改成 Listener的方式

<listener>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

節(jié)點(diǎn)詳解

web-app

根節(jié)點(diǎn)

<web-app></web-app>

context-param

用來(lái)設(shè)定web站臺(tái)的環(huán)境參數(shù)谦炬。

它包含兩個(gè)子元素:

  • <param-name></param-name> 用來(lái)指定參數(shù)的名稱(chēng)
  • <param-value></param-value> 用來(lái)設(shè)定參數(shù)值

在此設(shè)定的參數(shù)悦屏,可以在servlet中用 getServletContext().getInitParameter("my_param")來(lái)取得。

例子:

 <context-param>

  <param-name>log4jConfigLocation</param-name>

  <param-value>classpath*:/log4j.properties</param-value>

 </context-param>

listener

用來(lái)設(shè)定Listener接口键思,它的主要子元素為:

  • <listener-class></listener-class> 定義Listener的類(lèi)名稱(chēng)

例子:

<listener>

     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

 </listener>

filter

是用來(lái)聲明filter的相關(guān)設(shè)定

  • <filter-name></filter-name> 這當(dāng)然就是指定filter的名字
  • <filter-class></filter-class> 這是用來(lái)定義filter的類(lèi)的名稱(chēng)
  • <init-param></init-param> 用來(lái)定義參數(shù)础爬,它有兩個(gè)子元素:
  • <param-name></param-name> 用來(lái)指定參數(shù)的名稱(chēng)
  • <param-value></param-value> 用來(lái)設(shè)定參數(shù)值

例子:

<filter>

  <filter-name>encodingFilter</filter-name>

  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

  <init-param>

   <param-name>encoding</param-name>

   <param-value>GBK</param-value>

  </init-param>

  <init-param>

   <param-name>forceEncoding</param-name>

   <param-value>true</param-value>

  </init-param>

 </filter>

servlet

來(lái)聲明一個(gè)servlet的數(shù)據(jù),主要有以下子元素:

  • <servlet-name></servlet-name> 指定servlet的名稱(chēng)
  • <servlet-class></servlet-class> 指定servlet的類(lèi)名稱(chēng)
  • <jsp-file></jsp-file> 指定web站臺(tái)中的某個(gè)JSP網(wǎng)頁(yè)的完整路徑
  • <init-param></init-param> 用來(lái)定義參數(shù),和前面的<init-param>差不多

同樣,與<servlet></servlet>一起使用的是<servlet-mapping></servlet-mapping> 用來(lái)定義servlet所對(duì)應(yīng)的URL酝枢,包含兩個(gè)子元素:<servlet-name></servlet-name> 指定servlet的名稱(chēng)<url-pattern></url-pattern> 指定servlet所對(duì)應(yīng)的URL

 <servlet>

  <servlet-name>DemoServlet</servlet-name>

  <servlet-class>com.test.DemoServlet</servlet-class>

 </servlet>

 <servlet-mapping>

  <servlet-name>DemoServlet</servlet-name>

  <url-pattern>/demoServlet</url-pattern>

 </servlet-mapping>

description

是對(duì)站臺(tái)的描述

例子:

<description>傳道、授業(yè)供炎、解惑</description> 

display-name

定義站臺(tái)的名稱(chēng)
例子:

<display-name>我的站點(diǎn)</display-name>

icon

icon元素包含small-icon和large-icon兩個(gè)子元素.用來(lái)指定web站臺(tái)中小圖標(biāo)和大圖標(biāo)的路徑.
<small-icon>/路徑/smallicon.gif</small-icon>

small-icon元素應(yīng)指向web站臺(tái)中某個(gè)小圖標(biāo)的路徑,大小為16 X 16 pixel,但是圖象文件必須為GIF或JPEG格式,擴(kuò)展名必須為:.gif或.jpg.

<large-icon>/路徑/largeicon-jpg</large-icon>
large-icon元素應(yīng)指向web站臺(tái)中某個(gè)大圖表路徑,大小為32 X 32 pixel,但是圖象文件必須為GIF或JPEG的格式,擴(kuò)展名必須為; gif或jpg.
例子:

<icon> 

 <small-icon>/images/small.gif</small-icon> 

 <large-icon>/images/large.gir</large-icon> 

</icon>

distributable

是指定該站臺(tái)是否可分布式處理

session-config

用來(lái)定義web站臺(tái)中的session參數(shù)

包含一個(gè)子元素:
<session-timeout></session-timeout> 用來(lái)定義這個(gè)web站臺(tái)所有session的有效期限渴逻,單位為 分鐘

mime-mapping

定義某一個(gè)擴(kuò)展名和某一個(gè)MIME Type做對(duì)應(yīng)該
包含兩個(gè)子元素:

  • <extension></extension> 擴(kuò)展名的名稱(chēng)
  • <mime-type></mime-type> MIME格式

例子:

 <mime-mapping>

  <extension>doc</extension>  

  <mime-type>application/vnd.ms-word</mime-type>

 </mime-mapping>    

 <mime-mapping>

  <extension>xls</extension>

  <mime-type>application/vnd.ms-excel</mime-type>

 </mime-mapping>

error-page

例子

<error-page> <error-page>

     <error-code>500</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>400</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>403</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>404</error-code>

     <location>/message.jsp</location>

 </error-page>

 <error-page>

     <error-code>502</error-code>

     <location>/index.jsp</location>

 </error-page>

jsp-config

例子

<jsp-config> 

 <taglib>

 <taglib-uri>/struts-tags</taglib-uri>

 <taglib-location>/WEB-INF/struts-tags.tld</taglib-location>

 </taglib>

 <taglib>

 <taglib-uri>/struts-dojo-tags</taglib-uri>

 <taglib-location>/WEB-INF/struts-dojo-tags.tld</taglib-location>

 </taglib>

 <taglib>

 <taglib-uri>/s</taglib-uri>

 <taglib-location>/WEB-INF/struts-tags.tld</taglib-location>

 </taglib>

 </jsp-config>

welcome-file-list

 <welcome-file-list>

 <welcome-file>index.html</welcome-file>

 <welcome-file>index.htm</welcome-file>

 <welcome-file>index.jsp</welcome-file>

 </welcome-file-list>

resource-ref

定義利用JNDI取得站臺(tái)可利用的資源
有五個(gè)子元素:

  • <description></description> 資源說(shuō)明
  • <rec-ref-name></rec-ref-name> 資源名稱(chēng)
  • <res-type></res-type> 資源種類(lèi)
  • <res-auth></res-auth> 資源經(jīng)由Application或Container來(lái)許可
  • <res-sharing-scope></res-sharing-scope> 資源是否可以共享,有Shareable和Unshareable兩個(gè)值音诫,默認(rèn)為Shareable

比如惨奕,配置數(shù)據(jù)庫(kù)連接池就可在此配置

 <resource-ref>

 <description>JNDI JDBC DataSource of shop</description>

 <res-ref-name>jdbc/sample_db</res-ref-name>

 <res-type>javax.sql.DataSource</res-type>

 <res-auth>Container</res-auth>

 </resource-ref>

擴(kuò)展閱讀

Tomcat服務(wù)器學(xué)習(xí)和使用(一)

JavaWeb學(xué)習(xí)總結(jié)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市竭钝,隨后出現(xiàn)的幾起案子梨撞,更是在濱河造成了極大的恐慌,老刑警劉巖香罐,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卧波,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡庇茫,警方通過(guò)查閱死者的電腦和手機(jī)幽勒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)港令,“玉大人,你說(shuō)我怎么就攤上這事锈颗∏昱” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵击吱,是天一觀的道長(zhǎng)淋淀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)覆醇,這世上最難降的妖魔是什么朵纷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮永脓,結(jié)果婚禮上袍辞,老公的妹妹穿的比我還像新娘。我一直安慰自己常摧,他們只是感情好搅吁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著落午,像睡著了一般谎懦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上溃斋,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天界拦,我揣著相機(jī)與錄音,去河邊找鬼梗劫。 笑死享甸,一個(gè)胖子當(dāng)著我的面吹牛截碴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播枪萄,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼隐岛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瓷翻?” 一聲冷哼從身側(cè)響起聚凹,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎齐帚,沒(méi)想到半個(gè)月后妒牙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡对妄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年湘今,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剪菱。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摩瞎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出孝常,到底是詐尸還是另有隱情旗们,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布构灸,位于F島的核電站上渴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏喜颁。R本人自食惡果不足惜稠氮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望半开。 院中可真熱鬧隔披,春花似錦、人聲如沸寂拆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漓库。三九已至恃慧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渺蒿,已是汗流浹背痢士。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怠蹂。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓善延,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親城侧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子易遣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司嫌佑,掛了不少豆茫,但最終還是拿到小米、百度屋摇、阿里揩魂、京東、新浪炮温、CVTE火脉、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,253評(píng)論 11 349
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,409評(píng)論 1 92
  • 在學(xué)習(xí)Servlet是找到一篇不錯(cuò)的文章,轉(zhuǎn)載一下柒啤。學(xué)習(xí)心得,Servlet其實(shí)只是個(gè)接口,相當(dāng)于是定義了一個(gè)標(biāo)準(zhǔn)...
    君子若蓮閱讀 1,204評(píng)論 1 16
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法倦挂,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法担巩,繼承相關(guān)的語(yǔ)法方援,異常的語(yǔ)法,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,639評(píng)論 18 399
  • 兵睛,,窥浪,
    一塊瘦司閱讀 122評(píng)論 0 0