Apollo2.1.0+Springboot使用OpenApI
依赖管理
<!-- bootstrap最高级启动配置读取 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.ctrip.framework.apollo/apollo-client -->
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-openapi</artifactId>
<version>2.1.0</version>
</dependency>
application.properties
# Apollo
app.id=MORE-USER-USE
apollo.cache-dir=./ManyUser/apollo/cache
apollo.bootstrap.enabled=true
#apollo.bootstrap.namespaces=application.properties
apollo.meta=http://localhost:8080
apollo.bootstrap.eagerLoad.enabled=true
apollo.config-service=http://localhost:8080
env=DEV
apollo.use.admin.token=809d168da6f3baa39c02c1d376a0cc9cec852fa0fa8c6e2cff9b33e276d3738a
apollo.use.portal.url=http://localhost:8070
apollo-env.properties
dev.meta=http://localhost:8080
启动类 加入 @EnableApolloConfig
/**
* @description: 启动类
* @author: GuoTong
* @createTime: 2023-06-21 20:31
* @since JDK 1.8 OR 11
**/
@SpringBootApplication
@EnableApolloConfig
public class AppStartClass {
public static void main(String[] args) {
SpringApplication.run(AppStartClass.class, args);
}
}
常规配置中心集成使用
package com.gton.user.config;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import com.gton.user.io.Resp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* @description: Apollo同时还增加了几个新的Annotation来简化在Spring环境中的使用。
* @author: GuoTong
* @createTime: 2023-06-24 12:30
* @since JDK 1.8 OR 11
**/
@Component
@Slf4j
public class MyApolloConfig {
/**
* ApolloJsonValue annotated on fields example, the default value is specified as empty list - []
* <br />
* jsonBeanProperty=[{"someString":"hello","someInt":100},{"someString":"world!","someInt":200}]
*/
@ApolloJsonValue("${jsonBeanProperty:[]}")
private List<Resp> anotherJsonBeans = new ArrayList<>();
@Value("${batch:100}")
private String batch;
//config change listener for namespace application
@ApolloConfigChangeListener(value = "application")
private void apolloChange(ConfigChangeEvent changeEvent) {
//update injected value of batch if it is changed in Apollo
if (changeEvent.isChanged("batch")) {
batch = changeEvent.getChange("batch").getNewValue();
}
log.info(changeEvent.getNamespace() + "变化的key=>" + changeEvent.changedKeys() + ";==1");
}
@ApolloConfigChangeListener(value = "order")
private void someOnChange(ConfigChangeEvent changeEvent) {
//update injected value of batch if it is changed in Apollo
if (changeEvent.isChanged("anotherJsonBeans")) {
log.info(changeEvent.getChange("anotherJsonBeans").getOldValue());
log.error(changeEvent.getChange("anotherJsonBeans").getNewValue());
}
log.info(anotherJsonBeans.toString());
log.info(changeEvent.getNamespace() + "变化的key=>" + changeEvent.changedKeys() + ";==1");
}
}
Apollo 的开放平台使用
package com.gton.user.handler;
import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient;
import com.ctrip.framework.apollo.openapi.dto.NamespaceReleaseDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenPageDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
/**
* @description: Apollo开放平台操作
* @author: GuoTong
* @createTime: 2023-06-24 14:10
* @since JDK 1.8 OR 11
**/
public class ApolloOpenApiOperator {
private ApolloOpenApiClient apolloOpenApiClient;
private static ApolloOpenApiOperator apolloOpenApiOperator = null;
public static ApolloOpenApiOperator getApolloOpenApiOperator() throws IOException {
if (apolloOpenApiOperator == null) {
synchronized (ApolloOpenApiOperator.class) {
if (apolloOpenApiOperator == null) {
return new ApolloOpenApiOperator();
}
}
}
return apolloOpenApiOperator;
}
public ApolloOpenApiOperator(ApolloOpenApiClient apolloOpenApiClient) {
this.apolloOpenApiClient = apolloOpenApiClient;
}
public ApolloOpenApiOperator() throws IOException {
initApolloOpenApiOperator();
}
private void initApolloOpenApiOperator() throws IOException {
// 获取配置文件
ClassPathResource classPathResource = new ClassPathResource("application.properties");
InputStream inputStream = classPathResource.getInputStream();
// 使用properties加载
Properties properties = new Properties();
properties.load(inputStream);
String token = properties.getProperty("apollo.use.admin.token");
String portalUrl = properties.getProperty("apollo.use.portal.url");
if (StringUtils.isNotEmpty(token)) {
this.apolloOpenApiClient = ApolloOpenApiClient
.newBuilder().
withConnectTimeout(60000).
withToken(token).
withPortalUrl(portalUrl).
withReadTimeout(60000)
.build();
}
}
public ApolloOpenApiClient getApolloOpenApiClient() {
return this.apolloOpenApiClient;
}
/**
* Description: 创建NamSpace
*
* @param openAppNamespaceKey
* @author: GuoTong
* @date: 2023-06-24 15:04:44
* @return:void
*/
public void crateNameSpace(OpenAppNamespaceKey openAppNamespaceKey) {
OpenAppNamespaceDTO openAppNamespaceDTO = new OpenAppNamespaceDTO();
openAppNamespaceDTO.setAppId(openAppNamespaceKey.getAppId());
openAppNamespaceDTO.setName(openAppNamespaceKey.getSpaceName());
openAppNamespaceDTO.setComment(openAppNamespaceKey.getSpaceDesc());
openAppNamespaceDTO.setPublic(openAppNamespaceKey.spaceIsPub);
apolloOpenApiClient.createAppNamespace(openAppNamespaceDTO);
}
/**
* Description: 下发Apollo
*
* @param doIssueApolloKey
* @author: GuoTong
* @date: 2023-06-24 14:35:52
* @return:void
*/
public void doIssueApollo(DoIssueApolloKey doIssueApolloKey) {
OpenItemDTO openItemDTO = new OpenItemDTO();
openItemDTO.setKey(doIssueApolloKey.getKey());
openItemDTO.setValue(doIssueApolloKey.getValue());
openItemDTO.setComment(doIssueApolloKey.getDesc());
openItemDTO.setType(doIssueApolloKey.handlerValueType(doIssueApolloKey.getValueType()));
openItemDTO.setDataChangeCreatedBy(doIssueApolloKey.getOperator());
if (doIssueApolloKey.isModifiedOrInsert()) {
openItemDTO.setDataChangeLastModifiedBy(doIssueApolloKey.getOperator());
}
// 下发到Apollo
apolloOpenApiClient.createOrUpdateItem(
doIssueApolloKey.getAppId(),
doIssueApolloKey.getEnv(),
doIssueApolloKey.getClusterName(),
doIssueApolloKey.getNamespaceName(),
openItemDTO
);
}
/**
* Description: 发布整个NameSpace;推荐下发完成之后统一调一次,不要多次的下发操作,每一次下发都调用
*
* @param publishApolloKey
* @author: GuoTong
* @date: 2023-06-24 14:56:43
* @return:void
*/
public void executorPublish(PublishApolloKey publishApolloKey) {
// apollo下发的数据执行发布
NamespaceReleaseDTO namespaceReleaseDTO = new NamespaceReleaseDTO();
//配置版本名称
namespaceReleaseDTO.setReleaseTitle(publishApolloKey.getReleaseTitle());
// 发布说明
namespaceReleaseDTO.setReleaseComment(publishApolloKey.getReleaseDescription());
// 操作员
namespaceReleaseDTO.setReleasedBy(publishApolloKey.getReleaseOperator());
apolloOpenApiClient.publishNamespace(publishApolloKey.getAppId(),
publishApolloKey.getEnv(),
publishApolloKey.getClusterName(),
publishApolloKey.getNamespaceName(), namespaceReleaseDTO);
}
/**
* Description: 移除Apollo的配置
* String appId, String env, String clusterName, String namespaceName, String key,
* String operator
*
* @param removeKeys
* @author: GuoTong
* @date: 2023-06-24 15:27:07
* @return:void
*/
public void executorRemove(DoIssueApolloKey removeKeys) {
apolloOpenApiClient.removeItem(removeKeys.getAppId(),
removeKeys.getEnv(),
removeKeys.getClusterName(),
removeKeys.getNamespaceName(), removeKeys.getKey(), removeKeys.getOperator());
}
/**
* queryApolloKey many
*
* @param baseApolloKey
* @author: GuoTong
* @date: 2023-06-24 14:56:43
* @return:void
*/
public List<OpenItemDTO> queryApolloKey(BaseApolloKey baseApolloKey, int page, int size) {
if (page <= 1) {
page = 0;
}
if (size <= 0) {
size = 10;
}
OpenPageDTO<OpenItemDTO> itemsByNamespace = apolloOpenApiClient.findItemsByNamespace(baseApolloKey.getAppId(),
baseApolloKey.getEnv(),
baseApolloKey.getClusterName(),
baseApolloKey.getNamespaceName(), page, size);
List<OpenItemDTO> content = itemsByNamespace.getContent();
return content;
}
/**
* queryApolloKey one
*
* @param baseApolloKey
* @author: GuoTong
* @date: 2023-06-24 14:56:43
* @return:void
*/
public OpenItemDTO queryApolloKeyOne(DoIssueApolloKey baseApolloKey) {
OpenItemDTO itemsByNamespace = apolloOpenApiClient.getItem(baseApolloKey.getAppId(),
baseApolloKey.getEnv(),
baseApolloKey.getClusterName(),
baseApolloKey.getNamespaceName(), baseApolloKey.getKey());
return itemsByNamespace;
}
@Data
public static class OpenAppNamespaceKey {
private String appId;
private String spaceName;
private String spaceDesc;
private boolean spaceIsPub = false;
// 默认值 DEV
private String env = "DEV";
private String clusterName;
private String namespaceName;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class DoIssueApolloKey extends BaseApolloKey {
private String key;
private String value;
// 默认值 Apollo
private String operator = "Apollo";
private String desc;
private String valueType;
// 是否是修改
private boolean modifiedOrInsert;
/**
* Description: 查询 Portal web的前端得出
*
* @author: GuoTong
* @date: 2023-06-24 14:46:42
* <select class="form-control ng-valid ng-valid-valdr ng-not-empty ng-dirty ng-touched ng-valid-parse" name="type" ng-model="item.type" ng-change="changeType()">
* <option value="0" class="ng-binding">String</option>
* <option value="1" class="ng-binding">Number</option>
* <option value="2" class="ng-binding">Boolean</option>
* <option value="3" class="ng-binding">JSON</option>
* </select>
*/
public int handlerValueType(String valueType) {
switch (valueType) {
case "String":
return 0;
case "Number":
return 1;
case "Boolean":
return 2;
case "JSON":
return 3;
}
// 未匹配就默认使用String的值
return 0;
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class BaseApolloKey {
protected String appId;
// 默认值 DEV
protected String env = "DEV";
// 默认值 default
protected String clusterName = "default";
protected String namespaceName;
}
@Data
public static class PublishApolloKey extends BaseApolloKey {
// 发布时候的标题
private String releaseTitle;
// 发布时候的操作员
private String releaseOperator;
// 发布时候的DESC
private String releaseDescription;
}
}
配合Controller使用
package com.gton.user.controller;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
import com.gton.user.annotation.SwaggerScanClass;
import com.gton.user.handler.ApolloOpenApiOperator;
import com.gton.user.io.Resp;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* 多租户表(apollo)表控制层
*
* @author 郭童
* @since 2023-06-22 16:28:10
*/
@RestController
@RequestMapping("apollo")
@SwaggerScanClass
public class ApolloOperatorController {
/**
* 分页查询数据 namespaceName
*
* @param
* @return 所有数据
*/
@PostMapping("/queryLimit")
@ApiOperation("查询Apollo配置")
public Resp<List<OpenItemDTO>> queryPage(
@RequestParam("appId") String appId,
@RequestParam("clusterName") String clusterName,
@RequestParam("env") String env,
@RequestParam("namespaceName") String namespaceName
) throws IOException {
ApolloOpenApiOperator apolloOpenApiOperator = ApolloOpenApiOperator.getApolloOpenApiOperator();
ApolloOpenApiOperator.BaseApolloKey baseApolloKey = new ApolloOpenApiOperator.BaseApolloKey();
baseApolloKey.setAppId(appId);
baseApolloKey.setClusterName(clusterName);
baseApolloKey.setEnv(env);
baseApolloKey.setNamespaceName(namespaceName);
List<OpenItemDTO> openItemDTOS = apolloOpenApiOperator.queryApolloKey(baseApolloKey, 0, 10);
return Resp.Ok(openItemDTOS);
}
/**
* 通过主键查询单条数据
*
* @param key apollo-key
* @return 单条数据
*/
@GetMapping("/queryOne/{key}")
public Resp<OpenItemDTO> selectOne(@PathVariable("key") String key,
@RequestParam("appId") String appId,
@RequestParam("clusterName") String clusterName,
@RequestParam("env") String env,
@RequestParam("namespaceName") String namespaceName) throws IOException {
ApolloOpenApiOperator apolloOpenApiOperator = ApolloOpenApiOperator.getApolloOpenApiOperator();
ApolloOpenApiOperator.DoIssueApolloKey baseApolloKey = new ApolloOpenApiOperator.DoIssueApolloKey();
baseApolloKey.setAppId(appId);
baseApolloKey.setEnv(env);
baseApolloKey.setNamespaceName(namespaceName);
baseApolloKey.setClusterName(clusterName);
baseApolloKey.setKey(key);
OpenItemDTO openItemDTO = apolloOpenApiOperator.queryApolloKeyOne(baseApolloKey);
return Resp.Ok(openItemDTO);
}
/**
* 新增数据 到Apollo
*
* @param doIssueApolloKey 实体对象
* @return 新增结果
*/
@PostMapping("/save")
public Resp<String> insert(@RequestBody Map<String, String> doIssueApolloKey) throws IOException {
String json = JSON.toJSONString(doIssueApolloKey);
ApolloOpenApiOperator.DoIssueApolloKey doIssueApolloData = JSONObject.parseObject(json, ApolloOpenApiOperator.DoIssueApolloKey.class);
ApolloOpenApiOperator apolloOpenApiOperator = ApolloOpenApiOperator.getApolloOpenApiOperator();
doIssueApolloData.setModifiedOrInsert(false);
apolloOpenApiOperator.doIssueApollo(doIssueApolloData);
return Resp.Ok(doIssueApolloData.getKey());
}
/**
* 修改数据
*
* @param doIssueApolloKey 实体对象
* @return 修改结果
*/
@PutMapping("/update")
public Resp<String> update(@RequestBody Map<String, String> doIssueApolloKey) throws IOException {
String json = JSON.toJSONString(doIssueApolloKey);
ApolloOpenApiOperator.DoIssueApolloKey doIssueApolloData = JSONObject.parseObject(json, ApolloOpenApiOperator.DoIssueApolloKey.class);
ApolloOpenApiOperator apolloOpenApiOperator = ApolloOpenApiOperator.getApolloOpenApiOperator();
doIssueApolloData.setModifiedOrInsert(true);
apolloOpenApiOperator.doIssueApollo(doIssueApolloData);
return Resp.Ok(doIssueApolloData.getKey());
}
/**
* Description: 移出Apollo已下发数据
*
* @param key
* @param appId
* @param clusterName
* @param env
* @param namespaceName
* @author: GuoTong
* @date: 2023-06-24 15:42:24
* @return:com.gton.user.io.Resp<java.lang.String>
*/
@GetMapping("/dels")
public Resp<String> delete(@RequestParam("key") String key,
@RequestParam("appId") String appId,
@RequestParam("clusterName") String clusterName,
@RequestParam("env") String env,
@RequestParam("namespaceName") String namespaceName) throws IOException {
ApolloOpenApiOperator apolloOpenApiOperator = ApolloOpenApiOperator.getApolloOpenApiOperator();
ApolloOpenApiOperator.DoIssueApolloKey removeKeys = new ApolloOpenApiOperator.DoIssueApolloKey();
removeKeys.setAppId(appId);
removeKeys.setEnv(env);
removeKeys.setNamespaceName(namespaceName);
removeKeys.setClusterName(clusterName);
removeKeys.setKey(key);
apolloOpenApiOperator.executorRemove(removeKeys);
return Resp.Ok(removeKeys.getKey());
}
}
Apollo2.1.0+Springboot使用OpenApI的更多相关文章
- solr8.0 springboot整合solr(四)
引言: solr搭建起后,就该应用到java后台开发里了,接下来就用springboot整合应用solr 一:引入jar包 <!--solr--> <dependency> & ...
- 搭建 springboot 2.0 mybatis 读写分离 配置区分不同环境
最近公司打算使用springboot2.0, springboot支持HTTP/2,所以提前先搭建一下环境.网上很多都在springboot1.5实现的,所以还是有些差异的.接下来咱们一块看一下. 文 ...
- Springboot 系列(十六)你真的了解 Swagger 文档吗?
前言 目前来说,在 Java 领域使用 Springboot 构建微服务是比较流行的,在构建微服务时,我们大多数会选择暴漏一个 REST API 以供调用.又或者公司采用前后端分离的开发模式,让前端和 ...
- SpringBoot笔记一
1 开始 1.1 spring介绍 Spring Boot使开发独立的,产品级别的基于Spring的应用变得非常简单,你只需"just run". 我们为Spring平台及第三方库 ...
- springboot 开发入门,及问题汇总
1 . springboot简单介绍(http://projects.spring.io/spring-boot/) 现在的web项目几乎都会用到spring框架,而要使用spring难免需要配置大量 ...
- Spring Boot 2.0 教程 - 深入SpringAplication
原文连接:https://www.codemore.top/cates/Backend/post/2018-05-20/spring-boot-SpringApplication 可以通过Spring ...
- 使用kbmmw 生成REST 服务OpenAPI函数原型
我们以前介绍了很多kbmmw 开发REST 的例子.一直有个问题困惑着大家. 我们提供REST 服务,如何让客户端快速的使用,当然可以写文档,但是一旦 后台改变了,又要再一次给调用者发新文档,非常的麻 ...
- 初识elasticsearch_2(查询和整合springboot)
初始化 首先将官网所下载的json文件,放入到es中,采用如下命令: curl -H "Content-Type: application/json" -XPOST 'localh ...
- springboot 整合 Redis 方法二
方法一请参考之前博文 spring boot 整合 redis 自己的版本 java8 + redis3.0 + springboot 2.0.0 1 spring boot已经支持集成 redis ...
- OpenAPI初体验
问题的一开始源于客户和服务部门抱怨我的REST API文档写得不好,然后又了解到 django rest framework 利用 coreapi 能自动生成文档,再就是看到 swagger.io 上 ...
随机推荐
- 浅谈 thinkphp composer 扩展包加载原理
浅谈 thinkphp composer 扩展包加载原理 本文将介绍 ThinkPHP 中 Composer 扩展包的加载原理,帮助读者更好地理解和应用该功能. 前言 如题,今天感觉好久没有更新博客了 ...
- C++面试八股文:在C++中,有哪些可执行体?
某日二师兄参加XXX科技公司的C++工程师开发岗位第14面: 面试官:在C++中,有哪些可执行体? 二师兄:可执行体? 面试官:也就是可调用对象. 二师兄:让我想一想.函数.函数指针.类的静态方法.类 ...
- Pinot2的无人机传感器和摄像头
目录 1. 引言 2. 技术原理及概念 2.1 基本概念解释 2.2 技术原理介绍 2.3 相关技术比较 无人机传感器和摄像头在Pinot 2中得到广泛应用,其目的是为Pinot 2提供全面的传感器和 ...
- kafka入门必备知识
1. Kafka是一个分布式流处理平台: 可以让你发布和订阅流式的记录.这一方面与消息队列或者企业消息系统类似. 可以储存流式的记录,并且有较好的容错性. 可以在流式记录产生时就进行处理. 2. 消息 ...
- 移动端APP组件化架构实践
前言 对于中大型移动端APP开发来讲,组件化是一种常用的项目架构方式.个人最近几年在工作项目中也一直使用组件化的方式来开发,在这过程中也积累了一些经验和思考.主要是来自在日常开发中使用组件化开发遇到的 ...
- CentOS 8搭建Docker镜像私有仓库-registry
目录 简介 安装Docker 添加docker yum源 安装docker 确保网络模块开机自动加载 使桥接流量对iptables可见 配置docker 验证docker是否正常 添加用户到docke ...
- IIS部署的应用无法自动注册到Nacos
问题描述: 自己开发的某系统后台API接入nacos,在IIS上部署无法自动注册到nacos服务列表中.其根本原因是网站处于休眠状态,当某请求访问该网站时,网站被激活,nacos注册成功. 但这块有个 ...
- PTA 21级数据结构与算法实验7—查找表
目录 7-1 电话聊天狂人 7-2 两个有序序列的中位数 7-3 词频统计 7-4 集合相似度 7-5 悄悄关注 7-6 单身狗 7-7 词典 7-8 这是二叉搜索树吗? 7-9 二叉搜索树 7-1 ...
- 2023年郑州轻工业大学校赛邀请赛zxy
第一次组队和大家去外校打比赛,真的是一次很棒的体验,尽管结果不尽人意,但总之收获颇丰,也认识到自身更多的不足. 本次比赛是三人一队,一台电脑,一分纸质试题,我们三人开始先从第一题开始,这题看起来还行, ...
- Windows安装SSH服务器
1.打开Win的设置并在设置中找到应用 2.在应用中依次选择应用和功能 可选功能 3.在可选功能中选择添加功能 (OpenSSH客户端默认已存在) 选中OpenSSH服务器后点击下方的安装 4.快捷键 ...