Chapter 38: Using Profile to Complete Packaging Environment Separation Based on SpringBoot Architecture

In the development of medium and large-scale enterprise projects, environment separation is an essential step. However, today's developers only have this concept. There are still many projects that use ordinary methods, changing a lot of configuration each time they are packaged, released and deployed. If you forget to change one part of the file, it is equivalent to updating the system once. This way of modifying the configuration file to complete the environment replacement has brought us a lot of trouble and wasted a lot of our precious time! As early as the Spring 3.1version, it has provided us with the relevant understanding configuration method of environment separation, but the configuration in the traditional Spring project is Profileindeed a bit troublesome. After Springthe continuous update of the version, it has been able to support the separation of the project configuration environment well SpringBootafter it grows up .Profile

Objectives of this chapter

Based on SpringBootthe platform, it completes simple database environment operation separation, and Profilecompletes different database operations according to different activations.

SpringBoot enterprise-level core technology learning topic

Topic Topic name Thematic description
001 Spring Boot core technology Explain some core components of SpringBoot at the enterprise level
002 Spring Boot core technology chapter source code Each article in the Spring Boot core technology brief book corresponds to the source code of the code cloud
003 Spring Cloud core technology Comprehensive explanation of the core technologies of Spring Cloud
004 Spring Cloud core technology chapter source code Each article in the Spring Cloud core technology brief book corresponds to the source code
005 QueryDSL core technology Comprehensively explain the core technology of QueryDSL and integrate SpringDataJPA based on SpringBoot
006 SpringDataJPA core technology Comprehensive explanation of the core technology of Spring Data JPA

Build the project

Use the Idea tool to create a SpringBootproject, SpringBootthe current version has been updated to 1.5.8, we use the latest version to complete the content of this chapter, add related JPA, MySQL, Druid, , Lombok, Web, FastJsonetc. The pom.xml dependency configuration is as follows:

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

configuration database

We create three databases: project_prod=> online environment database, project_dev=> development environment database, => online test environment database, so that we can distinguish the environment well when project_betaswitching , let's create a basic user information table, ProfileThe SQL is as follows:

-- ----------------------------
-- 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;

Execute the above SQL in the three databases respectively to ensure that our data structure environment is consistent, and then insert data into the corresponding databases, as follows:

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');

This way we can distinguish the specific environment the project is accessing.

Create Entity

Create a data entity corresponding to system_user_infothe data table as follows:

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;
}

Next, we create a JPA interface for the above entity, and inherit the JpaRepository<T,PK>interface to complete Jpathe action of scanning automatic proxy instances.

Create JPA

SystemUserInfoJPAThe content of the interface is as follows:

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>
{

}

Configure the Profile environment

InSpringBoot order to agree Profileon the naming rules of configuration files, that is: application-xxx.propertiesOr application-xxx.yml, we only need to put the configuration files of the corresponding environment in the resourcesdirectory, that is classpath, we write three different configuration files corresponding to our database environment. .

application-dev.yml

According to our SpringBootagreement application-dev.xml, all configuration files are development environment information, which contains development environment data source configuration information. Of course, in the actual project development process, the configuration information can be arbitrarily agreed. The configuration content is as follows:

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

As you can see in the above code, we connect the local project_devdatabase as the access data source for the development environment.

application-beta.yml

application-beta.ymlThe configuration file is SpringBootthe online test environment we agreed with. In our actual development process, the online test environment is definitely not the same database as the development environment. At this time, we application-dev.ymlcopy the configuration file and modify the database link information. If There are other configurations in yours application-beta.yml, don't forget to modify them to the relevant environment configuration. The configuration information is as follows:

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

The application-prod.ymlconfiguration file is the configuration file SpringBootof the online production environment that we agreed with. All the information stored in it is the official environment configuration information. Generally, the online environment configuration information does not need to be changed during the development process. After the configuration is completed, it is only packaged. It spring.profiles.activeis enough to modify prodit during deployment (Note: It depends on the configuration convention name of the online environment of the actual project). The configuration information is as follows:

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

In order to facilitate our testing, I created three databases locally. Of course, in the actual project development, you may be a database read-write separation environment, or an environment where multiple servers are completely separated. You only need to modify the corresponding configuration for different conventions. Information will do.

Test Profile

Next, let's create a controller that uses what we have created above to SystemUserInfoJPAcomplete the read action from the database.

Create a test controller

In the above, we configure the content of the database table spring.profiles.active for each environment ``都初始化了一条数据,那么我就来编写一个读取数据库的请求方法,根据我们修改的, whether the request database can be changed. The controller code is as follows:

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);
    }
}

In the controller, by accessing the /user/{id}request address, we can obtain the basic information of the user and display it in the form of a string on the page. JsonNext, we will configure the ones that need to be activated, Profileand visit the request address to view the output effect.

Activate Profile

Since the activated Profileconfiguration does not belong to any environment-separated configuration file, we cannot add the activation configuration to any devconfiguration betafile of , the configuration looks like this:prodapplication.ymlSpringBoot

spring:
  profiles:
    active: dev

We application.ymlactivated the development environment in the configuration file, devand now we start the project to access the request path http://127.0.0.1:8080/user/1 to view the interface output, as shown below:

{
  id: 1,
  nickName: "开发环境用户",
  loginName: "dev",
  loginPassword: "dev_password"
}

As we expected, the user information of the development environment is correctly output, so if we modify the activation environment, will it also program the corresponding output? Let's confirm this by modifying the activation environment to be an online development environment:

spring:
  profiles:
    active: beta

Restart the project and visit http://127.0.0.1:8080/user/1 to request the path again. The output of the interface is as follows:

{
  id: 1,
  nickName: "线上测试环境用户",
  loginName: "beta",
  loginPassword: "beta_password"
}

It can be seen that it has been changed to the effect we need. We just activate different environments, and we can easily separate the environments. The formal environment is the same. Let's activate the formal environment to complete the Packagepackaging.

Formal environment packaging

There are many projects that need to change a lot of configuration files, access addresses and other configuration information when they are packaged and deployed online. So what should we do with Profilepost-package?
The answer is: worry.
In the first step, we only need to modify the activation environment to an online environment, as shown below:

spring:
  profiles:
    active: prod

The second step is to run the packaging command and wait for the packaging to complete. This chapter is Ideathe packaging completed by the development tool. The Ideatool has its Mavenown command window. You only need to select a different command and double-click to execute it, as shown in Figure 1 below:

figure 1
We double-click packagethe command and wait for the packaging to complete. After completion, jarit warwill be targetgenerated in the directory. Next, we use the Windows CMDcommand line to enter the jarexisting directory. Before executing the command, we need to turn off Ideathe started project:

java -jar chapter38-0.0.1-SNAPSHOT.jar

After the startup is complete, we visit the request address http://127.0.0.1:8080/user/1 again to view the interface output:

{
  id: 1,
  nickName: "正式环境用户",
  loginName: "prod",
  loginPassword: "prod_password"
}

prodThe user information of the official environment is correctly output .

Summarize

ProfileThe addition of the config file can save many operation and maintenance personnel a lot of trouble. A few years ago, the deployment was completely by modifying the configuration file. If the modification is wrong, it will lead to rework, which is a waste of time and energy.

It is recommended that you use the environment separation method to build the project as much as possible in the early stage of the project!

The code of this chapter has been uploaded to the code cloud:
SpringBoot supporting source code address: https://gitee.com/hengboy/spring-boot-chapter
SpringCloud supporting source code address: https://gitee.com/hengboy/spring-cloud-chapter
SpringBoot related For the series of articles, please visit: Catalog: SpringBoot Learning Catalogue
QueryDSL related series of articles, please visit: QueryDSL General Query Framework Learning Catalog
Spring DataJPA-related series of articles, please visit: Catalog: Spring DataJPA Learning Catalog
Thank you for reading!
Welcome to join the QQ technical exchange group and make progress together.
QQ technical exchange group

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324771405&siteId=291194637