前言
先简单说一下这个题目的意思是什么。
我们知道,如果我们的项目是SpringCloud的项目,我们是可以把我们的本地配置写到云端的的配置中心的,比如集成SpringCloud Alibaba,你就可以使用Nacos,然后把配置写到Nacos中,从而保证配置的安全。
那么如果是SpringBoot项目,大部分我们的配置都是直接写在本地的,那么就会出现代码如果泄露,配置文件内的内容就会被发现从而造成危险,所以如果可以把SpringBoot项目的配置文件也从云端或者远程处拉取的话,那么项目的安全度就会高很多。
所以可以考虑使用一种类似于配置中心的方式,我们自己建设一个简易的配置中心,然后我们发送HTTP请求去配置中心拉取代码,也可以做到配置不存在本地的形式。
我的思路是,写一个小网页,然后把配置存储在网页对应的数据库中,也就是我们写一个内部人员使用的管理系统,我们可以把配置输入到这个管理系统中,和Nacos差不多。
然后我们只需要向管理系统发送请求,并且携带上一些参数,配置系统就会把其中的配置返回给我们,从而做到SpringBoot项目也可以从远程拉取配置的方式。
思路
我们公司的实现方式是,封装好一个jar包,打包到maven仓库,之后只要项目需要使用,就拉取这个项目即可。
之后就是,我们得配置我们需要加载的一些配置信息,以及提供一些项目参数来确定能从配置中心拉取到唯一的配置。比如提供项目的id,项目的开发环境env,需要加载的一些其他需要从配置中心拉取的配置。
配置有了,我们需要在我们的jar包中,封装好一些读取用户本地配置的一些信息,也就是我们需要读取用户本地的配置文件,我们先开发一个类用于存储最终得到的信息:
public class AppProperties { //默认开发组 private static final String DEFAULT_GROUP = "Default"; private static String projectName;//项目名称 private static String environment;//开发环境 private static String group;//开发组 public AppProperties() { } public static String getGroup() { return group; } public static String getAppName() { return projectName; } public static String getEnvironment() { return environment; } }
之后,我们就得编写一个类,这个类需要用于获取用户可能的存放配置文件的所有地方,可以分为如下几种:ClassPath、System、UserDir、Environment。
public class ConfigCenterClientEnvironment { private List<Property> propertySourcesList = new CopyOnWriteArrayList(); public ConfigCenterClientEnvironment() { this.propertySourcesList.add(new EnvironmentProperty()); this.propertySourcesList.add(new SystemProperty()); this.propertySourcesList.add(new UserDirProperty()); this.propertySourcesList.add(new ClassPathProperty()); } private String getByOrder(String name) { Iterator i$ = this.propertySourcesList.iterator(); String value; do { if (!i$.hasNext()) { return null; } Property propertySources = (Property)i$.next(); value = (String)propertySources.get(name); } while(!StringUtils.isNotBlank(value)); return value; } public String getEnvironment() { return this.getByOrder("environment"); } public String getProjectName() { return this.getByOrder("projectName"); } public String getGroup() { return this.getByOrder("group"); } }
下面简单的贴出一个获取System配置的类
public class SystemProperty extends Properties { public SystemProperty() { String projectName = System.getProperty("projectName"); String environment = System.getProperty("environment"); String group = System.getProperty("group"); if (StringUtils.isNotBlank(projectName)) { this.put("projectName", projectName); } if (StringUtils.isNotBlank(environment)) { this.put("environment", environment); } if (StringUtils.isNotBlank(group)) { this.put("group", group); } } }
类似于从ClassPath获取配置的方式也一样,只不过获取配置文件的方式变为了先使用InputStream流去读取配置文件,读取到配置文件非空之后在读取配置文件中对应的配置。
ok,到目前位置我们已经把本地的配置文件全都读取完毕并且保存好了,只好我们要做的就是基于这些配置文件的信息,向我们的注册中心发送请求,并且从注册中心得到数据。
大概的代码编写方式如下,我们传入对应的projectName,env,group等参数,然后我们使用这些参数配合上我们注册中心的地址,比如http://xxx/xxx/然后加上我们的这些参数拼接在后面,就可以得到一个完整的url串。这里你也可以按照上面一样的方式,让配置中心的地址也选择从我们本地读,但是这样子不太好了,就失去了我们一开始配置这个东西的理由。
得到url之后,我们发送这个url向注册中心,并且得到一个json串。
private List<ProjectConfig> getProjectConfigListFromRemote(String projectName, String env, String group) { try { String url = UrlBuilder.getConfigListByEnv(projectName, env, group); String json = this.httpHelper.get(url); this.currentStatus = "ready"; //当前是否被好发送 return JsonHelper.convertToProjectConfig(json); } catch (Exception var6) { this.currentStatus = "offline"; //配置中心离线 报错 logger.error(var6.getMessage(), var6); throw new RuntimeException(var6.getMessage(), var6); } }
当然,为了确保当前用户拥有获取配置的权限,我们还可以加上一个用户校验。
class HttpHelper { private String user; private String password; public HttpHelper(String user, String password) { this.user = user; this.password = password; } public String get(String url) throws Exception { return this.HttpInvoker(url, "GET", this.user, this.password, (String)null); } public String post(String url, String body) throws Exception { return this.HttpInvoker(url, "POST", this.user, this.password, body); } }
然后,我们通过Json解析的方式,将从配置中心得到的配置,进行Json的解析,得到最后的类,我们可以使用gson进行解析
gson解析后如下
至此,我们已经把配置从配置中心获取到了,至于获取到的配置的格式,是你自己定义的,只要方便你之后进行解析即可,我们使用的是xml的配置。
在得到了配置之后,如果我们需要使用这些配置对本地的一些类进行配置,那么我们直接根据配置的key获取到配置对应的value即可,然后解析value这个字符串,然后对属性与类进行赋值即可。