微服务配置中心 Apollo解析——Portal 关联 Namespace

17: roleInitializationService.initNamespaceRoles(appId, namespaceName, operator);

18: // 循环 `models` ,创建 Namespace 对象

19: for (NamespaceCreationModel model : models) {

20: NamespaceDTO namespace = model.getNamespace();

21: // 校验相关参数非空

22: RequestPrecondition.checkArgumentsNotEmpty(model.getEnv(), namespace.getAppId(), namespace.getClusterName(), namespace.getNamespaceName());

23: // 创建 Namespace 对象

24: try {

25: namespaceService.createNamespace(Env.valueOf(model.getEnv()), namespace);

26: } catch (Exception e) {

27: logger.error("create namespace fail.", e);

28: Tracer.logError(String.format("create namespace fail. (env=%s namespace=%s)", model.getEnv(), namespace.getNamespaceName()), e);

29: }

30: }

31: // 授予 Namespace Role 给当前管理员

32: assignNamespaceRoleToOperator(appId, namespaceName);

33: return ResponseEntity.ok().build();

34: }

  • POST `/apps/{appId}/namespaces` 接口 ,Request Body 传递 JSON 对象。

  • @PreAuthorize(...) 注解,调用 PermissionValidator#hasCreateNamespacePermission(appId) 方法,校验是否有创建 Namespace 的权限。后续文章,详细分享。

  • com.ctrip.framework.apollo.portal.entity.model.NamespaceCreationModel ,Namespace 创建 Model 。代码如下:

public class NamespaceCreationModel {

/**

* 环境

*/

private String env;

/**

* Namespace 信息

*/

private NamespaceDTO namespace;

}

  • com.ctrip.framework.apollo.common.dto.NamespaceDTO ,Namespace DTO 。代码如下:

public class NamespaceDTO extends BaseDTO {

private long id;

/**

* App 编号

*/

private String appId;

/**

* Cluster 名字

*/

private String clusterName;

/**

* Namespace 名字

*/

private String namespaceName;

}

  • x

  • 第 13 行:校验 models 非空。

  • 第 14 至 17 行:初始化 Namespace 的 Role 们。详解解析,见 《Apollo 源码解析 ------ Portal 认证与授权(二)之授权》 。

  • 第 18 至 30 行:循环 models ,创建 Namespace 对象们。

  • 第 22 行:调用 RequestPrecondition#checkArgumentsNotEmpty(String... args) 方法,校验 NamespaceDTO 的 env appId clusterName namespaceName 非空。

  • 第 25 行:调用 NamespaceService#createNamespace(Env, NamespaceDTO) 方法,创建并保存 Namespace 到 Admin Service 中。

  • 第 26 至 29 行:当发生异常时,即创建失败,仅打印异常日志。也就是说,在 【第 33 行】,依然提示创建 Namespace 成功。

  • 第 32 行:授予 Namespace Role 给当前管理员。详解解析,见 《Apollo 源码解析 ------ Portal 认证与授权(二)之授权》 。

2.2 NamespaceService

在 apollo-portal 项目中,

com.ctrip.framework.apollo.portal.service.NamespaceService ,提供 Namespace 的 Service 逻辑。

#createNamespace(Env env, NamespaceDTO namespace) 方法,保存 Namespace 对象到 Admin Service 中。代码如下:

1: @Autowired

2: private UserInfoHolder userInfoHolder;

3: @Autowired

4: private AdminServiceAPI.NamespaceAPI namespaceAPI;

5:

6: public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) {

7: // 设置 NamespaceDTO 的创建和修改人为当前管理员

8: if (StringUtils.isEmpty(namespace.getDataChangeCreatedBy())) {

9: namespace.setDataChangeCreatedBy(userInfoHolder.getUser().getUserId());

10: }

11: namespace.setDataChangeLastModifiedBy(userInfoHolder.getUser().getUserId());

12: // 创建 Namespace 到 Admin Service

13: NamespaceDTO createdNamespace = namespaceAPI.createNamespace(env, namespace);

14: // 【TODO 6001】Tracer 日志

15: Tracer.logEvent(TracerEventType.CREATE_NAMESPACE, String.format("%s+%s+%s+%s", namespace.getAppId(), env, namespace.getClusterName(), namespace.getNamespaceName()));

16: return createdNamespace;

17: }

  • 第 7 至 11 行:设置 NamespaceDTO 的创建和修改人。

  • 第 13 行:调用 NamespaceAPI#createNamespace(Env, NamespaceDTO) 方法,创建 Namespace 到 Admin Service 。

  • 第 15 行:【TODO 6001】Tracer 日志

2.3 NamespaceAPI

com.ctrip.framework.apollo.portal.api.NamespaceAPI ,实现 API 抽象类,封装对 Admin Service 的 AppNamespace 和 Namespace 两个模块的 API 调用。代码如下:

NamespaceAPI

  • 使用 restTemplate ,调用对应的 API 接口。

3. Admin Service 侧

=======================

3.1 NamespaceController

在 apollo-adminservice 项目中,

com.ctrip.framework.apollo.adminservice.controller.NamespaceController ,提供 Namespace 的 API

#create(appId, clusterName, NamespaceDTO) 方法,创建 Namespace 。代码如下:

1: @RestController

2: public class NamespaceController {

3:

4: @Autowired

5: private NamespaceService namespaceService;

6:

7: /**

8: * 创建 Namespace

9: *

10: * @param appId App 编号

11: * @param clusterName Cluster 名字

12: * @param dto NamespaceDTO 对象

13: * @return 创建成功的 NamespaceDTO 对象

14: */

15: @RequestMapping(path = "/apps/{appId}/clusters/{clusterName}/namespaces", method = RequestMethod.POST)

16: public NamespaceDTO create(@PathVariable("appId") String appId,

17: @PathVariable("clusterName") String clusterName, @RequestBody NamespaceDTO dto) {

18: // 校验 NamespaceDTO 的 `namespaceName` 格式正确。

19: if (!InputValidator.isValidClusterNamespace(dto.getNamespaceName())) {

20: throw new BadRequestException(String.format("Namespace格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE));

21: }

22: // 将 NamespaceDTO 转换成 Namespace 对象

23: Namespace entity = BeanUtils.transfrom(Namespace.class, dto);

24: // 判断 `name` 在 Cluster 下是否已经存在对应的 Namespace 对象。若已经存在,抛出 BadRequestException 异常。

25: Namespace managedEntity = namespaceService.findOne(appId, clusterName, entity.getNamespaceName());

26: if (managedEntity != null) {

27: throw new BadRequestException("namespace already exist.");

28: }

29: // 保存 Namespace 对象

30: entity = namespaceService.save(entity);

31: // 将保存的 Namespace 对象转换成 NamespaceDTO

32: dto = BeanUtils.transfrom(NamespaceDTO.class, entity);

33: return dto;

34: }

35:

36: // ... 省略其他接口和属性

37: }

  • POST `/apps/{appId}/clusters/{clusterName}/namespaces` 接口 ,Request Body 传递 JSON 对象。

  • 第 18 至 21 行:调用 InputValidator#isValidClusterNamespace(name) 方法,校验NamespaceDTO 的 namespaceName 格式正确,符合 [0-9a-zA-Z_.-]+" 格式。

  • 第 23 行:调用 BeanUtils#transfrom(Class clazz, Object src) 方法,将 NamespaceDTO 转换成 Namespace 对象。

  • 第 20 至 23 行:调用 NamespaceService#findOne(appId, clusterName, namespaceName) 方法,校验 name 在 Cluster 下是否已经存在对应的 Namespace 对象。若已经存在,抛出 BadRequestException 异常。

  • 第 30 行:调用 NamespaceService#save(Namespace) 方法,保存 Namespace 对象到数据库。

  • 第 30 至 32 行:调用 BeanUtils#transfrom(Class clazz, Object src) 方法,将保存的 Namespace 对象,转换成 NamespaceDTO 返回。

3.2 NamespaceService

在 《Apollo 源码解析 ------ Portal 创建 Namespace》 的 「4.4 NamespaceService」 ,已经详细解析。

相关推荐
Cikiss1 分钟前
「全网最细 + 实战源码案例」设计模式——桥接模式
java·后端·设计模式·桥接模式
�时过境迁,物是人非5 分钟前
Redis地理散列GeoHash
前端·redis·bootstrap
山禾女鬼00123 分钟前
深入探索 HTML5 拖拽效果 API:打造流畅交互体验
前端·html·html5
Dr_Si35 分钟前
CF 761A.Dasha and Stairs(Java实现)
java·开发语言
你爱写程序吗(新H)42 分钟前
基于微信小程序的停车场管理系统设计 停车场微信小程序的设计与实现 (源码+文档)
java·spring boot·微信小程序·小程序
讓丄帝愛伱1 小时前
Java 泛型<? extends Object>
java·开发语言·python
Enti7c1 小时前
商品列表及商品详情展示
前端·css·css3
Dr_Si1 小时前
CF 764B.Timofey and cubes(Java实现)
java·算法·排序算法
纪元A梦1 小时前
Java设计模式:行为型模式→观察者模式
java·观察者模式·设计模式
掘金-我是哪吒2 小时前
分布式微服务系统架构第89集:kafka消费者
分布式·微服务·架构·kafka·系统架构