有的时候,我们会希望在配置文件中直接配置基于时间的参数,例如,当服务向注册中心注册的时候我们希望带上服务启动的时间戳。
如下,Spring Boot的配置文件中可以很方便的配置随机数。
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
同样,我们期望的时间配置方式如下:
spring.cloud.consul.discovery.tags=now=${date.now},timestamp=${date.timestamp}
如何实现不多说,上代码。
核心实现:DatePropertySource
继承PropertySource,实现特定的Date资源池。
支持Calendar中所有属性的单独获取,方便自由组合,使用方式:${date.PROP_NAME}
public class DatePropertySource extends PropertySource {
private static final Log log = LogFactory.getLog(DatePropertySource.class);
public static final String DATE_PROPERTY_SOURCE_NAME = "date_time";
public static final String PREFIX = "date.";
public static final String NOW = "NOW";
public static final String TIMESTAMP = "TIMESTAMP";
//yyyy-MM-dd HH:mm:ss
public static final String FORMAT = "FORMAT";
public static final String YMD = "YMD";
public static final String HMS = "HMS";
public static final String ERA = "ERA";
public static final String YEAR = "YEAR";
public static final String DAY_OF_YEAR = "DAY_OF_YEAR";
public static final String DAY_OF_MONTH = "DAY_OF_MONTH";
public static final String WEEK_OF_YEAR = "WEEK_OF_YEAR";
public static final String WEEK_OF_MONTH = "WEEK_OF_MONTH";
public static final String DAY_OF_WEEK_IN_MONTH = "DAY_OF_WEEK_IN_MONTH";
public static final String AM_PM = "AM_PM";
public static final String HOUR = "HOUR";
public static final String HOUR_OF_DAY = "HOUR_OF_DAY";
public static final String MINUTE = "MINUTE";
public static final String SECOND = "SECOND";
public static final String MILLISECOND = "MILLISECOND";
public DatePropertySource(String name) {
super(name, Calendar.getInstance());
}
public DatePropertySource() {
this(DATE_PROPERTY_SOURCE_NAME);
}
@Override
public Object getProperty(String name) {
if (!name.startsWith(PREFIX)) {
return null;
}
if (log.isTraceEnabled()) {
log.trace("Generating date property for '" + name + "'");
}
String valueType = name.substring(PREFIX.length()).toUpperCase();
Calendar now = Calendar.getInstance();
switch (valueType) {
case NOW:
return getNow(now);
case TIMESTAMP:
return getTimestamp(now);
case FORMAT:
return getFormat(now);
case YMD:
return getYMD(now);
case HMS:
return getHMS(now);
case ERA:
return getEra(now);
case YEAR:
return getYear(now);
case DAY_OF_YEAR:
return getDayOfYear(now);
case DAY_OF_MONTH:
return getDayOfMonth(now);
case WEEK_OF_YEAR:
return getWeekOfYear(now);
case WEEK_OF_MONTH:
return getWeekOfMonth(now);
case DAY_OF_WEEK_IN_MONTH:
return getDayOfWeekInMonth(now);
case AM_PM:
return getAmOrPm(now);
case HOUR:
return getHour(now);
case HOUR_OF_DAY:
return getHourOfDay(now);
case MINUTE:
return getMinute(now);
case SECOND:
return getSecond(now);
case MILLISECOND:
return getMilliSecond(now);
default:
return getNow(now);
}
}
public static void addToEnvironment(ConfigurableEnvironment environment) {
environment.getPropertySources().addAfter(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
new RandomValuePropertySource(DATE_PROPERTY_SOURCE_NAME));
log.trace("RandomValuePropertySource add to Environment");
}
private Date getNow(Calendar instance) {
return instance.getTime();
}
private String getFormat(Calendar instance) {
StringBuffer sb = new StringBuffer(64);
sb.append(instance.get(Calendar.YEAR))
.append("-")
.append(instance.get(Calendar.MONTH))
.append("-")
.append(instance.get(Calendar.DAY_OF_MONTH))
.append(" ")
.append(instance.get(Calendar.HOUR))
.append(":")
.append(instance.get(Calendar.MINUTE))
.append(":")
.append(instance.get(Calendar.SECOND));
return sb.toString();
}
private long getTimestamp(Calendar instance) {
return instance.getTimeInMillis();
}
private String getYMD(Calendar instance) {
return instance.get(Calendar.YEAR) + "-" + instance.get(Calendar.MONTH) + "-" + instance.get(Calendar.DAY_OF_MONTH);
}
private String getHMS(Calendar instance) {
return instance.get(Calendar.HOUR_OF_DAY) + ":" + instance.get(Calendar.MINUTE) + ":" + instance.get(Calendar.SECOND);
}
private int getEra(Calendar instance) {
return instance.get(Calendar.ERA);
}
private int getYear(Calendar instance) {
return instance.get(Calendar.YEAR);
}
private int getDayOfYear(Calendar instance) {
return instance.get(Calendar.DAY_OF_YEAR);
}
private int getDayOfMonth(Calendar instance) {
return instance.get(Calendar.DAY_OF_MONTH);
}
private int getWeekOfYear(Calendar instance) {
return instance.get(Calendar.WEEK_OF_YEAR);
}
private int getWeekOfMonth(Calendar instance) {
return instance.get(Calendar.WEEK_OF_MONTH);
}
private int getDayOfWeek(Calendar instance) {
return instance.get(Calendar.DAY_OF_WEEK);
}
private int getDayOfWeekInMonth(Calendar instance) {
return instance.get(Calendar.DAY_OF_WEEK_IN_MONTH);
}
private int getAmOrPm(Calendar instance) {
return instance.get(Calendar.AM_PM);
}
private int getHour(Calendar instance) {
return instance.get(Calendar.HOUR);
}
private int getHourOfDay(Calendar instance) {
return instance.get(Calendar.HOUR_OF_DAY);
}
private int getMinute(Calendar instance) {
return instance.get(Calendar.MINUTE);
}
private int getSecond(Calendar instance) {
return instance.get(Calendar.SECOND);
}
private int getMilliSecond(Calendar instance) {
return instance.get(Calendar.MILLISECOND);
}
}
加入系统资源池
实现ApplicationContextInitializer接口,将DatePropertySource加入系统资源池,使其生效。
public class DatePropertyConfiguration implements ApplicationContextInitializer{
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
DatePropertySource datePropertySource = new DatePropertySource();
environment.getPropertySources().addLast(datePropertySource);
}
}
resources\META-INF\spring.factories中配置ApplicationContextInitializer,SpringBoot启动时会自动加载。
org.springframework.context.ApplicationContextInitializer=\
com.example.demo.config.DatePropertyConfiguration
完成
OK,至此,一个自定义的资源池就完成了,从此配置文件中可以自由组合,直接配置时间的不同格式了。
注意:使用的时间在属性值生成完成后固定,不会在每次使用、注入的时候改变。