SpringBoot读取配置文件到实体类和静态变量
Posted 在奋斗的大道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot读取配置文件到实体类和静态变量相关的知识,希望对你有一定的参考价值。
1.读取配置文件到实体类
在实际开发中,我们知道Apache Solr索引库的配置信息不能在代码中写死,得放到配置文件中,动态的去读取,这样当我们修改Apache Solr索引库参数参数的时候,就不用重新编译和打包了,直接修改配置文件即可。所以,有时我们需要从配置文件中读取数据到实体类中。
1.1 配置文件和实体类准备
首先在SpringBoot的application.porperties 配置文件中配置示例数据solr.archinfo:
solr.archinfo.url=http://127.0.0.1:8314/solr-webapp/archInfo
solr.archinfo.maxRetries=2
solr.archinfo.connectionTimeout=5000
示例实体类ApacheSolrArchInfoEntity,
重点注意:
1、必须包含set方法才能实现后续将从配置文件中读取的值注入到实体类的对应变量中。
2、配置参数属性名称与实体类属性必须一一对应。
package com.zzg.solr.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
/**
* Apache Solr 连接实体对象
* @author zzg
*
*/
@Component
@ConfigurationProperties(prefix = "solr.archinfo")
@Data
public class ApacheSolrArchInfoEntity {
private String url;
private Integer maxRetries;
private Integer connectionTimeout;
}
1.2 读取配置文件到实体类的方法
SpringBoot提供了多种注解来快速读取配置文件中值的方式,如下:
1.2.1 @Value
注解
首先需要在实体类上添加@Component
注解表示将该实体类放入到Spring容器中,然后只需要在每个成员变量上添加@Value
注解即可,注解中的参数值为配置文件中的参数名,并用${}
包起来:
package com.zzg.solr.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
/**
* Apache Solr 连接实体对象
* @author zzg
*
*/
@Component
@Data
public class ApacheSolrArchInfoEntity {
@Value("${solr.archinfo.url}")
private String url;
@Value("${solr.archinfo.maxRetries}")
private Integer maxRetries;
@Value("${solr.archinfo.connectionTimeout}")
private Integer connectionTimeout;
}
注意:该注解仅能读取单个值,对于Map、List和Bean对象这类数据不能读取和自动注入,也就是说不能读取一系列的多个数据。
1.2.2 @ConfigurationProperties注解
对于@Value注解的局限性,@ConfigurationProperties注解对其进行了解决,该注解可以实现对配置文件中的属性值批量读取和注入。使用方法依旧是首先添加@Component注解将实体类放入到Spring容器中,然后添加@ConfigurationProperties注解,并指定该注解的prefix参数表示对应实体类的前缀:
package com.zzg.solr.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
/**
* Apache Solr 连接实体对象
* @author zzg
*
*/
@Component
@ConfigurationProperties(prefix = "solr.archinfo")
@Data
public class ApacheSolrArchInfoEntity {
private String url;
private Integer maxRetries;
private Integer connectionTimeout;
}
该注解可以实现对上述配置文件中的单个值、Map、List集合和其他对象的快速注入到实体类中。所以@Value
与 @ConfigurationProperties
注解的差异在于:需要批量注入配置文件的属性值时用后者,需要指定单个属性值时用前者。
1.2.3 @PropertySource
注解加载其他配置文件
上述的@ConfigurationProperties注解和 @ConfigurationProperties 注解默认都是从SpringBoot的全局配置文件application.properties/application.yml中获取的值。所有配置数据写在全局配置文件中,会显得配置文件过于臃肿和杂乱,所以可将和全局配置无关的配置参数(如上述的实体类参数)抽取出来,单独放到另一个局部配置文件中。这就是@PropertySource注解的作用,指定想要读取的配置文件的来源。
实现步骤总结:
第一步:在application.properties文件的同级目录resources中,新增archinfo.properties文件
#配置solr 连接参数
solr.archinfo.url=http://127.0.0.1:8314/solr-webapp/archInfo
solr.archinfo.maxRetries=2
solr.archinfo.connectionTimeout=5000
第二步:注解使用方法只需在上述注解使用的基础上,添加@PropertySource
注解即可,将默认配置文件改为我们自己指定的配置文件,注解参数value
属性是数组类型,用于指定配置文件位置。:
package com.zzg.solr.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
/**
* Apache Solr 连接实体对象
* @author zzg
*
*/
@Component
@ConfigurationProperties(prefix = "solr.archinfo")
@PropertySource(value = {"classpath:archinfo.properties"})
@Data
public class ApacheSolrArchInfoEntity {
private String url;
private Integer maxRetries;
private Integer connectionTimeout;
}
1.2.4 @ImportResource注解应用xml配置文件
SpringBoot提倡零配置, 即无xml配置,但是在实际开发中,可能有一些特殊要求必须使用 xml 配置;这时我们可以通过 Spring 提供的 @ImportResource 来应用 xml 配置文件。
比如上述我们需要将一个实体类中的数据全部从配置文件中读取,所以我们除了上述SpringBoot本身就提供的便捷的注解之外,还可以直接在Spring的xml配置文件中配置实体类的属性值,直接在配置文件中配置相当于也实现了从配置文件中读取数据。
@ImportResource的作用是加载Spring的xml配置文件的配置内容并应用到容器中使用:
1.创建 resources/spring-solr.xml 文件,添以下配置内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--Apache Solr 指定索引库实例化-->
<bean id="httpSolrClient" class="org.apache.solr.client.solrj.impl.HttpSolrClient">
<constructor-arg name="baseURL
value="http://127.0.0.1:8314/solr-webapp/archInfo" />
</bean>
</beans>
2.使用 @ImportResource
注解标注在一个配置类上,实现将Spring的该配置文件加载应用到容器中,下例是主配置类:
package com.zzg.config;
import org.springframework.context.annotation.Configuration;
@Configuration
@ImportResource(locations = {"classpath:spring-solr.xml"})
public class ApacheSolrConfig {
}
@ImportResource
注解实际提供的是一种向容器中注入组件的方式,同理,可以通过其他向容器中注入组件的方式来实现对实体类数据的解耦,如@@Configuration
和@Bean
注解搭配等。
2.读取配置文件到静态变量
在使用阿里云的短信服务时,accessKeyId和accessSecret等参数不能在代码中写死,需要解耦,并且可能OSS对象存储也需要用到这个密钥,所以想到的方案是将这些参数放到一个静态变量中,供全局调用,然后静态变量中的值来源于配置文件。所以出现了需要读取配置文件到静态变量的需求。
2.1 在方法上添加@Value
注解
对于上面描述的读取配置文件到实体类中@Value
注解是添加在成员变量上,但对于静态成员变量就不行了,会是一个空值。但可以将其添加到set方法上,实现对静态变量的注入。另外,依旧是得在类上添加@Component
注解,要注入就要放入容器嘛~
AliyunParameter.properties配置文件:
#阿里云短信服务的参数数据
aliyun.accessKeyId=xxxxxxxxxxxx
aliyun.accessSecret=yyyyyyyyyyyy
aliyun.smsSignName=科彬个人社区
aliyun.smsRegionId=cn-hangzhou
aliyun.smsTemplateCode.REGISTER_CODE=SMS_1111111111
aliyun.smsTemplateCode.VERIFY_CODE=SMS_222222222
含静态变量的实体类:
import java.util.Map;
@PropertySource(value = {"classpath:AliyunParameter.properties"})
@Component
public class AliyunParameter {
public static String accessKeyId;
public static String accessSecret;
public static String smsRegionId;
public static String smsSignName;
public static Map<String,String> smsTemplateCode;
@Value("${aliyun.accessKeyId}")
public void setAccessKeyId(String accessKeyId){
AliyunParameter.accessKeyId = accessKeyId;
}
}
注意:这种读取配置文件到静态变量的方式依旧存在@Value
注解的局限性,只能注入单个变量,对于集合List、Map这类数据不能注入。
2.2 使用@PostConstruct注解在初始化Servlet之前初始化静态变量
被@PostConstruct注解修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct修饰的方法在其所在类的构造函数之后执行,Servlet的 init() 方法之前执行。通常我们在Spring框架中使用到@PostConstruct注解的方法在整个Bean初始化中的执行顺序为:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)。
第一步:创建一个配置类AliyunConfig,该配置类通过上述的@ConfigurationProperties
注解将配置文件中的值注入到实体类中,然后再通过@PostConstruct
注解对上述AliyunParameter
类中的静态变量进行初始化:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Map;
@PropertySource(value = {"classpath:AliyunParameter.properties"})
@Component
@ConfigurationProperties(prefix = "aliyun")
public class AliyunConfig {
private String accessKeyId;
private String accessSecret;
private String smsRegionId;
private String smsSignName;
private Map<String,String> smsTemplateCode;
@PostConstruct
public void aliyunParameterInit(){
AliyunParameter.setParameter(this);
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessSecret() {
return accessSecret;
}
public void setAccessSecret(String accessSecret) {
this.accessSecret = accessSecret;
}
public String getSmsRegionId() {
return smsRegionId;
}
public void setSmsRegionId(String smsRegionId) {
this.smsRegionId = smsRegionId;
}
public String getSmsSignName() {
return smsSignName;
}
public void setSmsSignName(String smsSignName) {
this.smsSignName = smsSignName;
}
public Map<String, String> getSmsTemplateCode() {
return smsTemplateCode;
}
public void setSmsTemplateCode(Map<String, String> smsTemplateCode) {
this.smsTemplateCode = smsTemplateCode;
}
}
调整包含静态变量的 AliyunParameter 类,提供一个set方法对静态变量进行赋值:
import java.util.Map;
public class AliyunParameter {
public static String accessKeyId;
public static String accessSecret;
public static String smsRegionId;
public static String smsSignName;
public static Map<String,String> smsTemplateCode;
public static void setParameter(AliyunConfig aliyunConfig) {
AliyunParameter.accessKeyId = aliyunConfig.getAccessKeyId();
AliyunParameter.accessSecret = aliyunConfig.getAccessSecret();
AliyunParameter.smsRegionId = aliyunConfig.getSmsRegionId();
AliyunParameter.smsSignName = aliyunConfig.getSmsSignName();
AliyunParameter.smsTemplateCode = aliyunConfig.getSmsTemplateCode();
}
public static void print() {
System.out.println("SmsParameter{" +
"regionId='" + smsRegionId + '\\'' +
", accessKeyId='" + accessKeyId + '\\'' +
", accessSecret='" + accessSecret + '\\'' +
", signName='" + smsSignName + '\\'' +
", templateCode=" + smsTemplateCode +
'}');
}
}
以上是关于SpringBoot读取配置文件到实体类和静态变量的主要内容,如果未能解决你的问题,请参考以下文章