springboot中spring.profiles.active来引入多个properties文件 & Springboot获取容器中对象&springboot修改配置参数
1. 引入多个properties文件
很多时候,我们项目在开发环境和生成环境的环境配置是不一样的,例如,数据库配置,在开发的时候,我们一般用测试数据库,而在生产环境的时候,我们是用正式的数据,这时候,我们可以利用profile在不同的环境下配置用不同的配置文件或者不同的配置
spring boot允许你通过命名约定按照一定的格式(application-{profile}.properties)来定义多个配置文件,然后通过在application.properyies通过spring.profiles.active来具体激活一个或者多个配置文件,如果没有没有指定任何profile的配置文件的话,spring boot默认会启动application-default.properties。
profile的配置文件可以按照application.properties的放置位置一样,放于以下四个位置,
当前目录的 “/config”的子目录下
当前目录下
classpath根目录的“/config”包下
classpath的根目录下
常见的应用场景
1. 多环境切换
在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识,比如:
application-dev.properties:开发环境
application-test.properties:测试环境
application-prod.properties:生产环境
我们在总的applications.properties文件中可以通过下面切换:
spring.profiles.active=dev
2. 我们进行分模块开发的时候如下:
在dao层的模块中有下面配置: application-dao.properties
内容如下:
############################################################ # # Mybatis settings # ############################################################ #jiazai mybatis peizhiwenjian(**代表任意目录,*代表任意多个字符) mybatis.mapper-locations = classpath:mapper/**/*Mapper.xml mybatis.config-location = classpath:mybatis/SqlMapConfig.xml mybatis.type-aliases-package = cn.qlq.bean ############################################################ # # datasource settings # ############################################################ spring.datasource.driver-class-name= com.mysql.jdbc.Driver spring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8 spring.datasource.username = root spring.datasource.password = 123456
我们在总的applications.properties文件可以通过下面方式引入上面properties文件:
spring.profiles.active=dao
补充:代码也可以根据当前激活的环境来进行IOC生成对应的bean,如下:
(1)application.properties激活dev对象
spring.profiles.active=dev
(2)代码中根据激活的环境生成对象:
package com.zd.bx.service; public interface TestService { void test1(); }
dev环境的实现类:
package com.zd.bx.service; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; @Service @Profile("dev") public class DevTestService implements TestService { @Override public void test1() { System.out.println("test1 dev"); } }
prod环境的实现类:
package com.zd.bx.service; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; @Service @Profile("prod") public class ProdTestService implements TestService { @Override public void test1() { System.out.println("test1 prod"); } }
Profile注解可以接受一个数组,多个激活的环境。源码如下:
/** <a href="http://www.cpupk.com/decompiler">Eclipse Class Decompiler</a> plugin, Copyright (c) 2017 Chen Chao. */ package org.springframework.context.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.env.AbstractEnvironment; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Profiles; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(ProfileCondition.class) public @interface Profile { /** * The set of profiles for which the annotated component should be registered. */ String[] value(); }
补充:application.properties也可以引入多个properties文件,如下
# include激活多个包
#spring.profiles.include=dev
2.获取容器中对象
直接像在spring中获取会NPE异常。需要改装成下面工具类:
package cn.qs.utils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringBootUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringBootUtils.applicationContext = applicationContext; } public static Object getBean(String beanName) { return applicationContext.getBean(beanName); } public static <T> T getBean(Class<T> beanClass) { return applicationContext.getBean(beanClass); } public static <T> T getBean(String beanName, Class<T> beanClass) { return applicationContext.getBean(beanName, beanClass); } }
进一步封装成如下工具类:
package cn.qs.utils;import org.springframework.web.context.ContextLoader; import org.springframework.web.context.WebApplicationContext;public class SystemUtils { private SystemUtils() { } public static <T> T getContextBean(Class<T> clazz) { WebApplicationContext currentWebApplicationContext = ContextLoader.getCurrentWebApplicationContext(); T bean = currentWebApplicationContext.getBean(clazz);// 根据类型获取对象 return bean; } }
使用方法:
UserHealthService userHealthService = SpringBootUtils.getBean(UserHealthService.class);
3.Springboot 修改配置参数
之前了解到Spring的配置封装到了一个Environment对象中,可以通过该对象获取到application.yml中的配置,而且会自动读取到System.getProperty可以获取到的属性(JVM该进程特有的属性)。但是有时候打成jar包的时候需要修改,其主要方式有如下:
测试类:
package com.xm.ggn.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author: 乔利强 * @date: 2021/1/5 20:21 * @description: */ @RestController public class TestController { @Value("${test:defaultValue}") private String test; @Autowired private Environment environment; @RequestMapping("test") public String test() { System.out.println(System.getProperty("test")); System.out.println(environment.getProperty("test")); return this.test; } }
0. 如果yml未设置,默认取 defaultValue, 且test方法的两个读取到的为null
1. application.properties中设置
test=123
结果: 返回的也是123,控制台打印如下:
null
123
2. 打成jar包以JVM参数的形式传递。-D 会传递给系统属性,也就是System.getProperty可以获取到,而且spring会自动读取系统属性到environment对象
java -jar -Dtest=123456 bx-0.0.1-SNAPSHOT.jar
结果: 返回的也是123456,控制台打印如下:
123456
123456
3. 以程序参数的形式启动(只会传递到spring的environment)。--key=value传递参数
java -jar bx-0.0.1-SNAPSHOT.jar --test=111222
结果:返回的也是111222,控制台打印如下:
null
111222
4.同时设置VM参数和程序参数(以程序参数为准)
java -jar -Dtest=123456 bx-0.0.1-SNAPSHOT.jar --test=654321
结果:返回654321,控制台打印如下:
123456 654321
补充:VM属性和程序参数的区别
VM属性是-Dkey=value设置的属性,可以用System.getProperty(key)获取到;程序属性是给main方法传递的参数