前提概要
在特別特殊的時候,我們可能需要外接tomcat去執行程式,例如alitomcat等特殊場景,方便我們去定時化開發專案或者其他特殊場景。
外接tomcat執行
pom.xml檔案首先更改打包方式 war,再排除springboot內建的 web 專案下tomcat依賴
Maven配置調整
移除tomcat依賴或者將tomcat依賴scope改為provide,移除tomcat依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 移除嵌入式tomcat外掛 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
再引入tomcat依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--打包的時候可以不用包進去,別的設施會提供。事實上該依賴理論上可以參與編譯,測試,執行等週期。
相當於compile,但是打包階段做了exclude操作-->
<scope>provided</scope>
</dependency>
將打包方式修改為war
<packaging>war</packaging>
調整springboot的啟動類
繼承org.springframework.boot.web.servlet.support.SpringBootServletInitializer,實現configure方法:
為什麼繼承該類,SpringBootServletInitializer原始碼註釋:
-
Note that a WebApplicationInitializer is only needed if you are building a war file and deploying it. If you prefer to run an embedded web server then you won't need this at all.
-
注意,如果您正在構建WAR檔案並部署它,則需要WebApplicationInitializer。如果你喜歡執行一個嵌入式Web伺服器,那麼你根本不需要這個。
DemoApplication,讓其實現SpringBootServletInitializer,然後重寫configure()方法:
方式一,啟動類繼承SpringBootServletInitializer實現configure:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
方式二,新增加一個類繼承SpringBootServletInitializer實現configure:
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//此處的Application.class為帶有@SpringBootApplication註解的啟動類
return builder.sources(Application.class);
}
}
注意事項
- 使用外部Tomcat部署訪問的時候,application.properties(或者application.yml)中配置的將失效,請使用tomcat的埠,tomcat,webapps下專案名進行訪問。
server.port=
server.servlet.context-path=
- 為了防止應用上下文所導致的專案訪問資源載入不到的問題,建議pom.xml檔案中
標籤下新增 標籤:
<build>
<!-- 應與application.properties(或application.yml)中context-path保持一致 -->
<finalName>war包名稱</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
-
IDEA 下,執行mvn clean,--> mvn package ,等到專案打包成功,在該專案檔案位置找到target 下的 demo.war,拷貝到tomcat/webapps目錄下,
-
使用windows命令列,啟動tomcat伺服器,專案啟動成功會出現, spring的標誌。
-
訪問路徑:localhost:8080/${打包檔名}/請求url
-
如何在訪問時去掉war包名?
原理:Tomcat的預設根目錄是ROOT,實際上ROOT這個專案在實際生產環境是沒有用的,所以我們可以用我們的專案覆蓋ROOT專案
操作過程
-
刪除ROOT下所有檔案及資料夾.
-
把我們專案的war包解壓後,專案目錄下的所有檔案和子目錄都拷貝到ROOT目錄下即可或者有更狠的一招:直接刪掉ROOT目錄,然後把我們的專案打包名稱改成ROOT.war,放到webapps下就行.
原理:Tomcat本身可以配置虛擬目錄。方法就是在Server.xml中
節點下加入Context資訊。
如我們可以配置<Context path="/abc" docBase="D:\app\abc" ... />,那我們可以通過地址http://localhost:8080/abc來訪問我們放在D:\app\下面的abc專案。我們可以把這個path="/abc"修改為path=""。意思就是把abc對映到根目錄,訪問路徑就會變成http://localhost:8080/。
按照配置虛擬目錄的方式,在
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="Interface" reloadable="true" />
<!--注:我這裡使用的是相對路徑,Interface專案是放在Tomcat的webapps目錄下的,當然也可以改為絕對路徑-->
</Host>
</Engine>
Spring Boot也提供了對JMX監控的支援。JMX監控對外暴露的資訊相同,不過是使用MBeans容器將應用資料封裝管理。
-
Springboot 的jmx 是預設開啟的,如果tomcat 部署兩個原springboot 打成的war 包。
-
需要將每一個專案的jmx關閉Application.properties 配置中 新增spring.jmx.enabled=false;
-
在各自專案中都新增:spring.jmx.default-domain=project1以及spring.jmx.default-domain=project2保證domain是不一樣的。
-
tomcat 相關配置修改
修改預設的http訪問埠:8080 為 8181,在tomcat8.5/conf/server.xml檔案裡修改:示例
<Connector port="8181" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
修改預設的session有效期
在tomcat/conf/web.xml檔案裡修改,範圍是具體專案:示例
<session-config>
<session-timeout>30</session-timeout>
</session-config>
在tomcat/conf/server.xml
<Context path="/test" docBase="/test"
defaultSessionTimeOut="3600" isWARExpanded="true"
isWARValidated="false" isInvokerEnabled="true"
isWorkDirPersistent="false"/>
在java後臺程式碼裡配置,具體頁面的session有效時間
session.setMaxInactiveInterval(30*60);
生效優先順序: 3 > 2 > 1,
(彩蛋) tomcat 調優
tomcat 修改最大執行緒,在tomcat/conf/server.xml檔案裡修改:示例
- maxThreads=“X” 表示最多同時處理X個連線
- minSpareThreads=“X” 初始化X個連線
- maxSpareThreads=“X” 表示如果最多可以有X個執行緒,一旦超過X個,則會關閉不在需要的執行緒
- acceptCount=“X” 當同時連線的人數達到maxThreads時,還可以排隊,佇列大小為X.超過X就不處理
tomcat 記憶體優化
- Windows 下的catalina.bat
- Linux 下的catalina.sh 如:
JAVA_OPTS=’-Xms256m -Xmx512m’
-Xms JVM初始化堆的大小
-Xmx JVM堆的最大值 實際引數大小根據伺服器配置或者專案具體設定.
Tomcat IO優化
- 同步阻塞IO(JAVA BIO) 同步並阻塞,伺服器實現模式為一個連線一個執行緒(one connection one thread 想想都覺得恐怖,執行緒可是非常寶貴的資源),當然可以通過執行緒池機制改善.
- BIO方式適用於連線數目比較小且固定的架構,這種方式對伺服器資源要求比較高,併發侷限於應用中,JDK1.4以前的唯一選擇,但程式直觀簡單易理解.
- JAVA NIO:又分為同步非阻塞IO,非同步阻塞IO 與BIO最大的區別one request one thread.可以複用同一個執行緒處理多個connection(多路複用)
- NIO方式適用於連線數目多且連線比較短(輕操作)的架構,比如聊天伺服器,併發侷限於應用中,程式設計比較複雜,JDK1.4開始支援.
- 非同步非阻塞IO(Java NIO2又叫AIO) 主要與NIO的區別主要是作業系統的底層區別.可以做個比喻:比作快遞,NIO就是網購後要自己到官網查下快遞是否已經到了(可能是多次),然後自己去取快遞;AIO就是快遞員送貨上門了(不用關注快遞進度)。
- AIO方式使用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,充分呼叫OS參與併發操作,程式設計比較複雜,JDK7開始支援.
在server.xml中
實現對Tomcat的IO切換
APR是從作業系統級別來解決非同步的IO問題,大幅度的提高效能. (http://apr.apache.org/).
- APR(Apache Portable Runtime)是一個高可移植庫,它是Apache HTTP Server 2.x的核心.能更好地和其它本地web技術整合,總體上讓Java更有效率作為一個高效能web伺服器平臺而不是簡單作為後臺容器.
- 在產品環境中,特別是直接使用Tomcat做WEB伺服器的時候,應該使用Tomcat,Native來提高其效能.如果不配APR,基本上300個執行緒狠快就會用滿,以後的請求就只好等待.但是配上APR之後,併發的執行緒數量明顯下降,從原來的300可能會馬上下降到只有幾十,新的請求會毫無阻塞的進來.
- 在區域網環境測,就算是400個併發,也是一瞬間就處理/傳輸完畢,但是在真實的Internet環境下,頁面處理時間只佔0.1%都不到,絕大部分時間都用來頁面傳輸.如果不用APR,一個執行緒同一時間只能處理一個使用者,勢必會造成阻塞。所以生產環境下用apr是非常必要的.