第三十八章:基於SpringBoot架構使用Profile完成打包環境分離

在中大型企業項目開發中,環境分離是必不可少的一步,然而如今的開發人員也只是有這個概念,仍是有不少項目採用普通的方式,每次打包發佈部署的時候改動一大堆的配置文件,有一個地方忘記改就至關於白更新了一次系統,這種修改配置文件完成環境更換的方式給咱們帶來了不少的困擾,浪費了咱們不少寶貴的時間!早在Spring 3.1版本就已經爲咱們提供了環境分離的相關注解配置方式,不過在傳統的Spring項目中配置Profile確實有點麻煩,在Spring版本的不斷更新直到後來SpringBoot成長起來後Profile已經可以很好支持項目配置環境分離。java

本章目標

基於SpringBoot平臺完成簡單的數據庫環境操做分離,根據激活不一樣的Profile完成不一樣的數據庫操做。mysql

構建項目

使用Idea工具建立一個SpringBoot項目,目前SpringBoot的版本已經更新至1.5.8,咱們採用最新版原本完成本章內容,添加相關JPAMySQLDruidLombokWebFastJson等,pom.xml依賴相關配置以下所示:git

....省略部分配置
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入druid最新maven依賴-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.39</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
....省略部分配置複製代碼

配置數據庫

咱們建立三個數據庫分別是project_prod => 線上環境數據庫、project_dev=>開發環境數據庫、project_beta=>線上測試環境數據庫,這樣咱們在切換Profile時能夠很好的區分環境,下面咱們建立一張用戶基本信息表,SQL以下:web

-- ----------------------------
-- Table structure for system_user_info
-- ----------------------------
DROP TABLE IF EXISTS `system_user_info`;
CREATE TABLE `system_user_info` (
  `SUI_ID` int(11) NOT NULL AUTO_INCREMENT,
  `SUI_NICK_NAME` varchar(50) DEFAULT NULL,
  `SUI_LOGIN_NAME` varchar(30) DEFAULT NULL,
  `SUI_LOGIN_PASSWORD` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`SUI_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;複製代碼

將上面SQL分別在三個數據庫內分別執行一次,保證咱們數據結構環境一致,而後對應數據庫分別插入數據,以下:spring

INSERT INTO `system_user_info` VALUES ('1', '線上測試環境用戶', 'beta', 'beta_password');
INSERT INTO `system_user_info` VALUES ('1', '開發環境用戶', 'dev', 'dev_password');
INSERT INTO `system_user_info` VALUES ('1', '正式環境用戶', 'prod', 'prod_password');複製代碼

這樣咱們就能夠區分項目正在訪問的具體環境。sql

建立Entity

對應system_user_info數據表建立一個數據實體,以下所示:數據庫

package com.yuqiyu.chapter38.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * 用戶基本信息實體
 * ========================
 * Created with IntelliJ IDEA.
 * User:恆宇少年
 * Date:2017/10/29
 * Time:08:25
 * 碼雲:http://git.oschina.net/jnyqy
 * ========================
 */
@Entity
@Table(name = "system_user_info")
@Data
public class SystemUserInfoEntity
{
    /**
     * 主鍵
     */
    @Column(name = "SUI_ID")
    @GeneratedValue
    @Id
    private Integer id;
    /**
     * 暱稱
     */
    @Column(name = "SUI_NICK_NAME")
    private String nickName;
    /**
     * 登陸名
     */
    @Column(name = "SUI_LOGIN_NAME")
    private String loginName;
    /**
     * 登陸密碼
     */
    @Column(name = "SUI_LOGIN_PASSWORD")
    private String loginPassword;
}複製代碼

接下來咱們爲上面的實體建立一個JPA接口,繼承JpaRepository<T,PK>接口完成Jpa掃描自動代理實例的動做。編程

建立JPA

SystemUserInfoJPA接口內容以下所示:json

package com.yuqiyu.chapter38.jpa;

import com.yuqiyu.chapter38.entity.SystemUserInfoEntity;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * 系統用戶信息jpa
 * ========================
 * Created with IntelliJ IDEA.
 * User:恆宇少年
 * Date:2017/10/29
 * Time:08:30
 * 碼雲:http://git.oschina.net/jnyqy
 * ========================
 */
public interface SystemUserInfoJPA
    extends JpaRepository<SystemUserInfoEntity,Integer>
{

}複製代碼

配置Profile環境

SpringBoot內已經爲了約定好了Profile配置文件的命名規則,即:application-xxx.properties或者application-xxx.yml,咱們只須要將對應環境的配置文件放到resources目錄下便可,也就是classpath下,咱們對應咱們的數據庫環境編寫三個不一樣的配置文件。bash

application-dev.yml

根據咱們與SpringBoot的約定在application-dev.xml配置文件內配置的都是開發環境信息,裏面包含了開發環境數據源配置信息,固然在實際的項目開發過程當中配置信息能夠任意約定。配置內容以下所示:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/project_dev?characterEncoding=utf8
    username: root
    password: 123456
    #最大活躍數
    maxActive: 20
    #初始化數量
    initialSize: 1
    #最大鏈接等待超時時間
    maxWait: 60000
    #打開PSCache,而且指定每一個鏈接PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    #經過connectionProperties屬性來打開mergeSql功能;慢SQL記錄
    #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 1 from dual
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    #配置監控統計攔截的filters,去掉後監控界面sql將沒法統計,'wall'用於防火牆
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true複製代碼

在上面代碼中能夠看到,咱們鏈接了本地的project_dev數據庫來做爲開發環境的訪問數據源。

application-beta.yml

application-beta.yml配置文件就是咱們與SpringBoot約定的線上測試環境,在咱們實際的開發過程當中線上測試環境確定與開發環境不是同一個數據庫,這時咱們將application-dev.yml配置文件複製一份,修改下數據庫連接信息便可,若是你的application-beta.yml還存在其餘的配置,不要忘記修改爲相關的環境配置。配置信息以下所示:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/project_beta?characterEncoding=utf8
    username: root
    password: 123456
    #最大活躍數
    maxActive: 20
    #初始化數量
    initialSize: 1
    #最大鏈接等待超時時間
    maxWait: 60000
    #打開PSCache,而且指定每一個鏈接PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    #經過connectionProperties屬性來打開mergeSql功能;慢SQL記錄
    #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 1 from dual
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    #配置監控統計攔截的filters,去掉後監控界面sql將沒法統計,'wall'用於防火牆
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true複製代碼

application-prod.yml

application-prod.yml配置文件則是咱們與SpringBoot約定的線上生產環境的配置文件,裏面保存的所有都是正式環境配置信息,通常在開發過程當中線上環境配置信息是不須要變更的,配置完成後就只是在打包部署時修改spring.profiles.activeprod就能夠了(注:根據實際項目的線上環境的配置約定名稱而定)。配置信息以下所示:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/project_prod?characterEncoding=utf8
    username: root
    password: 123456
    #最大活躍數
    maxActive: 20
    #初始化數量
    initialSize: 1
    #最大鏈接等待超時時間
    maxWait: 60000
    #打開PSCache,而且指定每一個鏈接PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    #經過connectionProperties屬性來打開mergeSql功能;慢SQL記錄
    #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 1 from dual
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    #配置監控統計攔截的filters,去掉後監控界面sql將沒法統計,'wall'用於防火牆
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true複製代碼

爲了方便咱們測試,我在本地建立的三個數據庫,固然實際項目開發中你多是數據庫讀寫分離環境,也多是多臺服務器徹底分離的環境,只須要針對不一樣的約定修改相對應的配置信息就能夠了。

#測試Profile

下面咱們來建立一個控制器,使用咱們上面已經建立好的SystemUserInfoJPA完成數據庫的讀取動做。

####建立測試控制器
在上面咱們爲每個環境的數據庫表``都初始化了一條數據,那麼我就來編寫一個讀取數據庫的請求方法,根據咱們修改的spring.profiles.active``配置文件內容,是否能夠改變請求數據庫。控制器代碼以下所示:

package com.yuqiyu.chapter38;

import com.yuqiyu.chapter38.entity.SystemUserInfoEntity;
import com.yuqiyu.chapter38.jpa.SystemUserInfoJPA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 測試profile環境
 * ========================
 * Created with IntelliJ IDEA.
 * User:恆宇少年
 * Date:2017/10/29
 * Time:09:02
 * 碼雲:http://git.oschina.net/jnyqy
 * ========================
 * @author hengyu
 */
@RestController
@RequestMapping(value = "/user")
public class IndexController
{
    @Autowired
    private SystemUserInfoJPA systemUserInfoJPA;

    /**
     * 查詢用戶詳情
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}")
    public SystemUserInfoEntity detail(@PathVariable("id") Integer id)
        throws Exception
    {
        return systemUserInfoJPA.findOne(id);
    }
}複製代碼

在控制器內,咱們經過訪問/user/{id}請求地址,就能夠獲取到用戶的基本信息在頁面上經過Json字符串的形式展現,下面咱們就來配置須要激活的Profile,訪問該請求地址查看輸出效果。

##激活Profile
因爲激活Profile的配置不屬於任何一個環境分離的配置文件,因此咱們不能夠在devbetaprod任意一個配置文件內添加激活配置,咱們知道application.ymlSpringBoot約定的配置文件,那麼我就在該配置文件內配置環境分離激活,配置以下所示:

spring:
  profiles:
    active: dev複製代碼

咱們在application.yml配置文件內激活了dev開發環境,下面咱們啓動項目訪問請求路徑http://127.0.0.1:8080/user/1來查看界面輸出內容,以下所示:

{
  id: 1,
  nickName: "開發環境用戶",
  loginName: "dev",
  loginPassword: "dev_password"
}複製代碼

正如咱們所料,正確的輸出了開發環境的用戶信息,那咱們修改下激活環境是否是也會編程相對應的輸出呢?下面咱們來證明這一點,修改激活環境爲線上開發環境:

spring:
  profiles:
    active: beta複製代碼

重啓項目,再次訪問http://127.0.0.1:8080/user/1請求路徑,界面輸出內容以下所示:

{
  id: 1,
  nickName: "線上測試環境用戶",
  loginName: "beta",
  loginPassword: "beta_password"
}複製代碼

能夠看到已經改爲咱們須要的效果,咱們只是激活了不一樣的環境,就輕鬆實現了環境的分離,正式環境也是同樣的,下面咱們來激活正式環境完成Package打包。

##正式環境打包
有不少項目在上線打包部署的時候須要改動不少配置文件,訪問地址等等配置信息,那咱們採用了Profile後打包該怎麼處理呢?
答案是:省心。
第一步咱們只須要修改激活環境改爲線上環境便可,以下所示:

spring:
  profiles:
    active: prod複製代碼

第二步運行打包命令,等待打包完成。本章是採用的Idea開發工具完成的打包,Idea工具爲Maven自帶了命令窗口,只須要選擇不一樣的命令雙擊就能夠執行,以下圖1所示:

圖1
圖1

咱們雙擊 package命令,等待打包完成就能夠了,完成後 jar或者 war會在 target目錄生成,下面咱們使用 Windows CMD命令行進入 jar存在的目錄,執行命令以前須要關掉 Idea啓動的項目:

java -jar chapter38-0.0.1-SNAPSHOT.jar複製代碼

啓動完成後,咱們再次訪問請求地址http://127.0.0.1:8080/user/1,查看界面輸出內容:

{
  id: 1,
  nickName: "正式環境用戶",
  loginName: "prod",
  loginPassword: "prod_password"
}複製代碼

正確輸出了prod正式環境的用戶信息。

#總結
Profile的加入可讓不少運維實施人員減小了太多的煩惱,在幾年前部署徹底都是採用修改配置文件,若是修改出錯還會致使返工,既浪費了時間也浪費了精力。

建議你們項目初期儘量的採用環境分離的方式進行構建項目!

本章代碼已經上傳到碼雲:
SpringBoot配套源碼地址:gitee.com/hengboy/spr…
SpringCloud配套源碼地址:gitee.com/hengboy/spr…
SpringBoot相關係列文章請訪問:目錄:SpringBoot學習目錄
QueryDSL相關係列文章請訪問:QueryDSL通用查詢框架學習目錄
SpringDataJPA相關係列文章請訪問:目錄:SpringDataJPA學習目錄
感謝閱讀!
歡迎加入QQ技術交流羣,共同進步。

QQ技術交流羣
QQ技術交流羣
相關文章
相關標籤/搜索