第三十八章:基于SpringBoot架構(gòu)使用Profile完成打包環(huán)境分離

在中大型企業(yè)項(xiàng)目開發(fā)中,環(huán)境分離是必不可少的一步,然而現(xiàn)在的開發(fā)人員也只是有這個(gè)概念,還是有很多項(xiàng)目采用普通的方式,每次打包發(fā)布部署的時(shí)候改動(dòng)一大堆的配置文件,有一個(gè)地方忘記改就相當(dāng)于白更新了一次系統(tǒng),這種修改配置文件完成環(huán)境更換的方式給我們帶來了很多的困擾,浪費(fèi)了我們很多寶貴的時(shí)間!早在Spring 3.1版本就已經(jīng)為我們提供了環(huán)境分離的相關(guān)注解配置方式,不過在傳統(tǒng)的Spring項(xiàng)目中配置Profile確實(shí)有點(diǎn)麻煩,在Spring版本的不斷更新直到后來SpringBoot成長起來后Profile已經(jīng)能夠很好支持項(xiàng)目配置環(huán)境分離。

免費(fèi)教程專題

恒宇少年在博客整理三套免費(fèi)學(xué)習(xí)教程專題,由于文章偏多特意添加了閱讀指南,新文章以及之前的文章都會(huì)在專題內(nèi)陸續(xù)填充,希望可以幫助大家解惑更多知識(shí)點(diǎn)。

本章目標(biāo)

基于SpringBoot平臺(tái)完成簡單的數(shù)據(jù)庫環(huán)境操作分離,根據(jù)激活不同的Profile完成不同的數(shù)據(jù)庫操作。

SpringBoot 企業(yè)級核心技術(shù)學(xué)習(xí)專題


專題 專題名稱 專題描述
001 Spring Boot 核心技術(shù) 講解SpringBoot一些企業(yè)級層面的核心組件
002 Spring Boot 核心技術(shù)章節(jié)源碼 Spring Boot 核心技術(shù)簡書每一篇文章碼云對應(yīng)源碼
003 Spring Cloud 核心技術(shù) 對Spring Cloud核心技術(shù)全面講解
004 Spring Cloud 核心技術(shù)章節(jié)源碼 Spring Cloud 核心技術(shù)簡書每一篇文章對應(yīng)源碼
005 QueryDSL 核心技術(shù) 全面講解QueryDSL核心技術(shù)以及基于SpringBoot整合SpringDataJPA
006 SpringDataJPA 核心技術(shù) 全面講解SpringDataJPA核心技術(shù)
007 SpringBoot核心技術(shù)學(xué)習(xí)目錄 SpringBoot系統(tǒng)的學(xué)習(xí)目錄,敬請關(guān)注點(diǎn)贊??!!

構(gòu)建項(xiàng)目

使用Idea工具創(chuàng)建一個(gè)SpringBoot項(xiàng)目,目前SpringBoot的版本已經(jīng)更新至1.5.8,我們采用最新版本來完成本章內(nèi)容,添加相關(guān)JPA、MySQLDruid、Lombok、WebFastJson等,pom.xml依賴相關(guān)配置如下所示:

....省略部分配置
<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>
....省略部分配置

配置數(shù)據(jù)庫

我們創(chuàng)建三個(gè)數(shù)據(jù)庫分別是project_prod => 線上環(huán)境數(shù)據(jù)庫、project_dev=>開發(fā)環(huán)境數(shù)據(jù)庫、project_beta=>線上測試環(huán)境數(shù)據(jù)庫,這樣我們在切換Profile時(shí)可以很好的區(qū)分環(huán)境,下面我們創(chuàng)建一張用戶基本信息表,SQL如下:

-- ----------------------------
-- 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分別在三個(gè)數(shù)據(jù)庫內(nèi)分別執(zhí)行一次,保證我們數(shù)據(jù)結(jié)構(gòu)環(huán)境一致,然后對應(yīng)數(shù)據(jù)庫分別插入數(shù)據(jù),如下:

INSERT INTO `system_user_info` VALUES ('1', '線上測試環(huán)境用戶', 'beta', 'beta_password');
INSERT INTO `system_user_info` VALUES ('1', '開發(fā)環(huán)境用戶', 'dev', 'dev_password');
INSERT INTO `system_user_info` VALUES ('1', '正式環(huán)境用戶', 'prod', 'prod_password');

這樣我們就可以區(qū)分項(xiàng)目正在訪問的具體環(huán)境。

創(chuàng)建Entity

對應(yīng)system_user_info數(shù)據(jù)表創(chuàng)建一個(gè)數(shù)據(jù)實(shí)體,如下所示:

package com.yuqiyu.chapter38.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * 用戶基本信息實(shí)體
 * ========================
 * 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;
}

接下來我們?yōu)樯厦娴膶?shí)體創(chuàng)建一個(gè)JPA接口,繼承JpaRepository<T,PK>接口完成Jpa掃描自動(dòng)代理實(shí)例的動(dòng)作。

創(chuàng)建JPA

SystemUserInfoJPA接口內(nèi)容如下所示:

package com.yuqiyu.chapter38.jpa;

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

/**
 * 系統(tǒng)用戶信息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環(huán)境

SpringBoot內(nèi)已經(jīng)為了約定好了Profile配置文件的命名規(guī)則,即:application-xxx.properties或者application-xxx.yml,我們只需要將對應(yīng)環(huán)境的配置文件放到resources目錄下即可,也就是classpath下,我們對應(yīng)我們的數(shù)據(jù)庫環(huán)境編寫三個(gè)不同的配置文件。

application-dev.yml

根據(jù)我們與SpringBoot的約定在application-dev.xml配置文件內(nèi)配置的都是開發(fā)環(huán)境信息,里面包含了開發(fā)環(huán)境數(shù)據(jù)源配置信息,當(dāng)然在實(shí)際的項(xiàng)目開發(fā)過程中配置信息可以任意約定。配置內(nèi)容如下所示:

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
    #最大活躍數(shù)
    maxActive: 20
    #初始化數(shù)量
    initialSize: 1
    #最大連接等待超時(shí)時(shí)間
    maxWait: 60000
    #打開PSCache,并且指定每個(gè)連接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
    #配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql將無法統(tǒng)計(jì),'wall'用于防火墻
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true

在上面代碼中可以看到,我們連接了本地的project_dev數(shù)據(jù)庫來作為開發(fā)環(huán)境的訪問數(shù)據(jù)源。

application-beta.yml

application-beta.yml配置文件就是我們與SpringBoot約定的線上測試環(huán)境,在我們實(shí)際的開發(fā)過程中線上測試環(huán)境肯定與開發(fā)環(huán)境不是同一個(gè)數(shù)據(jù)庫,這時(shí)我們將application-dev.yml配置文件復(fù)制一份,修改下數(shù)據(jù)庫鏈接信息即可,如果你的application-beta.yml還存在其他的配置,不要忘記修改成相關(guān)的環(huán)境配置。配置信息如下所示:

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
    #最大活躍數(shù)
    maxActive: 20
    #初始化數(shù)量
    initialSize: 1
    #最大連接等待超時(shí)時(shí)間
    maxWait: 60000
    #打開PSCache,并且指定每個(gè)連接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
    #配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql將無法統(tǒng)計(jì),'wall'用于防火墻
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true

application-prod.yml

application-prod.yml配置文件則是我們與SpringBoot約定的線上生產(chǎn)環(huán)境的配置文件,里面保存的全部都是正式環(huán)境配置信息,一般在開發(fā)過程中線上環(huán)境配置信息是不需要變動(dòng)的,配置完成后就只是在打包部署時(shí)修改spring.profiles.activeprod就可以了(注:根據(jù)實(shí)際項(xiàng)目的線上環(huán)境的配置約定名稱而定)。配置信息如下所示:

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
    #最大活躍數(shù)
    maxActive: 20
    #初始化數(shù)量
    initialSize: 1
    #最大連接等待超時(shí)時(shí)間
    maxWait: 60000
    #打開PSCache,并且指定每個(gè)連接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
    #配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql將無法統(tǒng)計(jì),'wall'用于防火墻
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true

為了方便我們測試,我在本地創(chuàng)建的三個(gè)數(shù)據(jù)庫,當(dāng)然實(shí)際項(xiàng)目開發(fā)中你可能是數(shù)據(jù)庫讀寫分離環(huán)境,也可能是多臺(tái)服務(wù)器完全分離的環(huán)境,只需要針對不同的約定修改相對應(yīng)的配置信息就可以了。

測試Profile

下面我們來創(chuàng)建一個(gè)控制器,使用我們上面已經(jīng)創(chuàng)建好的SystemUserInfoJPA完成數(shù)據(jù)庫的讀取動(dòng)作。

創(chuàng)建測試控制器

在上面我們?yōu)槊恳粋€(gè)環(huán)境的數(shù)據(jù)庫表````都初始化了一條數(shù)據(jù),那么我就來編寫一個(gè)讀取數(shù)據(jù)庫的請求方法,根據(jù)我們修改的spring.profiles.active配置文件內(nèi)容,是否可以改變請求數(shù)據(jù)庫。控制器代碼如下所示:

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環(huán)境
 * ========================
 * 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);
    }
}

在控制器內(nèi),我們通過訪問/user/{id}請求地址,就可以獲取到用戶的基本信息在頁面上通過Json字符串的形式展示,下面我們就來配置需要激活的Profile,訪問該請求地址查看輸出效果。

激活Profile

由于激活Profile的配置不屬于任何一個(gè)環(huán)境分離的配置文件,所以我們不可以在dev、beta、prod任意一個(gè)配置文件內(nèi)添加激活配置,我們知道application.ymlSpringBoot約定的配置文件,那么我就在該配置文件內(nèi)配置環(huán)境分離激活,配置如下所示:

spring:
  profiles:
    active: dev

我們在application.yml配置文件內(nèi)激活了dev開發(fā)環(huán)境,下面我們啟動(dòng)項(xiàng)目訪問請求路徑http://127.0.0.1:8080/user/1來查看界面輸出內(nèi)容,如下所示:

{
  id: 1,
  nickName: "開發(fā)環(huán)境用戶",
  loginName: "dev",
  loginPassword: "dev_password"
}

正如我們所料,正確的輸出了開發(fā)環(huán)境的用戶信息,那我們修改下激活環(huán)境是不是也會(huì)編程相對應(yīng)的輸出呢?下面我們來證實(shí)這一點(diǎn),修改激活環(huán)境為線上開發(fā)環(huán)境:

spring:
  profiles:
    active: beta

重啟項(xiàng)目,再次訪問http://127.0.0.1:8080/user/1請求路徑,界面輸出內(nèi)容如下所示:

{
  id: 1,
  nickName: "線上測試環(huán)境用戶",
  loginName: "beta",
  loginPassword: "beta_password"
}

可以看到已經(jīng)改成我們需要的效果,我們只是激活了不同的環(huán)境,就輕松實(shí)現(xiàn)了環(huán)境的分離,正式環(huán)境也是一樣的,下面我們來激活正式環(huán)境完成Package打包。

正式環(huán)境打包

有很多項(xiàng)目在上線打包部署的時(shí)候需要改動(dòng)很多配置文件,訪問地址等等配置信息,那我們采用了Profile后打包該怎么處理呢?
答案是:省心。
第一步我們只需要修改激活環(huán)境改成線上環(huán)境即可,如下所示:

spring:
  profiles:
    active: prod

第二步運(yùn)行打包命令,等待打包完成。本章是采用的Idea開發(fā)工具完成的打包,Idea工具為Maven自帶了命令窗口,只需要選擇不同的命令雙擊就可以執(zhí)行,如下圖1所示:

圖1

我們雙擊package命令,等待打包完成就可以了,完成后jar或者war會(huì)在target目錄生成,下面我們使用Windows CMD命令行進(jìn)入jar存在的目錄,執(zhí)行命令之前需要關(guān)掉Idea啟動(dòng)的項(xiàng)目:

java -jar chapter38-0.0.1-SNAPSHOT.jar

啟動(dòng)完成后,我們再次訪問請求地址http://127.0.0.1:8080/user/1,查看界面輸出內(nèi)容:

{
  id: 1,
  nickName: "正式環(huán)境用戶",
  loginName: "prod",
  loginPassword: "prod_password"
}

正確輸出了prod正式環(huán)境的用戶信息。

總結(jié)

Profile的加入可以讓很多運(yùn)維實(shí)施人員減少了太多的煩惱,在幾年前部署完全都是采用修改配置文件,如果修改出錯(cuò)還會(huì)導(dǎo)致返工,既浪費(fèi)了時(shí)間也浪費(fèi)了精力。

建議大家項(xiàng)目初期盡可能的采用環(huán)境分離的方式進(jìn)行構(gòu)建項(xiàng)目!

本章代碼已經(jīng)上傳到碼云:
SpringBoot配套源碼地址:https://gitee.com/hengboy/spring-boot-chapter
SpringCloud配套源碼地址:https://gitee.com/hengboy/spring-cloud-chapter

作者個(gè)人 博客
使用開源框架 ApiBoot 助你成為Api接口服務(wù)架構(gòu)師

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容