讓我們先來(lái)簡(jiǎn)單回顧一下 Web 技術(shù)的發(fā)展歷史,可以幫助你理解 Web 容器的由來(lái)。
早期的 Web 應用主要用于瀏覽新聞等靜態(tài)頁(yè)面,HTTP 服務(wù)器(比如 Apache、Nginx)向瀏覽器返回靜態(tài) HTML,瀏覽器負責解析 HTML,將結果呈現給用戶(hù)。
隨著(zhù)互聯(lián)網(wǎng)的發(fā)展,我們已經(jīng)不滿(mǎn)足于僅僅瀏覽靜態(tài)頁(yè)面,還希望通過(guò)一些交互操作,來(lái)獲取動(dòng)態(tài)結果,因此也就需要一些擴展機制能夠讓 HTTP 服務(wù)器調用服務(wù)端程序。
于是 Sun 公司推出了 Servlet 技術(shù)。你可以把 Servlet 簡(jiǎn)單理解為運行在服務(wù)端的 Java 小程序,但是 Servlet 沒(méi)有 main 方法,不能獨立運行,因此必須把它部署到 Servlet 容器中,由容器來(lái)實(shí)例化并調用 Servlet。
而 Tomcat 就是一個(gè) Servlet 容器。為了方便使用,它們也具有 HTTP 服務(wù)器的功能,因此 Tomcat 就是一個(gè)“HTTP 服務(wù)器 + Servlet 容器”,我們也叫它們 Web 容器。
HTTP 協(xié)議是瀏覽器與服務(wù)器之間的數據傳送協(xié)議。作為應用層協(xié)議,HTTP 是基于 TCP/IP 協(xié)議來(lái)傳遞數據的(HTML 文件、圖片、查詢(xún)結果等),HTTP 協(xié)議不涉及數據包(Packet)傳輸,主要規定了客戶(hù)端和服務(wù)器之間的通信格式。
假如瀏覽器需要從遠程 HTTP 服務(wù)器獲取一個(gè) HTML 文本,在這個(gè)過(guò)程中,瀏覽器實(shí)際上要做兩件事情。
用戶(hù)在登陸頁(yè)面輸入用戶(hù)名和密碼,點(diǎn)擊登陸后,瀏覽器發(fā)出了這樣的 HTTP 請求:
HTTP 請求數據由三部分組成,分別是請求行、請求報頭、請求正文。當這個(gè) HTTP 請求數據到達 Tomcat 后,Tomcat 會(huì )把 HTTP 請求數據字節流解析成一個(gè) Request 對象,這個(gè) Request 對象封裝了 HTTP 所有的請求信息。接著(zhù) Tomcat 把這個(gè) Request 對象交給 Web 應用去處理,處理完后得到一個(gè) Response 對象,Tomcat 會(huì )把這個(gè) Response 對象轉成 HTTP 格式的響應數據并發(fā)送給瀏覽器。
HTTP 的響應也是由三部分組成,分別是狀態(tài)行、響應報頭、報文主體。同樣,我還以極客時(shí)間登陸請求的響應為例。
我們知道,HTTP 協(xié)議有個(gè)特點(diǎn)是無(wú)狀態(tài),請求與請求之間是沒(méi)有關(guān)系的。這樣會(huì )出現一個(gè)很尷尬的問(wèn)題:Web 應用不知道你是誰(shuí)。因此 HTTP 協(xié)議需要一種技術(shù)讓請求與請求之間建立起聯(lián)系,并且服務(wù)器需要知道這個(gè)請求來(lái)自哪個(gè)用戶(hù),于是 Cookie 技術(shù)出現了。
Cookie 是 HTTP 報文的一個(gè)請求頭,Web 應用可以將用戶(hù)的標識信息或者其他一些信息(用戶(hù)名等)存儲在 Cookie 中。用戶(hù)經(jīng)過(guò)驗證之后,每次 HTTP 請求報文中都包含 Cookie,這樣服務(wù)器讀取這個(gè) Cookie 請求頭就知道用戶(hù)是誰(shuí)了。Cookie 本質(zhì)上就是一份存儲在用戶(hù)本地的文件,里面包含了每次請求中都需要傳遞的信息。
由于 Cookie 以明文的方式存儲在本地,而 Cookie 中往往帶有用戶(hù)信息,這樣就造成了非常大的安全隱患。而 Session 的出現解決了這個(gè)問(wèn)題,Session 可以理解為服務(wù)器端開(kāi)辟的存儲空間,里面保存了用戶(hù)的狀態(tài),用戶(hù)信息以 Session 的形式存儲在服務(wù)端。當用戶(hù)請求到來(lái)時(shí),服務(wù)端可以把用戶(hù)的請求和用戶(hù)的 Session 對應起來(lái)。那么 Session 是怎么和請求對應起來(lái)的呢?答案是通過(guò) Cookie,瀏覽器在 Cookie 中填充了一個(gè) Session ID 之類(lèi)的字段用來(lái)標識請求。
具體工作過(guò)程是這樣的:服務(wù)器在創(chuàng )建 Session 的同時(shí),會(huì )為該 Session 生成唯一的 Session ID,當瀏覽器再次發(fā)送請求的時(shí)候,會(huì )將這個(gè) Session ID 帶上,服務(wù)器接受到請求之后就會(huì )依據 Session ID 找到相應的 Session,找到 Session 后,就可以在 Session 中獲取或者添加內容了。而這些內容只會(huì )保存在服務(wù)器中,發(fā)到客戶(hù)端的只有 Session ID,這樣相對安全,也節省了網(wǎng)絡(luò )流量,因為不需要在 Cookie 中存儲大量用戶(hù)信息。
那么 Session 在何時(shí)何地創(chuàng )建呢?當然還是在服務(wù)器端程序運行的過(guò)程中創(chuàng )建的,不同語(yǔ)言實(shí)現的應用程序有不同的創(chuàng )建 Session 的方法。在 Java 中,是 Web 應用程序在調用 HttpServletRequest 的 getSession 方法時(shí),由 Web 容器(比如 Tomcat)創(chuàng )建的。
Tomcat 的 Session 管理器提供了多種持久化方案來(lái)存儲 Session,通常會(huì )采用高性能的存儲方式,比如 Redis,并且通過(guò)集群部署的方式,防止單點(diǎn)故障,從而提升高可用。同時(shí),Session 有過(guò)期時(shí)間,因此 Tomcat 會(huì )開(kāi)啟后臺線(xiàn)程定期的輪詢(xún),如果 Session 過(guò)期了就將 Session 失效。
HTTP 服務(wù)器怎么知道要調用哪個(gè) Java 類(lèi)的哪個(gè)方法呢。最直接的做法是在 HTTP 服務(wù)器代碼里寫(xiě)一大堆 if else 邏輯判斷:如果是 A 請求就調 X 類(lèi)的 M1 方法,如果是 B 請求就調 Y 類(lèi)的 M2 方法。但這樣做明顯有問(wèn)題,因為 HTTP 服務(wù)器的代碼跟業(yè)務(wù)邏輯耦合在一起了,如果新加一個(gè)業(yè)務(wù)方法還要改 HTTP 服務(wù)器的代碼。
那該怎么解決這個(gè)問(wèn)題呢?我們知道,面向接口編程是解決耦合問(wèn)題的法寶,于是有一伙人就定義了一個(gè)接口,各種業(yè)務(wù)類(lèi)都必須實(shí)現這個(gè)接口,這個(gè)接口就叫 Servlet 接口,有時(shí)我們也把實(shí)現了 Servlet 接口的業(yè)務(wù)類(lèi)叫作 Servlet。
但是這里還有一個(gè)問(wèn)題,對于特定的請求,HTTP 服務(wù)器如何知道由哪個(gè) Servlet 來(lái)處理呢?Servlet 又是由誰(shuí)來(lái)實(shí)例化呢?顯然 HTTP 服務(wù)器不適合做這個(gè)工作,否則又和業(yè)務(wù)類(lèi)耦合了。
于是,還是那伙人又發(fā)明了 Servlet 容器,Servlet 容器用來(lái)加載和管理業(yè)務(wù)類(lèi)。HTTP 服務(wù)器不直接跟業(yè)務(wù)類(lèi)打交道,而是把請求交給 Servlet 容器去處理,Servlet 容器會(huì )將請求轉發(fā)到具體的 Servlet,如果這個(gè) Servlet 還沒(méi)創(chuàng )建,就加載并實(shí)例化這個(gè) Servlet,然后調用這個(gè) Servlet 的接口方法。因此 Servlet 接口其實(shí)是 Servlet 容器跟具體業(yè)務(wù)類(lèi)之間的接口。下面我們通過(guò)一張圖來(lái)加深理解。
Servlet 接口和 Servlet 容器這一整套規范叫作 Servlet 規范。Tomcat 和 Jetty 都按照 Servlet 規范的要求實(shí)現了 Servlet 容器,同時(shí)它們也具有 HTTP 服務(wù)器的功能。作為 Java 程序員,如果我們要實(shí)現新的業(yè)務(wù)功能,只需要實(shí)現一個(gè) Servlet,并把它注冊到 Tomcat(Servlet 容器)中,剩下的事情就由 Tomcat 幫我們處理了。
Servlet 接口定義了下面五個(gè)方法:
public interface Servlet { void init(ServletConfig config) throws ServletException; ServletConfig getServletConfig(); void service(ServletRequest req, ServletResponse res)throws ServletException, IOException; String getServletInfo(); void destroy(); }
其中最重要是的 service 方法,具體業(yè)務(wù)類(lèi)在這個(gè)方法里實(shí)現處理邏輯。這個(gè)方法有兩個(gè)參數:ServletRequest 和 ServletResponse。ServletRequest 用來(lái)封裝請求信息,ServletResponse 用來(lái)封裝響應信息,因此本質(zhì)上這兩個(gè)類(lèi)是對通信協(xié)議的封裝。
HTTP 協(xié)議中的請求和響應就是對應了 HttpServletRequest 和 HttpServletResponse 這兩個(gè)類(lèi)。你可以通過(guò) HttpServletRequest 來(lái)獲取所有請求相關(guān)的信息,包括請求路徑、Cookie、HTTP 頭、請求參數等。此外, 我們還可以通過(guò) HttpServletRequest 來(lái)創(chuàng )建和獲取 Session。而 HttpServletResponse 是用來(lái)封裝 HTTP 響應的。
你可以看到接口中還有兩個(gè)跟生命周期有關(guān)的方法 init 和 destroy,這是一個(gè)比較貼心的設計,Servlet 容器在加載 Servlet 類(lèi)的時(shí)候會(huì )調用 init 方法,在卸載的時(shí)候會(huì )調用 destroy 方法。我們可能會(huì )在 init 方法里初始化一些資源,并在 destroy 方法里釋放這些資源,比如 Spring MVC 中的 DispatcherServlet,就是在 init 方法里創(chuàng )建了自己的 Spring 容器。
你還會(huì )注意到 ServletConfig 這個(gè)類(lèi),ServletConfig 的作用就是封裝 Servlet 的初始化參數。你可以在web.xml給 Servlet 配置參數,并在程序里通過(guò) getServletConfig 方法拿到這些參數。
我們知道,有接口一般就有抽象類(lèi),抽象類(lèi)用來(lái)實(shí)現接口和封裝通用的邏輯,因此 Servlet 規范提供了 GenericServlet 抽象類(lèi),我們可以通過(guò)擴展它來(lái)實(shí)現 Servlet。雖然 Servlet 規范并不在乎通信協(xié)議是什么,但是大多數的 Servlet 都是在 HTTP 環(huán)境中處理的,因此 Servet 規范還提供了 HttpServlet 來(lái)繼承 GenericServlet,并且加入了 HTTP 特性。這樣我們通過(guò)繼承 HttpServlet 類(lèi)來(lái)實(shí)現自己的 Servlet,只需要重寫(xiě)兩個(gè)方法:doGet 和 doPost。
當客戶(hù)請求某個(gè)資源時(shí),HTTP 服務(wù)器會(huì )用一個(gè) ServletRequest 對象把客戶(hù)的請求信息封裝起來(lái),然后調用 Servlet 容器的 service 方法,Servlet 容器拿到請求后,根據請求的 URL 和 Servlet 的映射關(guān)系,找到相應的 Servlet,如果 Servlet 還沒(méi)有被加載,就用反射機制創(chuàng )建這個(gè) Servlet,并調用 Servlet 的 init 方法來(lái)完成初始化,接著(zhù)調用 Servlet 的 service 方法來(lái)處理請求,把 ServletResponse 對象返回給 HTTP 服務(wù)器,HTTP 服務(wù)器會(huì )把響應發(fā)送給客戶(hù)端
Servlet 容器會(huì )實(shí)例化和調用 Servlet,那 Servlet 是怎么注冊到 Servlet 容器中的呢?一般來(lái)說(shuō),我們是以 Web 應用程序的方式來(lái)部署 Servlet 的,而根據 Servlet 規范,Web 應用程序有一定的目錄結構,在這個(gè)目錄下分別放置了 Servlet 的類(lèi)文件、配置文件以及靜態(tài)資源,Servlet 容器通過(guò)讀取配置文件,就能找到并加載 Servlet。Web 應用的目錄結構大概是下面這樣的:
| - MyWebApp | - WEB-INF/web.xml -- 配置文件,用來(lái)配置Servlet等 | - WEB-INF/lib/ -- 存放Web應用所需各種JAR包 | - WEB-INF/classes/ -- 存放你的應用類(lèi),比如Servlet類(lèi) | - META-INF/ -- 目錄存放工程的一些信息
Servlet 規范里定義了 ServletContext 這個(gè)接口來(lái)對應一個(gè) Web 應用。Web 應用部署好后,Servlet 容器在啟動(dòng)時(shí)會(huì )加載 Web 應用,并為每個(gè) Web 應用創(chuàng )建唯一的 ServletContext 對象。你可以把 ServletContext 看成是一個(gè)全局對象,一個(gè) Web 應用可能有多個(gè) Servlet,這些 Servlet 可以通過(guò)全局的 ServletContext 來(lái)共享數據,這些數據包括 Web 應用的初始化參數、Web 應用目錄下的文件資源等。由于 ServletContext 持有所有 Servlet 實(shí)例,你還可以通過(guò)它來(lái)實(shí)現 Servlet 請求的轉發(fā)。
引入了 Servlet 規范后,你不需要關(guān)心 Socket 網(wǎng)絡(luò )通信、不需要關(guān)心 HTTP 協(xié)議,也不需要關(guān)心你的業(yè)務(wù)類(lèi)是如何被實(shí)例化和調用的,因為這些都被 Servlet 規范標準化了,你只要關(guān)心怎么實(shí)現的你的業(yè)務(wù)邏輯。這對于程序員來(lái)說(shuō)是件好事,但也有不方便的一面。所謂規范就是說(shuō)大家都要遵守,就會(huì )千篇一律,但是如果這個(gè)規范不能滿(mǎn)足你的業(yè)務(wù)的個(gè)性化需求,就有問(wèn)題了,因此設計一個(gè)規范或者一個(gè)中間件,要充分考慮到可擴展性。Servlet 規范提供了兩種擴展機制:Filter 和 Listener。
Filter 是過(guò)濾器,這個(gè)接口允許你對請求和響應做一些統一的定制化處理,比如你可以根據請求的頻率來(lái)限制訪(fǎng)問(wèn),或者根據國家地區的不同來(lái)修改響應內容。過(guò)濾器的工作原理是這樣的:Web 應用部署完成后,Servlet 容器需要實(shí)例化 Filter 并把 Filter 鏈接成一個(gè) FilterChain。當請求進(jìn)來(lái)時(shí),獲取第一個(gè) Filter 并調用 doFilter 方法,doFilter 方法負責調用這個(gè) FilterChain 中的下一個(gè) Filter。
Listener 是監聽(tīng)器,這是另一種擴展機制。當 Web 應用在 Servlet 容器中運行時(shí),Servlet 容器內部會(huì )不斷的發(fā)生各種事件,如 Web 應用的啟動(dòng)和停止、用戶(hù)請求到達等。 Servlet 容器提供了一些默認的監聽(tīng)器來(lái)監聽(tīng)這些事件,當事件發(fā)生時(shí),Servlet 容器會(huì )負責調用監聽(tīng)器的方法。當然,你可以定義自己的監聽(tīng)器去監聽(tīng)你感興趣的事件,將監聽(tīng)器配置在web.xml中。比如 Spring 就實(shí)現了自己的監聽(tīng)器,來(lái)監聽(tīng) ServletContext 的啟動(dòng)事件,目的是當 Servlet 容器啟動(dòng)時(shí),創(chuàng )建并初始化全局的 Spring 容器。
Tomcat下載地址:https://tomcat.apache.org/download-80.cgi
/bin:存放 Windows 或 Linux 平臺上啟動(dòng)和關(guān)閉 Tomcat 的腳本文件。 /conf:存放 Tomcat 的各種全局配置文件,其中最重要的是server.xml。 /lib:存放 Tomcat 以及所有 Web 應用都可以訪(fǎng)問(wèn)的 JAR 文件。 /logs:存放 Tomcat 執行時(shí)產(chǎn)生的日志文件。 /work:存放 JSP 編譯后產(chǎn)生的 Class 文件。 /webapps:Tomcat 的 Web 應用目錄,默認情況下把 Web 應用放在這個(gè)目錄下。
打開(kāi) Tomcat 的日志目錄,也就是 Tomcat 安裝目錄下的 logs 目錄。Tomcat 的日志信息分為兩類(lèi) :一是運行日志,它主要記錄運行過(guò)程中的一些信息,尤其是一些異常錯誤日志信息 ;二是訪(fǎng)問(wèn)日志,它記錄訪(fǎng)問(wèn)的時(shí)間、IP 地址、訪(fǎng)問(wèn)的路徑等相關(guān)信息。
概要:
知識點(diǎn):
Tomcat是一個(gè)基于JAVA的WEB容器,其實(shí)現了JAVA EE中的 Servlet 與 jsp 規范,與Nginx apache 服務(wù)器不同在于一般用于動(dòng)態(tài)請求處理。在架構設計上采用面向組件的方式設計。即整體功能是通過(guò)組件的方式拼裝完成。另外每個(gè)組件都可以被替換以保證靈活性。
Server 和 Service
Connector 連接器
HTTP 1.1
SSL https
AJP( Apache JServ Protocol) apache 私有協(xié)議,用于apache 反向代理Tomcat
Container
Engine 引擎 catalina
Host 虛擬機 基于域名 分發(fā)請求
Context 隔離各個(gè)WEB應用 每個(gè)Context的 ClassLoader都是獨立
Component
Manager (管理器)
logger (日志管理)
loader (載入器)
pipeline (管道)
valve (管道中的閥)
server
root元素:server 的頂級配置 主要屬性: port:執行關(guān)閉命令的端口號 shutdown:關(guān)閉命令
演示shutdown的用法 #基于telent 執行SHUTDOWN 命令即可關(guān)閉(必須大寫(xiě)) telnet 127.0.0.1 8005 SHUTDOWN
service
服務(wù):將多個(gè)connector 與一個(gè)Engine組合成一個(gè)服務(wù),可以配置多個(gè)服務(wù)。
Connector
連接器:用于接收 指定協(xié)議下的連接 并指定給唯一的Engine 進(jìn)行處理。 主要屬性:
<Connector port="8860" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8862" URIEncoding="UTF-8" useBodyEncodingForURI="true" compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript" maxThreads="1024" minSpareThreads="200" acceptCount="800" maxConnections="10000" enableLookups="false" />
Engine
引擎:用于處理連接的執行器,默認的引擎是catalina。一個(gè)service 中只能配置一個(gè)Engine。 主要屬性:name 引擎名稱(chēng) defaultHost 默認host
Host
虛擬機:基于域名匹配至指定虛擬機。類(lèi)似于nginx 當中的server,默認的虛擬機是localhost. 主要屬性:
演示配置多個(gè)Host
<Host name="www.wukong.com" appBase="/usr/www/wukong" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="www.wukong.com.access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host>
Context
應用上下文:一個(gè)host 下可以配置多個(gè)Context ,每個(gè)Context 都有其獨立的classPath。相互隔離,以免造成ClassPath 沖突。 主要屬性:
演示配置多個(gè)Context
<Context path="/testweb" docBase="testweb.war" reloadbale="true"/>
Valve 閥門(mén):可以理解成
的過(guò)濾器,具體配置要基于具體的Valve 接口的子類(lèi)。以下即為一個(gè)訪(fǎng)問(wèn)日志的Valve
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="www.wukong.com.access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
Tomcat啟動(dòng)參數說(shuō)明
我們平時(shí)啟動(dòng)Tomcat過(guò)程是怎么樣的?
但是我們在Eclipse 或idea 中啟動(dòng)WEB項目的時(shí)候 也是把War包復雜至webapps 目錄解壓?jiǎn)??顯然不是,其真正做法是在Tomcat程序文件之外創(chuàng )建了一個(gè)部署目錄,在一般生產(chǎn)環(huán)境中也是這么做的 即:Tomcat 程序目錄和部署目錄分開(kāi) 。 我們只需要在啟動(dòng)時(shí)指定CATALINA_HOME 與 CATALINA_BASE 參數即可實(shí)現。
| 啟動(dòng)參數 | 描述說(shuō)明 | |:----|:----| | JAVA_OPTS | jvm 啟動(dòng)參數 , 設置內存 編碼等 -Xms100m -Xmx200m -Dfile.encoding=UTF-8 | | JAVA_HOME | 指定jdk 目錄,如果未設置從java 環(huán)境變量當中去找。 | | CATALINA_HOME | Tomcat 程序根目錄 | | CATALINA_BASE | 應用部署目錄,默認為$CATALINA_HOME | | CATALINA_OUT | 應用日志輸出目錄:默認$CATALINA_BASE/log | | CATALINA_TMPDIR | 應用臨時(shí)目錄:默認:$CATALINA_BASE/temp |
可以編寫(xiě)一個(gè)腳本 來(lái)實(shí)現自定義配置:
ln -s /home/wukong/apache-tomcat-8.5.56 apache-tomcat
更新 啟動(dòng) 腳本
#!/bin/bash export JAVA_OPTS="-Xms100m -Xmx200m" export CATALINA_HOME=/home/wukong/apache-tomcat export CATALINA_BASE="`pwd`" case $1 in start) $CATALINA_HOME/bin/catalina.sh start echo start success!! ;; stop) $CATALINA_HOME/bin/catalina.sh stop echo stop success!! ;; restart) $CATALINA_HOME/bin/catalina.sh stop echo stop success!! sleep 3 $CATALINA_HOME/bin/catalina.sh start echo start success!! ;; version) $CATALINA_HOME/bin/catalina.sh version ;; configtest) $CATALINA_HOME/bin/catalina.sh configtest ;; esac exit 0
docker 啟動(dòng)tomcat
docker run -id --name=test_tomcat -e JAVA_OPTS='-Xmx128m' -p 8888:8080 -v /usr/local/tuling-project/tomcat-test/webapps:/usr/local/tomcat/webapps -v /usr/local/tuling-project/tomcat-test/logs:/usr/local/tomcat/logs -v /usr/local/tuling-project/tomcat-test/conf:/usr/local/tomcat/conf --privileged=true tomcat:8
源碼構建
下載地址:https://tomcat.apache.org/download-80.cgi
配置
1.解壓源碼 apache-tomcat-8.5.57-src
2.apache-tomcat-8.5.57-src目錄下添加pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.tomcat</groupId> <artifactId>Tomcat8.0</artifactId> <name>Tomcat8.0</name> <version>8.0</version> <build> <finalName>Tomcat8.0</finalName> <sourceDirectory>java</sourceDirectory> <testSourceDirectory>test</testSourceDirectory> <resources> <resource> <directory>java</directory> </resource> </resources> <testResources> <testResource> <directory>test</directory> </testResource> </testResources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3</version> <configuration> <encoding>UTF-8</encoding> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>3.4</version> </dependency> <dependency> <groupId>ant</groupId> <artifactId>ant</artifactId> <version>1.7.0</version> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>javax.xml</groupId> <artifactId>jaxrpc</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> <version>4.5.1</version> </dependency> </dependencies> </project>
3.在apache-tomcat-8.5.57-src 同級目錄新建 catalina-home并保證目錄下面文件如下
注意: 上面文件夾apache-tomcat-8.5.57-src里面有的,就剪切過(guò)來(lái),沒(méi)有的就新建一個(gè), bin conf webapps 應該是從apache-tomcat-8.5.57-src剪切過(guò)來(lái)的
4.idea引入項目
File->Open 選擇解壓的C:\Users\wukong\Downloads\apache-tomcat-8.5.57-src\apache-tomcat-8.5.57-src
配置啟動(dòng)
MainClass: org.apache.catalina.startup.BootstrapVmOptions: -Dcatalina.home=C:\Users\wukong\Downloads\apache-tomcat-8.5.57-src\apache-tomcat-8.5.57-src\catalina-home
啟動(dòng)報錯
TestCookieFilter 報錯找不到這個(gè)類(lèi)CookieFilter
解決方法:
1. 刪除:TestCookieFilter
啟動(dòng)后,訪(fǎng)問(wèn)localhost:8080 報錯 org.apache.jasper.JasperException: java.lang.NullPointerException
解決方案:
org.apache.catalina.startup.Bootstrap 添加代碼塊
{ JasperInitializer initializer =new JasperInitializer(); }
以上就是Tomcat核心組件及應用架構詳解的詳細內容,更多關(guān)于Tomcat核心組件及應用架構的資料請關(guān)注腳本之家其它相關(guān)文章!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站