Spring boot實(shí)現(xiàn)應(yīng)用打包部署的示例
1、Spring Boot內(nèi)置web
Spring Boot 其默認(rèn)是集成web容器的,啟動(dòng)方式由像普通Java程序一樣,main函數(shù)入口啟動(dòng)。其內(nèi)置Tomcat容器或Jetty容器,具體由配置來決定(默認(rèn)Tomcat)。當(dāng)然你也可以將項(xiàng)目打包成war包,放到獨(dú)立的web容器中(Tomcat、weblogic等等),當(dāng)然在此之前你要對(duì)程序入口做簡(jiǎn)單調(diào)整。
對(duì)server的幾個(gè)常用的配置做個(gè)簡(jiǎn)單說明:
# 項(xiàng)目contextPath,一般在正式發(fā)布版本中,我們不配置 server.context-path=/myspringboot # 錯(cuò)誤頁,指定發(fā)生錯(cuò)誤時(shí),跳轉(zhuǎn)的URL。請(qǐng)查看BasicErrorController源碼便知 server.error.path=/error # 服務(wù)端口 server.port=9090 # session最大超時(shí)時(shí)間(分鐘),默認(rèn)為30 server.session-timeout=60 # 該服務(wù)綁定IP地址,啟動(dòng)服務(wù)器時(shí)如本機(jī)不是該IP地址則拋出異常啟動(dòng)失敗,只有特殊需求的情況下才配置 # server.address=192.168.16.11
Tomcat
Tomcat為Spring Boot的默認(rèn)容器,下面是幾個(gè)常用配置:
pom.xml依賴配置:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <!--<scope>provided</scope>--> </dependency>
# tomcat最大線程數(shù),默認(rèn)為200 server.tomcat.max-threads=800 # tomcat的URI編碼 server.tomcat.uri-encoding=UTF-8 # 存放Tomcat的日志、Dump等文件的臨時(shí)文件夾,默認(rèn)為系統(tǒng)的tmp文件夾(如:C:\Users\Shanhy\AppData\Local\Temp) server.tomcat.basedir=H:/springboot-tomcat-tmp # 打開Tomcat的Access日志,并可以設(shè)置日志格式的方法: #server.tomcat.access-log-enabled=true #server.tomcat.access-log-pattern= # accesslog目錄,默認(rèn)在basedir/logs #server.tomcat.accesslog.directory= # 日志文件目錄 logging.path=H:/springboot-tomcat-tmp # 日志文件名稱,默認(rèn)為spring.log logging.file=myapp.log
Jetty
如果你要選擇Jetty,也非常簡(jiǎn)單,就是把pom中的tomcat依賴排除,并加入Jetty容器的依賴,如下:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependencies>
項(xiàng)目構(gòu)建我們使用Maven或Gradle,這將使項(xiàng)目依賴、jar包管理、以及打包部署變的非常方便。
2、Maven構(gòu)建Spring Boot框架的可執(zhí)行Jar包
在spring boot里,很吸引人的一個(gè)特性是可以直接把應(yīng)用打包成為一個(gè)jar/war,然后這個(gè)jar/war是可以直接啟動(dòng)的,不需要另外配置一個(gè)Web Server。單獨(dú)的JAR包,然后通過java -jar <name>.jar命令運(yùn)行。
1.1 Maven
SpringBootMaven插件為Maven提供SpringBoot支持,它允許你打包可執(zhí)行jar或war存檔,然后就地運(yùn)行應(yīng)用。為了使用
它,你需要使用Maven 3.2(或更高版本)。
Maven用戶可以繼承spring-boot-starter-parent項(xiàng)目來獲取合適的默認(rèn)設(shè)置。該父項(xiàng)目提供以下特性:
1、默認(rèn)編譯級(jí)別為Java 1.6
2、源碼編碼為UTF-8
3、一個(gè)依賴管理節(jié)點(diǎn),允許你省略普通依賴的 <version>標(biāo)簽,繼承自 spring-boot-dependenciesPOM。
4、合適的插件配置(exec插件,surefire,Git commitID,shade)
5、針對(duì) application.properties和application.yml 的資源過濾
6、最后一點(diǎn):由于默認(rèn)配置文件接收Spring風(fēng)格的占位符( ${...} ),Maven filtering改用@..@ 占位符(你可以使用Maven屬性 resource.delimiter來覆蓋它)。
1.2繼承starter parent
想配置你的項(xiàng)目繼承 spring-boot-starter-parent 只需要簡(jiǎn)單地設(shè)置parent為:
<!-- Inherit defaults from Spring Boot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.0.BUILD-SNAPSHOT</version> </parent>
注:你應(yīng)該只需要在該依賴上指定Spring Boot版本。如他的starters,你可以放心的省略版本號(hào)。
1.3使用沒有父POM的SpringBoot
不是每個(gè)人都喜歡繼承spring-boot-starter-parentPOM。你可能需要使用公司標(biāo)準(zhǔn)parent,或你可能傾向于顯式聲明所有
Maven配置。
如果你不使用 spring-boot-starter-parent ,通過使用一個(gè)scope=import 的依賴,你仍能獲取到依賴管理的好處:
<dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.3.0.BUILD-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
1.4改變Java版本
spring-boot-starter-parent選擇相當(dāng)保守的Java兼容策略。如果你遵循我們的建議,使用最新的Java版本,你可以添加一
個(gè) java.version屬性:
<properties> <java.version>1.8</java.version> </properties>
1.5 使用Spring Boot Maven插件
SpringBoot包含一個(gè)Maven插件,它可以將項(xiàng)目打包成一個(gè)可執(zhí)行jar。如果想使用它,你可以將該插件添加到<plugins>節(jié)
點(diǎn)處:
<?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> <!-- ... --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.3.0.BUILD-SNAPSHOT</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
注:如果使用Spring-Boot-tarter-parent pom,你只需要添加該插件而無需配置它,除非你想改變定義在partent中的設(shè)置。
該配置會(huì)在Maven生命周期的 package階段重新打包一個(gè)jar或war。下面的示例顯示在target目錄下既有重新打包后的jar,
也有原始的jar:
1.6 linux下打包方法:
使用 mvn clean package 命令打包
如果還沒有安裝maven :
yum -y install apache-maven
或者單獨(dú)下載安裝:
wget http://apache.fayea.com/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz tar zxvf apache-maven-3.3.9-bin.tar.gz
設(shè)置環(huán)境變量:
MVN_HOME=/usr/local/app/apache-maven-3.3.9 export PATH=$PATH:$MVN_HOME/bin
然后可以使用以下命令編譯:
mvn clean package
可以追加參數(shù) -Dmaven.test.skip=true 跳過測(cè)試。
$mvn package $ls target/*.ja
target/myproject-1.0.0.jartarget/myproject-1.0.0.jar.original
1.6 使用Eclipse下打包方法:
打開maven插件的maven package,就可以打包了:
打包出來的文件:
如果不包含像上面那樣的<execution/>,你可以自己運(yùn)行該插件(但只有在package目標(biāo)也被使用的情況)。例如:
$ mvn package spring-boot:repackage $ ls target/*.jar
target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
如果使用一個(gè)里程碑或快照版本,你還需要添加正確的pluginRepository元素:
<pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <url>http://repo.spring.io/snapshot</url> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <url>http://repo.spring.io/milestone</url> </pluginRepository> </pluginRepositories>
打包可執(zhí)行jar和war文件
一旦spring-boot-maven-plugin被包含到你的pom.xml中,它就會(huì)自動(dòng)嘗試使用spring-boot:repackage目標(biāo)重寫存檔以使它們能夠執(zhí)行。為了構(gòu)建一個(gè)jar或war,你應(yīng)該使用常規(guī)的packaging元素配置你的項(xiàng)目:
<?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"> <!-- ... --> <packaging>jar</packaging> <!-- ... --> </project>
生成的存檔在 package 階段會(huì)被SpringBoot增強(qiáng)。你想啟動(dòng)的main類即可以通過指定一個(gè)配置選項(xiàng),也可以通過為manifest添加一個(gè)Main-Class屬性這種常規(guī)的方式實(shí)現(xiàn)。如果你沒有指定一個(gè)main類,該插件會(huì)搜索帶有publicstaticvoidmain(String[]args)方法的類。
為了構(gòu)建和運(yùn)行一個(gè)項(xiàng)目的artifact,你可以輸入以下命令:
$ mvn package $ java -jar target/spring-boot01-1.0-SNAPSHOT.jar
這種方式,只要控制臺(tái)關(guān)閉,服務(wù)就不能訪問了。下面我們使得 jar 包在后臺(tái)運(yùn)行:
java -jar spring-boot01-1.0-SNAPSHOT.jar > log.file 2>&1 &
為了構(gòu)建一個(gè)即是可執(zhí)行的,又能部署到一個(gè)外部容器的war文件,你需要標(biāo)記內(nèi)嵌容器依賴為"provided",例如:
<?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"> <!-- ... --> <packaging>war</packaging> <!-- ... --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- ... --> </dependencies> </project>
4、打包為單個(gè)jar時(shí),spring boot的啟動(dòng)方式
maven打包之后,會(huì)生成兩個(gè)jar文件:
- demo-0.0.1-SNAPSHOT.jar
- demo-0.0.1-SNAPSHOT.jar.original
其中demo-0.0.1-SNAPSHOT.jar.original是默認(rèn)的maven-jar-plugin生成的包。
demo-0.0.1-SNAPSHOT.jar是spring boot maven插件生成的jar包,里面包含了應(yīng)用的依賴,以及spring boot相關(guān)的類。下面稱之為fat jar。
先來查看spring boot打好的包的目錄結(jié)構(gòu)(不重要的省略掉):
├── META-INF │ ├── MANIFEST.MF ├── application.properties ├── com │ └── example │ └── SpringBootDemoApplication.class ├── lib │ ├── aopalliance-1.0.jar │ ├── spring-beans-4.2.3.RELEASE.jar │ ├── ... └── org └── springframework └── boot └── loader ├── ExecutableArchiveLauncher.class ├── JarLauncher.class ├── JavaAgentDetector.class ├── LaunchedURLClassLoader.class ├── Launcher.class ├── MainMethodRunner.class ├── ...
依次來看下這些內(nèi)容。
MANIFEST.MF
Manifest-Version: 1.0 Start-Class: com.example.SpringBootDemoApplication Implementation-Vendor-Id: com.example Spring-Boot-Version: 1.3.0.RELEASE Created-By: Apache Maven 3.3.3 Build-Jdk: 1.8.0_60 Implementation-Vendor: Pivotal Software, Inc. Main-Class: org.springframework.boot.loader.JarLauncher
可以看到有Main-Class是org.springframework.boot.loader.JarLauncher ,這個(gè)是jar啟動(dòng)的Main函數(shù)。
還有一個(gè)Start-Class是com.example.SpringBootDemoApplication,這個(gè)是我們應(yīng)用自己的Main函數(shù)
@SpringBootApplication public class SpringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); } }
com/example 目錄
這下面放的是應(yīng)用的.class文件。
lib目錄
這里存放的是應(yīng)用的Maven依賴的jar包文件。
比如spring-beans,spring-mvc等jar。
org/springframework/boot/loader 目錄
這下面存放的是Spring boot loader的.class文件。
啟動(dòng):
我們直接啟動(dòng):java -jar demo-0.0.1-SNAPSHOT.jar
5、Maven添加本地Jar包
我們有時(shí)候項(xiàng)目依賴外部的jar,我們使用Eclipse開發(fā)的時(shí)候我們直接通過build path添加jar就可以,但是使用mvn 打包的時(shí)候就會(huì)缺少這個(gè)包。
1. 使用system scope
我們直接引入rabbitmq-client.jar。這個(gè)方式比較靈活,到新的服務(wù)器上,無需做額外的操作。
<dependency> <groupId>rabbitmq.client</groupId> <artifactId>rabbitmq.client</artifactId> <version>3.0</version> <scope>system</scope> <systemPath>${basedir}/src/main/WEB-INF/lib/rabbitmq-client.jar</systemPath> </dependency>
1、groupId和artifactId以及version都是可以隨便填寫的 ,scope必須填寫為system,而systemPath我們現(xiàn)在我們jar包的目錄地址就可以了
2、${basedir}就是項(xiàng)目根目錄
2. 將jar包安裝到本地repository中
這個(gè)需要在新機(jī)器上執(zhí)行mvn install:install-file命令。
mvn install:install-file -Dfile= jar文件所存放的地址 -DgroupId= jar文件所屬的group:包名 -DartifactId= jar的項(xiàng)目名 名稱,一般就是去掉后綴的文件名 -Dversion=版本號(hào) -Dpackaging=jar:此包的打包形式,就是jar -DgeneratePom=true
例如執(zhí)行命令:
mvn install:install-file -Dfile=D:\JAR_LIB\rabbitmq-client.jar -DgroupId=com.rabbitmq -DartifactId=client -Dversion=3.5.0 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true
在項(xiàng)目中引用:
<dependency> <groupId>com.rabbitmq</groupId> <artifactId>client</artifactId> <version>3.5.0</version> </dependency>
3、添加 in project repository
設(shè)置項(xiàng)目的庫目錄
<repository> <id>in-project</id> <name>In Project Repo</name> <url>file://${project.basedir}/lib</url> </repository>
添加依賴:
<dependency> <groupId>com.rabbitmq</groupId> <artifactId>client</artifactId> <version>3.5.0</version> </dependency>
jar包及路徑必須嚴(yán)格遵循格式:
/groupId/artifactId/version/artifactId-verion.jar
本例中: lib/com/rabbitmq/client/3.5.0/rabbitmq-client-3.5.0.jar
6、部署到j(luò)avaEE容器
修改啟動(dòng)類,繼承 SpringBootServletInitializer 并重寫 configure 方法
public class SpringBootSampleApplication extends SpringBootServletInitializer{ private static final Logger logger = LoggerFactory.getLogger(SpringBootSampleApplication.class); @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(this.getClass()); } }
修改pom文件中jar 為 war
<!-- <packaging>jar</packaging> --> <packaging>war</packaging>
修改pom,排除tomcat插件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency>
打包部署到容器
7、熱部署
在我們開發(fā)過程中,我們需要經(jīng)常修改,為了避免重復(fù)啟動(dòng)項(xiàng)目,我們可以啟用熱部署。
Spring-Loaded項(xiàng)目提供了強(qiáng)大的熱部署功能,添加/刪除/修改 方法/字段/接口/枚舉 等代碼的時(shí)候都可以熱部署,速度很快,很方便。
想在Spring Boot中使用該功能非常簡(jiǎn)單,就是在spring-boot-maven-plugin插件下面添加依賴:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> <version>1.2.5.RELEASE</version> </dependency> </dependencies>
添加以后,通過mvn spring-boot:run啟動(dòng)就支持熱部署了。
注意:使用熱部署的時(shí)候,需要IDE編譯類后才能生效,你可以打開自動(dòng)編譯功能,這樣在你保存修改的時(shí)候,類就自動(dòng)重新加載了。
8、使用Profile區(qū)分環(huán)境
application.properties區(qū)分環(huán)境
spring boot 可以在 “配置文件”、“Java代碼類”、“日志配置” 中來配置profile區(qū)分不同環(huán)境執(zhí)行不同的結(jié)果
1、配置文件
使用配置文件application.yml 和 application.properties 有所區(qū)別
以application.properties 為例,通過文件名來區(qū)分環(huán)境 application-{profile}.properties
application.properties app.name=MyApp server.port=8080 spring.profiles.active=dev application-dev.properties server.port=8081 application-stg.properties server.port=8082
在啟動(dòng)程序的時(shí)候通過添加 –spring.profiles.active={profile} 來指定具體使用的配置
例如我們執(zhí)行 java -jar demo.jar –spring.profiles.active=dev 那么上面3個(gè)文件中的內(nèi)容將被如何應(yīng)用?
Spring Boot 會(huì)先加載默認(rèn)的配置文件,然后使用具體指定的profile中的配置去覆蓋默認(rèn)配置。
app.name 只存在于默認(rèn)配置文件 application.properties 中,因?yàn)橹付ōh(huán)境中不存在同樣的配置,所以該值不會(huì)被覆蓋
server.port 默認(rèn)為8080,但是我們指定了環(huán)境后,將會(huì)被覆蓋。如果指定stg環(huán)境,server.port 則為 8082
spring.profiles.active 默認(rèn)指定dev環(huán)境,如果我們?cè)谶\(yùn)行時(shí)指定 –spring.profiles.active=stg 那么將應(yīng)用stg環(huán)境,最終 server.port 的值為8082
Maven環(huán)境配置
項(xiàng)目工程統(tǒng)一使用maven的profile插件定義不同的項(xiàng)目構(gòu)建環(huán)境(dev, alpha, beta, prod),通過filter插件為不同環(huán)境下的配置項(xiàng)注入對(duì)應(yīng)的參數(shù)值來實(shí)現(xiàn)動(dòng)態(tài)配置目標(biāo)。
2定義profile
在POM.xml中配置四個(gè)profile,對(duì)應(yīng)項(xiàng)目所處的四個(gè)不同的環(huán)境-dev, alpha, beta, prod, profile的id屬性即為每個(gè)環(huán)境賦予一個(gè)唯一的標(biāo)示,元素的內(nèi)容則是以key-value的形式出現(xiàn)的鍵值對(duì),如我們定義了一個(gè)變量,其值在不同的環(huán)境下(不同id)被賦予了不同的值(dev, test, pre-prod, prod),要激活不同的環(huán)境打包,我們可以在命令行通過mvn package –P${profileId}來讓其運(yùn)行,為了開發(fā)便利,默認(rèn)激活的是dev開發(fā)環(huán)境,即開發(fā)人員不需要通過命令行手動(dòng)輸入-p參數(shù)也能運(yùn)行dev環(huán)境的打包。
<profile> <!-- 本地參數(shù) --> <id>dev</id> <properties> <server.port>8081</server.port> <server.address>0.0.0.0</server.address> <profileActive>dev</profileActive> </properties> <build> <filters> <filter> <groupId>${basedir}/src/main/resources/dev.properties</groupId> </filter> </profile>
9、創(chuàng)建一個(gè)Linux 應(yīng)用的sh腳本
下面幾個(gè)腳本僅供參考:
打包:clean.sh
#0、check user TIME_STAMP=`date +%Y%m%d%H%M` WHO=`whoami` if [ "$WHO" != 'www' ]; then echo 'current user is not www' echo 'exit' exit fi CODE_HOME=/home/www/app PROJECTNAME=qrealtime cd $CODE_HOME/$PROJECTNAME git pull mvn clean package pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk '{print $2}' ` if [ $pid != "" ]; then echo "App is running and pid=$pid" else echo "App is not running." fi
start.sh
#0、check user TIME_STAMP=`date +%Y%m%d%H%M` WHO=`whoami` if [ "$WHO" != 'www' ]; then echo 'current user is not www' echo 'exit' exit fi CODE_HOME=/home/www/app PROJECTNAME=qrealtime cd $CODE_HOME/$PROJECTNAME pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk '{print $2}'` if [ $pid ]; then echo "App is running and pid=$pid" else nohup java -jar $CODE_HOME/$PROJECTNAME/target/$<span style="font-family: 'microsoft yahei';">PROJECTNAME</span><span style="font-family: 'microsoft yahei';">-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &</span> fi
stop.sh
#0、check user TIME_STAMP=`date +%Y%m%d%H%M` WHO=`whoami` if [ "$WHO" != 'www' ]; then echo 'current user is not www' echo 'exit' exit fi CODE_HOME=/home/www/app PROJECTNAME=qrealtime cd $CODE_HOME/$PROJECTNAME pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk '{print $2}' ` if [ $pid ]; then echo "App is running and pid=$pid" kill -9 $pid if [[ $? -eq 0 ]];then echo "sucess to stop $PROJECTNAME " else echo "fail to stop $PROJECTNAME " fi fi
restart
#0、check user TIME_STAMP=`date +%Y%m%d%H%M` WHO=`whoami` if [ "$WHO" != 'www' ]; then echo 'current user is not www' echo 'exit' exit fi CODE_HOME=/home/www/app PROJECTNAME=qrealtime cd $CODE_HOME/$PROJECTNAME pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk '{print $2}' ` if [ $pid ]; then echo "App is running and pid=$pid" kill -9 $pid fi nohup java -jar $CODE_HOME/$PROJECTNAME/target/$PROJECTNAME-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &
10、Spring Boot應(yīng)用的docker化
首先看Spring Boot應(yīng)用程序的docker化,由于Spring Boot內(nèi)嵌了tomcat、Jetty等容器,因此我們對(duì)docker鏡像的要求就是需要java運(yùn)行環(huán)境。我的應(yīng)用代碼的的Dockerfile文件如下:
#基礎(chǔ)鏡像:倉庫是java,標(biāo)簽用8u66-jdk FROM java:8u66-jdk #當(dāng)前鏡像的維護(hù)者和聯(lián)系方式 MAINTAINER duqi duqi@example.com #將打包好的spring程序拷貝到容器中的指定位置 ADD target/bookpub-0.0.1-SNAPSHOT.jar /opt/bookpub-0.0.1-SNAPSHOT.jar #容器對(duì)外暴露8080端口 EXPOSE 8080 #容器啟動(dòng)后需要執(zhí)行的命令 CMD java -Djava.security.egd=file:/dev/./urandom -jar /opt/bookpub-0.0.1-SNAPSHOT.jar
因?yàn)槟壳暗氖纠绦虮容^簡(jiǎn)單,這個(gè)dockerfile并沒有在將應(yīng)用程序的數(shù)據(jù)存放在宿主機(jī)上。如果你的應(yīng)用程序需要寫文件系統(tǒng),例如日志,最好利用VOLUME /tmp命令,這個(gè)命令的效果是:在宿主機(jī)的/var/lib/docker目錄下創(chuàng)建一個(gè)臨時(shí)文件并把它鏈接到容器中的/tmp目錄。
把這個(gè)Dockerfile放在項(xiàng)目的根目錄下即可,后續(xù)通過docker-compose build統(tǒng)一構(gòu)建:基礎(chǔ)鏡像是只讀的,然后會(huì)在該基礎(chǔ)鏡像上增加新的可寫層來供我們使用,因此java鏡像只需要下載一次。
docker-compose是用來做docker服務(wù)編排,參看《Docker從入門到實(shí)踐》中的解釋:
Compose 項(xiàng)目目前在 Github 上進(jìn)行維護(hù),目前最新版本是 1.2.0。Compose 定位是“defining and running complex applications with Docker”,前身是 Fig,兼容 Fig 的模板文件。
Dockerfile 可以讓用戶管理一個(gè)單獨(dú)的應(yīng)用容器;而 Compose 則允許用戶在一個(gè)模板(YAML 格式)中定義一組相關(guān)聯(lián)的應(yīng)用容器(被稱為一個(gè) project,即項(xiàng)目),例如一個(gè) Web 服務(wù)容器再加上后端的數(shù)據(jù)庫服務(wù)容器等。
單個(gè)docker用起來確實(shí)沒什么用,docker技術(shù)的關(guān)鍵在于持續(xù)交付,通過與jekins的結(jié)合,可以實(shí)現(xiàn)這樣的效果:開發(fā)人員提交push,然后jekins就自動(dòng)構(gòu)建并測(cè)試剛提交的代碼,這就是我理解的持續(xù)交付。
11、守護(hù)進(jìn)程啟動(dòng)
使用java命令運(yùn)行應(yīng)用非常簡(jiǎn)單,但是通常我們都是通過ssh命令連接到服務(wù)器并運(yùn)行它,一旦ssh連接斷開,那么由它fork的java子進(jìn)程也就隨之銷毀了。所以我們必須借助工具將應(yīng)用作為服務(wù)運(yùn)行在服務(wù)器上:
Systemd
systemd 是Linux 下的一款系統(tǒng)和服務(wù)管理器??梢詾镾pring Boot應(yīng)用編寫啟動(dòng)腳本:
[Unit] Description=Spring Boot Application [Service] ExecStart=/usr/bin/java -jar location_of_jar_file.jar --spring.config.location=location_of_config.properties --spring.profiles.active=profile User=${your expected user} [Install] WantedBy=multi-user.target
Supervisord
Supervisord配置:
[program:app] command=/usr/bin/java -jar location_of_jar_file.jar --spring.config.location=location_of_config.properties --spring.profiles.active=profile user=${your expected user} autostart=true autorestart=true startsecs=10 startretries=3
12、生產(chǎn)環(huán)境運(yùn)維支持
與開發(fā)和測(cè)試環(huán)境不同的是,當(dāng)應(yīng)用部署到生產(chǎn)環(huán)境時(shí),需要各種運(yùn)維相關(guān)的功能的支持,包括性能指標(biāo)、運(yùn)行信息和應(yīng)用管理等。所有這些功能都有很多技術(shù)和開源庫可以實(shí)現(xiàn)。Spring Boot 對(duì)這些運(yùn)維相關(guān)的功能進(jìn)行了整合,形成了一個(gè)功能完備和可定制的功能集,稱之為 Actuator。只需要在 POM 文件中增加對(duì) “org.springframe.boot:spring-boot-starter-actuator” 的依賴就可以添加 Actuator。Actuator 在添加之后,會(huì)自動(dòng)暴露一些 HTTP 服務(wù)來提供這些信息。這些 HTTP 服務(wù)的說明如表 2。
Spring Boot Actuator 所提供的 HTTP 服務(wù)
名稱 | 說明 | 是否包含敏感信息 |
---|---|---|
autoconfig | 顯示 Spring Boot 自動(dòng)配置的信息。 | 是 |
beans | 顯示應(yīng)用中包含的 Spring bean 的信息。 | 是 |
configprops | 顯示應(yīng)用中的配置參數(shù)的實(shí)際值。 | 是 |
dump | 生成一個(gè) thread dump。 | 是 |
env | 顯示從 ConfigurableEnvironment 得到的環(huán)境配置信息。 | 是 |
health | 顯示應(yīng)用的健康狀態(tài)信息。 | 否 |
info | 顯示應(yīng)用的基本信息。 | 否 |
metrics | 顯示應(yīng)用的性能指標(biāo)。 | 是 |
mappings | 顯示 Spring MVC 應(yīng)用中通過“ @RequestMapping”添加的路徑映射。 |
是 |
shutdown | 關(guān)閉應(yīng)用。 | 是 |
trace | 顯示應(yīng)用相關(guān)的跟蹤(trace)信息。 | 是 |
對(duì)于表中的每個(gè)服務(wù),通過訪問名稱對(duì)應(yīng)的 URL 就可以獲取到相關(guān)的信息。如訪問“/info”就可以獲取到 info 服務(wù)對(duì)應(yīng)的信息。服務(wù)是否包含敏感信息說明了該服務(wù)暴露出來的信息是否包含一些比較敏感的信息,從而確定是否需要添加相應(yīng)的訪問控制,而不是對(duì)所有人都公開。所有的這些服務(wù)都是可以配置的,比如通過改變名稱來改變相應(yīng)的 URL。下面對(duì)幾個(gè)重要的服務(wù)進(jìn)行介紹。
health 服務(wù)
Spring Boot 默認(rèn)提供了對(duì)應(yīng)用本身、關(guān)系數(shù)據(jù)庫連接、MongoDB、Redis 和 Rabbit MQ 的健康狀態(tài)的檢測(cè)功能。當(dāng)應(yīng)用中添加了 DataSource 類型的 bean 時(shí),Spring Boot 會(huì)自動(dòng)在 health 服務(wù)中暴露數(shù)據(jù)庫連接的信息。應(yīng)用也可以提供自己的健康狀態(tài)信息,如代碼清單 7 所示。
health 服務(wù)
@Component public class AppHealthIndicator implements HealthIndicator { @Override public Health health() { return Health.up().build(); } }
應(yīng)用只需要實(shí)現(xiàn) org.springframework.boot.actuate.health.HealthIndicator 接口,并返回一個(gè) org.springframework.boot.actuate.health.Health 對(duì)象,就可以通過 health 服務(wù)來獲取所暴露的信息。health 服務(wù)返回的
結(jié)果
{"status":"UP","app":{"status":"UP"},"db":{"status":"UP","database":"HSQL Database Engine","hello":1}}
info 服務(wù)
info 服務(wù)所暴露的信息是完全由應(yīng)用來確定的。應(yīng)用中任何以“info.”開頭的配置參數(shù)會(huì)被自動(dòng)的由 info 服務(wù)來暴露。只需要往 application.properties 中添加以“info.”開頭的參數(shù)即可,如:
info.app_name=My First Spring Boot Application info.app_version=1.0.0
當(dāng)訪問“/info”時(shí),訪問的 JSON 數(shù)據(jù):{"app_name":"My First Spring Boot Application","app_version":"1.0.0"}
metrics 服務(wù)
當(dāng)訪問 metrics 服務(wù)時(shí),可以看到 Spring Boot 通過 SystemPublicMetrics 默認(rèn)提供的一些系統(tǒng)的性能參數(shù)值,包括內(nèi)存、CPU、Java 類加載和線程等的基本信息。應(yīng)用可以記錄其他所需要的信息。Spring Boot 默認(rèn)提供了兩種類型的性能指標(biāo)記錄方式:gauge 和 counter。gauge 用來記錄單個(gè)絕對(duì)數(shù)值,counter 用來記錄增量或減量值。比如在一個(gè) Web 應(yīng)用中,可以用 counter 來記錄當(dāng)前在線的用戶數(shù)量。當(dāng)用戶登錄時(shí),把 counter 的值加 1;當(dāng)用戶退出時(shí),把 counter 的值減 1。
示例:
@RestController public class GreetingsController { @Autowired private CounterService counterService; @RequestMapping("/greet") public String greet() { counterService.increment("myapp.greet.count"); return "Hello!"; } }
上面代碼添加了對(duì) Spring Boot 提供的 CounterService 的依賴。當(dāng) greet 方法被調(diào)用時(shí),會(huì)把名稱為“myapp.greet.count”的計(jì)數(shù)器的值加 1。也就是當(dāng)用戶每次訪問“/greet”時(shí),該計(jì)算器就會(huì)被加 1。除了 CounterService 之外,還可以使用 GaugeService 來記錄絕對(duì)值。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java如何獲取List<String>中的String詳解
工作了這么長(zhǎng)時(shí)間了,一直沒有記錄的習(xí)慣,以至于導(dǎo)致我即便是查過的東西總會(huì)忘記,下面這篇文章主要給大家介紹了關(guān)于Java如何獲取List<String>中String的相關(guān)資料,需要的朋友可以參考下2022-02-02java中HashMap.values()轉(zhuǎn)為ArrayList()問題
這篇文章主要介紹了java中HashMap.values()轉(zhuǎn)為ArrayList()問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03spring cloud zuul 與 sentinel的結(jié)合使用操作
這篇文章主要介紹了spring cloud zuul 與 sentinel 的結(jié)合使用操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Spring MVC之WebApplicationContext_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Spring MVC之WebApplicationContext的相關(guān)資料,需要的朋友可以參考下2017-08-08Java使用OCR技術(shù)識(shí)別驗(yàn)證碼實(shí)現(xiàn)自動(dòng)化登陸方法
在本篇文章里小編給大家分享的是關(guān)于Java 如何使用 OCR 技術(shù)識(shí)別驗(yàn)證碼實(shí)現(xiàn)自動(dòng)化登陸的相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的朋友們學(xué)習(xí)下。2019-08-08Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例
這篇文章主要介紹了Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例,Zookeeper?分布式鎖應(yīng)用了其?臨時(shí)順序節(jié)點(diǎn)?的特性,在Zookeeper中創(chuàng)建一個(gè)持久節(jié)點(diǎn)ParentLock,當(dāng)?shù)谝粋€(gè)客戶端要獲取鎖時(shí),在ParentLock節(jié)點(diǎn)下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn),需要的朋友可以參考下2023-12-12淺談Maven安裝及環(huán)境配置出錯(cuò)的解決辦法
這篇文章主要介紹了淺談Maven安裝及環(huán)境配置出錯(cuò)的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09