前面已經(jīng)完成了一個(gè)簡(jiǎn)單的項(xiàng)目,項(xiàng)目開發(fā)完成后,進(jìn)入測(cè)試,然后發(fā)布到生產(chǎn)環(huán)境。這章的目標(biāo)就是一次編譯,就可以部署到測(cè)試環(huán)境和生產(chǎn)環(huán)境。
SpringBoot項(xiàng)目編譯
調(diào)整項(xiàng)目
首先調(diào)整一下HelloApplication類中的"/hello" api移到com.biboheart.demos.api包中(有點(diǎn)強(qiáng)迫癥,不喜歡在入中類中放API)。
在com.biboheart.demos.api包中創(chuàng)建一個(gè)類"HelloController"
內(nèi)容如下:
package com.biboheart.demos.api;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Value("${custom.name:default}")
private String customName;
@RequestMapping(value = "/hello")
public String hello(String name) {
System.out.println("配置文件自定義配置的值是: " + customName);
return "hello " + name + " with " + customName;
}
}
原來(lái)HelloApplication的內(nèi)容
package com.biboheart.demos;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class HelloApplication {
@Value("${custom.name:default}")
private String customName;
public static void main( String[] args ) {
SpringApplication.run(HelloApplication.class, args);
}
@RequestMapping(value = "/hello")
public String hello(String name) {
System.out.println("配置文件自定義配置的值是: " + customName);
return "hello " + name;
}
}
改為
package com.biboheart.demos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloApplication {
public static void main( String[] args ) {
SpringApplication.run(HelloApplication.class, args);
}
}
啟動(dòng)項(xiàng)目,看看當(dāng)前效果

控制臺(tái)打印

回顧
回顧下這個(gè)API,代碼
@RestController
public class HelloController {
@Value("${custom.name:default}")
private String customName;
@RequestMapping(value = "/hello")
public String hello(String name) {
System.out.println("配置文件自定義配置的值是: " + customName);
return "hello " + name + " with " + customName;
}
}
通過(guò)@Value,從配置文件中獲取custom.name的值,如果沒有配置這個(gè)值,則值為default。
當(dāng)訪問(wèn)api “/hello”是,控制臺(tái)打印這個(gè)值,返回"hello" + [傳入?yún)?shù)的值] + " with " + [配置的值]
配置文件是這樣的
server:
port: 80
custom:
name: bhhello
停止運(yùn)行,改下配置文件
server:
port: 80
custom:
name: bhhello-app
運(yùn)行項(xiàng)目,查看訪問(wèn)結(jié)果


當(dāng)前目錄

編譯項(xiàng)目
完成項(xiàng)目之后需要編譯(打包)后發(fā)布。點(diǎn)擊IDEA下方的“Terminal”,打開命令行窗口


輸入
cd bhhello
進(jìn)入項(xiàng)目目錄

執(zhí)行maven打包命令
mvn package

顯示"BUILD SUCCESS" 表示打包成功,可以在target目錄中看到編譯完成的jar文件。

部署項(xiàng)目
項(xiàng)目編譯完成后。開始部署項(xiàng)目。首先部署到測(cè)試服務(wù)器,供測(cè)試人員測(cè)試。SpringBoot的項(xiàng)目適合部署到linux服務(wù)器,windows中也是可以運(yùn)行這個(gè)項(xiàng)目,但是做系統(tǒng)服務(wù)似乎比較麻煩。我們這里不講windows環(huán)境的部署,只講linux環(huán)境中的部署。這個(gè)環(huán)境要自行想辦法了,可以安裝虛擬機(jī)(前面已經(jīng)安裝過(guò)docker,那時(shí)候已經(jīng)安裝了虛擬機(jī))。我就遠(yuǎn)程到自己的阿里云服務(wù)器部署。
在windows中執(zhí)行項(xiàng)目
打開cmd,進(jìn)入target目錄。

執(zhí)行
java -jar bhhello-1.0.0-SNAPSHOT.jar
出錯(cuò)了,顯示bhhello-1.0.0-SNAPSHOT.jar中沒有主清單屬性

可以進(jìn)入項(xiàng)目的pom.xml文件,加上一個(gè)spring-boot-maven-plugin插件。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
這里我們不加在本項(xiàng)目的pom.xml文件中,我們加在bhparent(即bhhello項(xiàng)目的父項(xiàng)目)的pom.xml中。

加這里的好處,后面開發(fā)的子項(xiàng)目中都不需要再加這個(gè)plugin。
下面是/bhparent/pom.xml文件的內(nèi)容
<?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>com.biboheart.demos</groupId>
<artifactId>bhparent</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<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-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- 我常用的一些工具寫在這個(gè)包里,源碼地址:https://gitee.com/biboheart/brick 已經(jīng)在maven中央倉(cāng)庫(kù)發(fā)布 -->
<dependency>
<groupId>com.biboheart</groupId>
<artifactId>bh-brick</artifactId>
<version>0.0.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
<modules>
<module>bhhello</module>
</modules>
</project>
重新編譯項(xiàng)目

編譯完成后,再次執(zhí)行

啟動(dòng)完成,訪問(wèn)api

控制臺(tái)中打印出相應(yīng)字符串

發(fā)布到服務(wù)器
服務(wù)器需要安裝java。
用xshell連接服務(wù)器,打開服務(wù)器操作界面。服務(wù)器是centos7的環(huán)境。域名www.blueheart.cn已經(jīng)解析到這臺(tái)服務(wù)器。后面的訪問(wèn)會(huì)通過(guò)域名訪問(wèn)。

進(jìn)入/opt目錄,把項(xiàng)目部署到這個(gè)目錄中。

上傳文件到/opt,我用xftp上傳

ls命令查看目錄中的文件

改下文件名稱,這個(gè)名稱有點(diǎn)不方便使用,而且在升級(jí)版本之后,版本號(hào)變化會(huì)導(dǎo)致文件名變化,會(huì)涉及到其它文件的修改。
執(zhí)行命令mv改文件,把文件名改成bhhello.jar
mv bhhello-1.0.0-SNAPSHOT.jar bhhello.jar

把bhhello.jar改成可執(zhí)行文件
chmod 500 bhhello.jar

啟動(dòng)項(xiàng)目

也可以用/opt/bhhello.jar啟動(dòng)項(xiàng)目

訪問(wèn)api


結(jié)果正確。只是這樣還不夠,現(xiàn)在如果把xshell窗口關(guān)閉,或者中止當(dāng)前執(zhí)行。服務(wù)就會(huì)停止。我們需要給它放到后臺(tái)運(yùn)行。我的方案是配置成系統(tǒng)服務(wù)。
配置centos系統(tǒng)服務(wù)
進(jìn)入目錄/etc/systemd/system,執(zhí)行vi bhhello.service編輯文件bhhello.service
[Unit]
Description=bh hello server
After=syslog.target
[Service]
User=root
ExecStart=/opt/bhhello.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
按"esc"鍵退出編輯模式,輸入":wq"保存退出。
執(zhí)行命令systemctl start bhhello啟動(dòng)項(xiàng)目
執(zhí)行命令systemctl status bhhello -l 查看服務(wù)狀態(tài)

看到服務(wù)正在啟動(dòng)。訪問(wèn)api結(jié)果相同。

如果需要開機(jī)自動(dòng)啟動(dòng)服務(wù),只需運(yùn)行命令systemctl enable bhhello

多環(huán)境配置
上面已經(jīng)完成項(xiàng)目部署。從開發(fā)環(huán)境搭建到編碼到編譯發(fā)布,基本走通。
假設(shè)現(xiàn)在項(xiàng)目是部署在測(cè)試環(huán)境中,測(cè)試通過(guò)后,部署到生產(chǎn)環(huán)境中。對(duì)于這個(gè)小項(xiàng)目沒什么問(wèn)題,在生產(chǎn)環(huán)境中走一遍上面的部署流程就可以。如果測(cè)試環(huán)境中的一些參數(shù)與生產(chǎn)環(huán)境中不一樣的話呢,假如測(cè)試連接的數(shù)據(jù)庫(kù)與生產(chǎn)環(huán)境中連接的數(shù)據(jù)庫(kù)是不同一個(gè)。那么就需要修改配置文件,再編譯,再發(fā)布到生產(chǎn)環(huán)境。這樣就不合適了,重新編譯后就會(huì)有些不確定因素存在。說(shuō)得嚴(yán)重了點(diǎn),控制好可能也不會(huì)出大問(wèn)題??倸w是不如一次編譯,同一個(gè)文件在不同環(huán)境中運(yùn)行。
spring boot提供了多環(huán)境配置的解決方案。下面來(lái)體驗(yàn)下。
解決方案
SpringBoot可以有多個(gè)配置文件,根據(jù)不同的環(huán)境選擇不同的配置文件??梢园迅鳝h(huán)境相同的配置項(xiàng)配置在一個(gè)文件中同,區(qū)別的項(xiàng)分多個(gè)文件配置。在運(yùn)行項(xiàng)目的時(shí)候傳參選擇環(huán)境。這樣描述比較難以理解。下面實(shí)踐下。
修改配置文件
原來(lái)的配置文件修改下,增加spring.profiles.active:dev配置項(xiàng)和值。dev表示開發(fā)環(huán)境,這個(gè)值是自己定義的。這里這樣定義
dev: 開發(fā)環(huán)境
test: 測(cè)試環(huán)境
prod: 生產(chǎn)環(huán)境
application.yml文件結(jié)果
server:
port: 80
spring:
profiles:
active: dev
custom:
name: bhhello-app
在src/main/resources目錄中,即application.yml同目錄中創(chuàng)建三個(gè)文件application-dev.yml,application-test.yml,application-prod.yml 分別是開發(fā)環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境的配置。把通用的配置寫在application.yml中。
這里只是做一個(gè)演示,用每個(gè)環(huán)境中的custom.name的值的變化來(lái)演示配置的變化。
application-dev.yml的內(nèi)容
custom:
name: bhhello-app-dev
application-test.yml的內(nèi)容
custom:
name: bhhello-app-test
application-prod.yml的內(nèi)容
custom:
name: bhhello-app-prod
目錄結(jié)構(gòu)如下

現(xiàn)在我們?cè)陂_發(fā)環(huán)境中(IDEA)中啟動(dòng)項(xiàng)目

控制臺(tái)中會(huì)打印出當(dāng)前執(zhí)行的配置環(huán)境
訪問(wèn)下api,因?yàn)檫@里有4個(gè)yml配置文件,打印的結(jié)果會(huì)是哪個(gè)呢?

打印的是bhhello-app-dev。
如果改一下application.yml中spring.profiles.active的值如下
server:
port: 80
spring:
profiles:
active: test
custom:
name: bhhello-app
重啟服務(wù)后,再訪問(wèn)。訪問(wèn)結(jié)果就會(huì)變化成application-test.yml中的配置。


編譯部署
這幾個(gè)配置文件都是打包在.jar文件中的,如果不能解決部署的時(shí)候改變spring.profiles.active的值,就達(dá)不到一次編譯,根據(jù)環(huán)境不同配置的需求。下面先把spring.profiles.active的值改回dev,開發(fā)調(diào)試的時(shí)候都是這個(gè)值。這個(gè)值的變化需要在部署的時(shí)候不重新編譯的情況下變化。
執(zhí)行mvn package編譯打包成.jar

先停止linux服務(wù)器中,前面運(yùn)行的bhhello服務(wù)。使用命令systemctl stop bhhello停止服務(wù),可以查看一下狀態(tài)是否停止。

上傳剛剛打包的bhhello-1.0.0-SNAPSHOT.jar文件到服務(wù)器的/opt目錄中,與前面一致。這里有個(gè)更便捷的方法,先在本地修改好文件名再覆蓋上傳,就不用再執(zhí)行chmod 500 命令了。


先用命令行執(zhí)行試試,/opt/bhhello.jar??梢钥吹浆F(xiàn)在選擇的是dev的配置。

訪問(wèn)api驗(yàn)證下。

修改環(huán)境配置
按鍵盤Ctrl+c停止程序。
如果要修改配置文件中的一個(gè)值,可以在命令后跟上--[屬性]=[值],是命令后面空格,再跟上兩個(gè)“-”,接上屬性=值。這里需要修改spring.profiles.active的值為test,這是部署測(cè)試環(huán)境的。
執(zhí)行命令/opt/bhhello.jar --spring.profiles.active=test

訪問(wèn)驗(yàn)證一下

這樣,在不重新編譯的情況下改變了配置值。
接下來(lái),修改服務(wù)文件,因?yàn)樽罱K的啟動(dòng)是通過(guò)服務(wù)啟動(dòng)的。
進(jìn)入目錄/etc/systemd/system,執(zhí)行命令vi bhhello.service,進(jìn)入查看文件內(nèi)容,按鍵盤i鍵進(jìn)入編輯模式,修改如下
[Unit]
Description=bh hello server
After=syslog.target
[Service]
User=root
ExecStart=/opt/bhhello.jar --spring.profiles.active=test
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
保存文件,執(zhí)行命令systemctl daemon-reload刷新服務(wù)。
執(zhí)行systemctl start bhhello啟動(dòng)服務(wù),執(zhí)行systemctl status bhhello -l查看服務(wù)狀態(tài)

訪問(wèn)api驗(yàn)證結(jié)果

結(jié)果如預(yù)期一致。
后記
部署到生產(chǎn)環(huán)境的話,同上面測(cè)試文件的部署流程。把.service文件中的test改成prod。就選擇了生產(chǎn)環(huán)境的配置值。還可以更多環(huán)境的個(gè)性化配置。只要spring.profiles.active的值與配置文件名配置,application-[spring.profiles.active].yml。如增加一個(gè)配置文件application-hhh.yml,部署的時(shí)候命令中跟上--spring.profiles.active=hhh ,服務(wù)就會(huì)根據(jù)application-hhh.yml中的配置值執(zhí)行。