1.定义http配置接口
接口名为 : /springbootService/server01,完整接口路径如下
http://127.0.0.1:10001/springbootService/server01
注 : springbootService在其他服务中定义,server01为配置名称
接口响应格式与内容如下
{
"name":"springbootService",
"profiles":[
"server01"
],
"label":null,
"propertySources":[
{
"name":"http://127.0.0.1:10001/springbootService/server01",
"source":{
"name":"001",
"server.port":"8002"
}
}
],
"version":null,
"state":null
}
说明 : 只需要关注 source 属性即可
对象类如下
Environment
package com.aliyun.industry.configuration.biz.model.config;
import java.util.List;
/**
* @Auther: liyue
* @Date: 2020/5/6 18:13
* @Description:
*/
public class Environment {
private String name;
private String[] profiles;
private String label;
private List<PropertySource> propertySources;
private String version;
private String state;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getProfiles() {
return profiles;
}
public void setProfiles(String[] profiles) {
this.profiles = profiles;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public List<PropertySource> getPropertySources() {
return propertySources;
}
public void setPropertySources(List<PropertySource> propertySources) {
this.propertySources = propertySources;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Environment() {
}
public Environment(String name, String[] profiles, String label, List<PropertySource> propertySources, String version, String state) {
this.name = name;
this.profiles = profiles;
this.label = label;
this.propertySources = propertySources;
this.version = version;
this.state = state;
}
}
PropertySource
import java.util.Map;
/**
* @Auther: liyue
* @Date: 2020/5/6 18:14
* @Description:
*/
public class PropertySource {
private String name;
private Map<?, ?> source;
public PropertySource() {
}
public PropertySource(String name, Map<?, ?> source) {
this.name = name;
this.source = source;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<?, ?> getSource() {
return source;
}
public void setSource(Map<?, ?> source) {
this.source = source;
}
}
封装工具类 : ConfigWrapperUtil ; type是配置文件名,content是map类型,key是配置名称,value是配置值
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @Auther: liyue
* @Date: 2020/5/8 17:09
* @Description:
*/
public class ConfigWrapperUtil {
public static Environment wrapper(String type, Map<String,String> content){
Environment environment = new Environment();
environment.setName("springbootService");
environment.setLabel(null);
String[] profiles = {type};
environment.setProfiles(profiles);
PropertySource propertySource = new PropertySource("http://127.0.0.1:10001/springbootService/"+type,content);
List<PropertySource> propertySources = new LinkedList<PropertySource>(){{
add(propertySource);
}};
environment.setPropertySources(propertySources);
return environment;
}
}
控制层 : SpringCloudConfigController
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import java.util.TreeMap;
/**
* @Auther: liyue
* @Date: 2020/5/8 17:05
* @Description:
*/
@RestController
public class SpringCloudConfigController {
@RequestMapping("/{springbootService}/{type}")
public Object getMap(@PathVariable String type) {
Map<String, String> map = new TreeMap<>();
map.put("server.port", "8002");
map.put("name", "张三");
return ConfigWrapperUtil.wrapper(type, map);
}
}
注 : springbootService 两边不加大括号的话,该名称必须和其他服务的 spring.application.name 配置的数值对应才能读取,两边加了大括号之后可以通用匹配,不需要管其他服务的 spring.application.name 配置内容
2.其他springboot服务读取配置
引入maven配置
<!--Spring Cloud Config 客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
resources下新建 bootstrap.properties 文件,profile为接口的第二个URI,内容如下
spring.cloud.config.uri=http://localhost:10001/
spring.cloud.config.profile=server01
application.properties 中定义 spring.application.name,改数值必须与配置接口的第一个URI相同
spring.application.name=springCloudConfig
server.port=8001
3.调试
配置接口正常访问时,启动测试服务,若以8002端口运行说明成功,8001端口说明获取配置失败
4.依赖对应
- 2.0.2.RELEASE
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
- parent
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath />
</parent>
<properties>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
5.配置增删改查(文件形式存储)
package com.alibaba.gts.flm.config.center.api.service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.gts.flm.config.center.api.constant.Constants;
import com.alibaba.gts.flm.config.center.api.controller.model.CommonResult;
import com.alibaba.gts.flm.config.center.api.exception.MsgException;
import com.alibaba.gts.flm.config.center.api.service.model.ConfigDTO;
import com.alibaba.gts.flm.config.center.api.service.model.Environment;
import com.alibaba.gts.flm.config.center.api.service.model.PropertySource;
import com.alibaba.gts.flm.config.center.api.util.DateUtil;
import com.alibaba.gts.flm.config.center.api.util.FileUtil;
import com.alibaba.gts.flm.config.center.api.util.ShellUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author: liyue
* @Date: 2023/05/31/09:49
* @Description:
*/
@Service
public class ConfigService {
public static final String configListFile = Constants.configPath + File.separator + "list.json";
@Value("${ip}")
private String ip;
@Value("${server.port}")
private Integer port;
public Object list(ConfigDTO req) {
if (!new File(configListFile).exists()) {
return CommonResult.success();
}
String s = FileUtil.readByLineRs(configListFile);
List<ConfigDTO> reqS = JSONArray.parseArray(s, ConfigDTO.class);
List<ConfigDTO> rs = reqS.stream().filter(c -> filter(req, c)).collect(Collectors.toList());
int index = 1;
for (ConfigDTO r : rs) {
r.setNumber(index);
index++;
}
return CommonResult.success(rs);
}
private Boolean filter(ConfigDTO req, ConfigDTO c) {
JSONObject reqs = JSONObject.parseObject(JSONObject.toJSONString(req));
if (reqs.size() == 0) {
return Boolean.TRUE;
}
JSONObject cs = JSONObject.parseObject(JSONObject.toJSONString(c));
Boolean rs = Boolean.FALSE;
for (Map.Entry<String, Object> entry : reqs.entrySet()) {
String cv = cs.getString(entry.getKey());
Object reqv = entry.getValue();
if (reqv == null) {
rs = Boolean.FALSE;
} else {
if (cv.contains(reqv.toString())) {
rs = Boolean.TRUE;
} else {
return Boolean.FALSE;
}
}
}
return rs;
}
public Object getById(Long id) {
if (!new File(configListFile).exists()) {
return CommonResult.success();
}
String s = FileUtil.readByLineRs(configListFile);
List<ConfigDTO> reqS = JSONArray.parseArray(s, ConfigDTO.class);
ConfigDTO req = reqS.stream().filter(c -> c.getId().equals(id)).findFirst().get();
return CommonResult.success(req);
}
public Object add(ConfigDTO req) {
List<ConfigDTO> reqS = null;
// if (req.getConfig().equals("commonConfig")){
// throw new MsgException("<公共配置>已添加");
// }
if (new File(configListFile).exists()) {
String s = FileUtil.readByLineRs(configListFile);
reqS = JSONArray.parseArray(s, ConfigDTO.class);
Long max = null;
try {
max = reqS.stream().max(Comparator.comparingLong(ConfigDTO::getId)).get().getId();
} catch (Exception e) {
max = 0L;
}
req.setId(max + 1);
reqS.add(req);
} else {
reqS = new LinkedList<>();
req.setId(1L);
reqS.add(req);
}
FileUtil.write(configListFile, JSONObject.toJSONString(reqS));
return CommonResult.success();
}
private void backup(){
ShellUtil.exec("cp "+configListFile+" "+configListFile+".bak_"+ DateUtil.format(new Date(),DateUtil.PATTERN_YYYYMMDDHHMMSSSSS));
}
public Object update(ConfigDTO req) {
if (!new File(configListFile).exists()) {
return CommonResult.success();
}
this.backup();
String s = FileUtil.readByLineRs(configListFile);
List<ConfigDTO> reqS = JSONArray.parseArray(s, ConfigDTO.class);
for (ConfigDTO dto : reqS) {
if (dto.getId().equals(req.getId())) {
if (req.getName() != null) {
dto.setName(req.getName());
}
if (req.getConfig() != null) {
dto.setConfig(req.getConfig());
}
if (req.getEnv() != null) {
dto.setEnv(req.getEnv());
}
if (req.getRemake() != null) {
dto.setRemake(req.getRemake());
}
if (req.getContent() != null) {
checkPropertiesStr(req.getContent());
dto.setContent(req.getContent());
}
break;
}
}
FileUtil.write(configListFile, JSONObject.toJSONString(reqS));
return CommonResult.success();
}
public Object delete(Long id) {
if (!new File(configListFile).exists()) {
return CommonResult.success();
}
this.backup();
String s = FileUtil.readByLineRs(configListFile);
List<ConfigDTO> reqS = JSONArray.parseArray(s, ConfigDTO.class);
Iterator<ConfigDTO> iterator = reqS.iterator();
while (iterator.hasNext()) {
ConfigDTO next = iterator.next();
// if (next.getConfig().equals("commonConfig")){
// throw new MsgException("公共配置无法删除");
// }
if (next.getId().equals(id)) {
iterator.remove();
break;
}
}
FileUtil.write(configListFile, JSONObject.toJSONString(reqS));
return CommonResult.success();
}
public Object getConfig(String config, String env) {
if (!new File(configListFile).exists()) {
return CommonResult.success();
}
String s = FileUtil.readByLineRs(configListFile);
List<ConfigDTO> reqS = JSONArray.parseArray(s, ConfigDTO.class);
ConfigDTO req = reqS.stream().filter(c -> c.getConfig().equals(config) && c.getEnv().equals(env)).findFirst().get();
Map<String, String> map = JSONObject.parseObject(propertiesStrToJsonStr(req.getContent()), Map.class);
return wrapper(config, env, map);
}
public static void main(String[] args) {
String s = "url=2222=3333";
int i = s.indexOf("=");
System.out.println(s.substring(0, i));
System.out.println(s.substring(i + 1));
}
private void checkPropertiesStr(String str) {
for (String s : str.split("\n")) {
if (isContinue(s)) {
continue;
}
try {
int i = s.indexOf("=");
s.substring(0, i);
s.substring(i + 1);
} catch (Exception e) {
throw new MsgException("内容\"" + s + "\"格式错误! 正确格式为 k=v");
}
}
}
public String propertiesStrToJsonStr(String str) {
if (str == null) {
return null;
}
JSONObject json = new JSONObject();
for (String s : str.split("\n")) {
if (isContinue(s)) {
continue;
}
try {
int i = s.indexOf("=");
json.put(s.substring(0, i), s.substring(i + 1));
} catch (Exception e) {
throw new MsgException("内容\"" + s + "\"格式错误! 正确格式为 k=v");
}
}
return json.toJSONString();
}
private Boolean isContinue(String str) {
if (str.startsWith("#") || str.equals("") || str.trim().equals("")) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public String jsonStrToPropertiesStr(String str) {
if (str == null) {
return null;
}
JSONObject jsonObject = JSONObject.parseObject(str);
StringBuilder sb = new StringBuilder();
jsonObject.forEach((k, v) -> {
sb.append(k).append("=").append(v).append("\n");
});
return sb.toString();
}
public Environment wrapper(String config, String env, Map<String, String> content) {
Environment environment = new Environment();
environment.setName(config);
environment.setLabel(null);
String[] profiles = {env};
environment.setProfiles(profiles);
PropertySource propertySource = new PropertySource("http://" + ip + ":" + port + "/" + config + "/" + env, content);
List<PropertySource> propertySources = new LinkedList<PropertySource>() {{
add(propertySource);
}};
environment.setPropertySources(propertySources);
return environment;
}
}
工具类 : Java 常用工具类(30) : File工具类_archive.nextfileheader() 为空_Lxinccode的博客-CSDN博客
END。