SpringBoot-8编写ApplicationConfig类并构思配置更新策略
首先在application.yml中添加一些配置的配置,然后在config目录下编写ApplicationConfig类,@Value的形式把yml的注入到private元素中,最后在Controller或者ServiceImpl中注入ApplicationConfig,就可以使用
1. ApplicationConfig类相关
application.yml
1 2 3 4 5 6
| weight: char: 0.25 pinyin-tone: 0.25 pinyin-without-tone: 0.25 set: 0.25
|
ApplicationConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| package cn.edu.bupt.aiswitchboard.config;
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration;
@Configuration public class ApplicationConfig { @Value("${weight.char}") private double weightChar;
@Value("${weight.pinyin-tone}") private double weightPinyinTone;
@Value("${weight.pinyin-without-tone}") private double weightPinyinWithoutTone;
@Value("${weight.set}") private double weightSet;
public double getWeightChar() { return weightChar; }
public void setWeightChar(double weightChar) { this.weightChar = weightChar; }
public double getWeightPinyinTone() { return weightPinyinTone; }
public void setWeightPinyinTone(double weightPinyinTone) { this.weightPinyinTone = weightPinyinTone; }
public double getWeightPinyinWithoutTone() { return weightPinyinWithoutTone; }
public void setWeightPinyinWithoutTone(double weightPinyinWithoutTone) { this.weightPinyinWithoutTone = weightPinyinWithoutTone; }
public double getWeightSet() { return weightSet; }
public void setWeightSet(double weightSet) { this.weightSet = weightSet; } }
|
在controller或者service里面的使用,NameFinderServiceImpl.java(可能还有简化方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package cn.edu.bupt.aiswitchboard.service;
import cn.edu.bupt.aiswitchboard.config.ApplicationConfig; import cn.edu.bupt.aiswitchboard.dao.WorkerDao; import cn.edu.bupt.aiswitchboard.model.NameFinderFindRequest; import cn.edu.bupt.aiswitchboard.model.NameFinderInsertRequest; import cn.edu.bupt.aiswitchboard.model.Worker; import cn.edu.bupt.aiswitchboard.utils.ScoreUtils; import cn.edu.bupt.aiswitchboard.utils.PinyinUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;
import java.util.*;
@Service public class NameFinderServiceImpl implements NameFinderService{
private final ApplicationConfig applicationConfig; public NameFinderServiceImpl(ApplicationConfig applicationConfig) { this.applicationConfig = applicationConfig; }
@Override public Object find(NameFinderFindRequest requestParameters) { ... double totalScore = applicationConfig.getWeightChar() * scoreChar + applicationConfig.getWeightPinyinTone() * scorePinyinTone + applicationConfig.getWeightPinyinWithoutTone() * scorePinyinWithoutTone + applicationConfig.getWeightSet() * scoreSet; ... return data; } }
|
2. 更新策略相关
对于系统中的一些配置项,我们很有可能在系统上线的时候需要进行更新,从设计角度来说有很多种更新策略的选择,可以分为:
更新策略 |
好处 |
不足 |
1)把待更新参数写在配置文件里面,然后编写几个数据更新的接口,当向接口请求的时候可以完成数据的更新 |
相对是一种比较简单的方式 |
这种方案的不足之处其实非常多:首先在分布式系统中如果有反向代理如NGINX这样的前面封装存在,那么一个接口请求只能做到一个后面被代理服务器的更新,其他的还是会是老版数据。此外,如果一次性要修改很多参数,还需要把接口编写很多个。这里有一种自己实现的基于redis记录时间的多进程同步方式,在一个机器上完成修改后,修改时间会变,其他机器读到了改变后的修改时间将更新。 |
2)每次接口请求的时候都重新读取配置文件 |
比较简单,而且保证肯定可以生效,不会受到反向代理多台服务器的影响 |
首先会影响接口的效率,即使不是更新的接口请求也会重新加载一遍配置文件(在python中通过读json实现),在java这边可能也需要有类似的操作,但是不知道怎么能每次都修改ApplicationConfig然后完成一些注入 |
3)将配置文件写在mysql中 |
当使用配置文件的时候,从mysql那边去取,这样能保证实时读到的是最新的 |
和mysql有交互,如果mysql宕机会不会有问题,小数据量应该还好 |
暂时能想到的是以上这些更新策略,这还是一个非常常用的问题,感觉是有多种方式可以实现的