• Apoll创建项目分析


    1.Apoll创建项目代码分析

    POST 请求到/apps

    2.controller分析

    2.1 Post参数对象AppModel

    public class AppModel {
    
      @NotBlank(message = "name cannot be blank")
      private String name;
    
      @NotBlank(message = "appId cannot be blank")
      @Pattern(
          regexp = InputValidator.CLUSTER_NAMESPACE_VALIDATOR,
          message = "Invalid AppId format: " + InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE
      )
      private String appId;
    
      @NotBlank(message = "orgId cannot be blank")
      private String orgId;
    
      @NotBlank(message = "orgName cannot be blank")
      private String orgName;
    
      @NotBlank(message = "ownerName cannot be blank")
      private String ownerName;
    
      private Set<String> admins;
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
      public String getAppId() {
        return appId;
      }
    
      public void setAppId(String appId) {
        this.appId = appId;
      }
    
      public String getOrgId() {
        return orgId;
      }
    
      public void setOrgId(String orgId) {
        this.orgId = orgId;
      }
    
      public String getOrgName() {
        return orgName;
      }
    
      public void setOrgName(String orgName) {
        this.orgName = orgName;
      }
    
      public String getOwnerName() {
        return ownerName;
      }
    
      public void setOwnerName(String ownerName) {
        this.ownerName = ownerName;
      }
    
      public Set<String> getAdmins() {
        return admins;
      }
    
      public void setAdmins(Set<String> admins) {
        this.admins = admins;
      }
    }
    

    2.2 controller逻辑

    @PreAuthorize(value = "@permissionValidator.hasCreateApplicationPermission()")
    // 用到了SpringSecurity包里面的判断权限的功能,使用了注解@PreAuthorize,如果没有权限,就直接返回报错
        @PostMapping
        public App create(@Valid @RequestBody AppModel appModel) {
            // 2.3将AppModel 类型对象转换为App对象
            App app = transformToApp(appModel);
            
            // 2.4 创建应用信息
            App createdApp = appService.createAppInLocal(app);
            // 4.1 发布应用创建事件
            publisher.publishEvent(new AppCreationEvent(createdApp));
    
            Set<String> admins = appModel.getAdmins();
            if (!CollectionUtils.isEmpty(admins)) {
                rolePermissionService
                        .assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()),
                                admins, userInfoHolder.getUser().getUserId());
            }
    
            return createdApp;
        }
    

    2.3 transformApp方法

    /**
    * 将AppModel对象转换为App对象
    **/
    private App transformToApp(AppModel appModel) {
            String appId = appModel.getAppId();
            String appName = appModel.getName();
            String ownerName = appModel.getOwnerName();
            String orgId = appModel.getOrgId();
            String orgName = appModel.getOrgName();
    
            return App.builder()
                    .appId(appId)
                    .name(appName)
                    .ownerName(ownerName)
                    .orgId(orgId)
                    .orgName(orgName)
                    .build();
    
        }
    

    2.4 appService.createAppInLocal(app)

    @Transactional // 事务注解
        public App createAppInLocal(App app) {
            String appId = app.getAppId();
            App managedApp = appRepository.findByAppId(appId); // 通过数据库中的App表找到应用名字id为appId的记录
    
            if (managedApp != null) {
                // 查重校验
                throw new BadRequestException(String.format("App already exists. AppId = %s", appId));
            }
            // 判断应用的所属人员,目前系统中是否还存在
            UserInfo owner = userService.findByUserId(app.getOwnerName());
            if (owner == null) {
                throw new BadRequestException("Application's owner not exist.");
            }
            app.setOwnerEmail(owner.getEmail());
            // 获取当前用户
            String operator = userInfoHolder.getUser().getUserId();
            // 补齐应用的创建人,修改人
            app.setDataChangeCreatedBy(operator);
            app.setDataChangeLastModifiedBy(operator);
            App createdApp = appRepository.save(app); // 数据落App表
    
            // 2.5 创建应用关联的默认namespace
            appNamespaceService.createDefaultAppNamespace(appId);
            // 2.6 初始化应用的角色信息
            roleInitializationService.initAppRoles(createdApp);
            // 2.7 发布日志事件,记录日志
            Tracer.logEvent(TracerEventType.CREATE_APP, appId);
    
            return createdApp;
        }
    
    

    2.5 创建应用关联的默认namespace

    appNamespaceService.createDefaultAppNamespace(appId)

    @Transactional
      public void createDefaultAppNamespace(String appId) {
        if (!isAppNamespaceNameUnique(appId, ConfigConsts.NAMESPACE_APPLICATION)) {
          throw new BadRequestException(String.format("App already has application namespace. AppId = %s", appId));
        }
        // 对应了AppNamespace表一条记录,里面关联了应用Id
        AppNamespace appNs = new AppNamespace();
        appNs.setAppId(appId);
        appNs.setName(ConfigConsts.NAMESPACE_APPLICATION);
        appNs.setComment("default app namespace");
        appNs.setFormat(ConfigFileFormat.Properties.getValue());
        String userId = userInfoHolder.getUser().getUserId();
        appNs.setDataChangeCreatedBy(userId);
        appNs.setDataChangeLastModifiedBy(userId);
    
        appNamespaceRepository.save(appNs);
      }
    

    2.6 初始化应用的角色信息

    roleInitializationService.initAppRoles(createdApp);

    @Transactional
        public void initAppRoles(App app) {
            String appId = app.getAppId();
            // 创建角色名字,以Master+AppId为主
            String appMasterRoleName = RoleUtils.buildAppMasterRoleName(appId);
    
            //has created before,判断一下这个角色的名字是否在数据库中已存在
            if (rolePermissionService.findRoleByRoleName(appMasterRoleName) != null) {
                return;
            }
            // 获取应用的创建人信息
            String operator = app.getDataChangeCreatedBy();
            // 3.1 create app permissions,创建应用相关的角色及相关权限逻辑
            createAppMasterRole(appId, operator);
            // 3.2 create manageAppMaster permission
            createManageAppMasterRole(appId, operator);
    
            // 3.3 创建角色与用户的关系
            rolePermissionService
                    .assignRoleToUsers(RoleUtils.buildAppMasterRoleName(appId), Sets.newHashSet(app.getOwnerName()),
                            operator);
    
            initNamespaceRoles(appId, ConfigConsts.NAMESPACE_APPLICATION, operator);
            initNamespaceEnvRoles(appId, ConfigConsts.NAMESPACE_APPLICATION, operator);
    
            //assign modify、release namespace role to user
            rolePermissionService.assignRoleToUsers(
                    RoleUtils.buildNamespaceRoleName(appId, ConfigConsts.NAMESPACE_APPLICATION, RoleType.MODIFY_NAMESPACE),
                    Sets.newHashSet(operator), operator);
            rolePermissionService.assignRoleToUsers(
                    RoleUtils.buildNamespaceRoleName(appId, ConfigConsts.NAMESPACE_APPLICATION, RoleType.RELEASE_NAMESPACE),
                    Sets.newHashSet(operator), operator);
    
        }
    

    2.7 发布日志事件,记录日志

    public static void logEvent(String type, String name) {
        try {
          getProducer().logEvent(type, name);
        } catch (Throwable ex) {
          logger.warn("Failed to log event for type: {}, name: {}", type, name, ex);
        }
      }
    private static MessageProducer getProducer() {
        try {
          if (producerManager == null) {
            synchronized (lock) {
              if (producerManager == null) {
                producerManager = ServiceBootstrap.loadFirst(MessageProducerManager.class);
              }
            }
          }
        } catch (Throwable ex) {
          logger.error(
              "Failed to initialize message producer manager, use null message producer manager.", ex);
          producerManager = NULL_MESSAGE_PRODUCER_MANAGER;
        }
        return producerManager.getProducer();
      }
    // 对应了有一些logEvent的实现类CatMessageProducer,里面执行了某些方法,反射
    @Override
      public void logEvent(String type, String name) {
        try {
          LOG_EVENT_WITH_TYPE_AND_NAME.invoke(null, type, name);
        } catch (Throwable ex) {
          throw new IllegalStateException(ex);
        }
      }
    

    3.角色相关的特殊说明

    3.1 创建masterRole角色

    createAppMasterRole(appId, operator)

    private void createAppMasterRole(String appId, String operator) {
            Set<Permission> appPermissions =
                    Stream.of(PermissionType.CREATE_CLUSTER, PermissionType.CREATE_NAMESPACE, PermissionType.ASSIGN_ROLE)
                            .map(permissionType -> createPermission(appId, permissionType, operator)).collect(Collectors.toSet());
            Set<Permission> createdAppPermissions = rolePermissionService.createPermissions(appPermissions); // 权限表Permission落库了(权限表里有权限名字及应用的名字关系)
            Set<Long>
                    appPermissionIds =
                    createdAppPermissions.stream().map(BaseEntity::getId).collect(Collectors.toSet());
    
            //create app master role,这个是角色表Role的数据
            Role appMasterRole = createRole(RoleUtils.buildAppMasterRoleName(appId), operator);
            // 角色和权限的绑定关系落库
            rolePermissionService.createRoleWithPermissions(appMasterRole, appPermissionIds);
        }
    
    private Permission createPermission(String targetId, String permissionType, String operator) {
            Permission permission = new Permission();
            permission.setPermissionType(permissionType);
            permission.setTargetId(targetId);
            permission.setDataChangeCreatedBy(operator);
            permission.setDataChangeLastModifiedBy(operator);
            return permission;
        }
    /**
    * rolePermissionService.createPermissions
    **/
    @Transactional
        public Set<Permission> createPermissions(Set<Permission> permissions) {
            Multimap<String, String> targetIdPermissionTypes = HashMultimap.create();
            for (Permission permission : permissions) {
                targetIdPermissionTypes.put(permission.getTargetId(), permission.getPermissionType());
            }
    
            for (String targetId : targetIdPermissionTypes.keySet()) {
                Collection<String> permissionTypes = targetIdPermissionTypes.get(targetId);
                List<Permission> current =
                        permissionRepository.findByPermissionTypeInAndTargetId(permissionTypes, targetId);
                Preconditions.checkState(CollectionUtils.isEmpty(current),
                        "Permission with permissionType %s targetId %s already exists!", permissionTypes,
                        targetId);
            }
    
            Iterable<Permission> results = permissionRepository.saveAll(permissions);
            return StreamSupport.stream(results.spliterator(), false).collect(Collectors.toSet());
        }
    

    看下数据库中的结构

    Permission表
    MariaDB [ApolloPortalDB]> select * from Permission;
    +----+------------------+------------------------------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    | Id | PermissionType   | TargetId                           | IsDeleted | DataChange_CreatedBy | DataChange_CreatedTime | DataChange_LastModifiedBy | DataChange_LastTime |
    +----+------------------+------------------------------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    |  1 | CreateNamespace  | dubbo-demo-service                 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  2 | CreateCluster    | dubbo-demo-service                 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  3 | AssignRole       | dubbo-demo-service                 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  4 | ManageAppMaster  | dubbo-demo-service                 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  5 | ModifyNamespace  | dubbo-demo-service+application     |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  6 | ReleaseNamespace | dubbo-demo-service+application     |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  7 | ModifyNamespace  | dubbo-demo-service+application+DEV |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  8 | ReleaseNamespace | dubbo-demo-service+application+DEV |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    +----+------------------+------------------------------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    8 rows in set (0.001 sec)
    Rule角色表
    MariaDB [ApolloPortalDB]> select * from Role;
    +----+-----------------------------------------------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    | Id | RoleName                                            | IsDeleted | DataChange_CreatedBy | DataChange_CreatedTime | DataChange_LastModifiedBy | DataChange_LastTime |
    +----+-----------------------------------------------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    |  1 | Master+dubbo-demo-service                           |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  2 | ManageAppMaster+dubbo-demo-service                  |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  3 | ModifyNamespace+dubbo-demo-service+application      |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  4 | ReleaseNamespace+dubbo-demo-service+application     |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  5 | ModifyNamespace+dubbo-demo-service+application+DEV  |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  6 | ReleaseNamespace+dubbo-demo-service+application+DEV |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    +----+-----------------------------------------------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    6 rows in set (0.001 sec)
    Rule角色和权限Permission的关系表
    MariaDB [ApolloPortalDB]> select * from RolePermission;
    +----+--------+--------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    | Id | RoleId | PermissionId | IsDeleted | DataChange_CreatedBy | DataChange_CreatedTime | DataChange_LastModifiedBy | DataChange_LastTime |
    +----+--------+--------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    |  1 |      1 |            1 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  2 |      1 |            2 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  3 |      1 |            3 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  4 |      2 |            4 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  5 |      3 |            5 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  6 |      4 |            6 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  7 |      5 |            7 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  8 |      6 |            8 |           | apollo               | 2022-04-13 20:07:39    | apollo                    | 2022-04-13 20:07:39 |
    |  9 |      7 |            9 |          | apollo               | 2022-04-14 17:39:38    | apollo                    | 2022-04-14 17:49:31 |
    | 10 |      7 |           10 |          | apollo               | 2022-04-14 17:39:38    | apollo                    | 2022-04-14 17:49:31 |
    | 11 |      7 |           11 |          | apollo               | 2022-04-14 17:39:38    | apollo                    | 2022-04-14 17:49:31 |
    | 12 |      8 |           12 |          | apollo               | 2022-04-14 17:39:38    | apollo                    | 2022-04-14 17:49:31 |
    | 13 |      9 |           13 |          | apollo               | 2022-04-14 17:39:39    | apollo                    | 2022-04-14 17:49:31 |
    | 14 |     10 |           14 |          | apollo               | 2022-04-14 17:39:39    | apollo                    | 2022-04-14 17:49:31 |
    | 15 |     11 |           15 |          | apollo               | 2022-04-14 17:39:39    | apollo                    | 2022-04-14 17:49:31 |
    | 16 |     12 |           16 |          | apollo               | 2022-04-14 17:39:39    | apollo                    | 2022-04-14 17:49:31 |
    | 17 |     13 |           17 |          | apollo               | 2022-04-14 17:50:41    | apollo                    | 2022-04-14 17:51:37 |
    | 18 |     13 |           18 |          | apollo               | 2022-04-14 17:50:41    | apollo                    | 2022-04-14 17:51:37 |
    | 19 |     13 |           19 |          | apollo               | 2022-04-14 17:50:41    | apollo                    | 2022-04-14 17:51:37 |
    | 20 |     14 |           20 |          | apollo               | 2022-04-14 17:50:41    | apollo                    | 2022-04-14 17:51:37 |
    | 21 |     15 |           21 |          | apollo               | 2022-04-14 17:50:41    | apollo                    | 2022-04-14 17:51:37 |
    | 22 |     16 |           22 |          | apollo               | 2022-04-14 17:50:42    | apollo                    | 2022-04-14 17:51:37 |
    | 23 |     17 |           23 |          | apollo               | 2022-04-14 17:50:43    | apollo                    | 2022-04-14 17:51:37 |
    | 24 |     18 |           24 |          | apollo               | 2022-04-14 17:50:43    | apollo                    | 2022-04-14 17:51:37 |
    | 25 |     19 |           25 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    | 26 |     19 |           26 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    | 27 |     19 |           27 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    | 28 |     20 |           28 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    | 29 |     21 |           29 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    | 30 |     22 |           30 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    | 31 |     23 |           31 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    | 32 |     24 |           32 |           | apollo               | 2022-04-14 17:52:04    | apollo                    | 2022-04-14 17:52:04 |
    +----+--------+--------------+-----------+----------------------+------------------------+---------------------------+---------------------+
    32 rows in set (0.000 sec)
    

    3.2 创建管理MasterRole

    @Transactional
        private void createManageAppMasterRole(String appId, String operator) {
            Permission permission = createPermission(appId, PermissionType.MANAGE_APP_MASTER, operator);
            rolePermissionService.createPermission(permission);
            Role role = createRole(RoleUtils.buildAppRoleName(appId, PermissionType.MANAGE_APP_MASTER), operator);
            Set<Long> permissionIds = new HashSet<>();
            permissionIds.add(permission.getId());
            rolePermissionService.createRoleWithPermissions(role, permissionIds);
        }
    

    3.3 创建角色与用户的关系

    @Transactional
        public Set<String> assignRoleToUsers(String roleName, Set<String> userIds,
                                             String operatorUserId) {
            Role role = findRoleByRoleName(roleName);
            Preconditions.checkState(role != null, "Role %s doesn't exist!", roleName);
    
            List<UserRole> existedUserRoles =
                    userRoleRepository.findByUserIdInAndRoleId(userIds, role.getId());
            Set<String> existedUserIds =
                existedUserRoles.stream().map(UserRole::getUserId).collect(Collectors.toSet());
    
            Set<String> toAssignUserIds = Sets.difference(userIds, existedUserIds);
    
            Iterable<UserRole> toCreate = toAssignUserIds.stream().map(userId -> {
                UserRole userRole = new UserRole();
                userRole.setRoleId(role.getId());
                userRole.setUserId(userId);
                userRole.setDataChangeCreatedBy(operatorUserId);
                userRole.setDataChangeLastModifiedBy(operatorUserId);
                return userRole;
            }).collect(Collectors.toList());
    
            userRoleRepository.saveAll(toCreate);
            return toAssignUserIds;
        }
    

    4. 事件处理

    4.1 发布事件

    SpringContext的事件,
    publisher.publishEvent(new AppCreationEvent(createdApp));

  • 相关阅读:
    RxJava学习经验谈——map与flatmap
    不要打断链式结构:使用 RxJava的 compose() 操作符
    Android Retrofit网络请求Service,@Path、@Query、@QueryMap、@Map...
    Android 勤用RXJava compose操作符消除重复代码
    Android使用token维持登陆状态的方法
    Java服务器对外提供接口以及Android端向服务器请求数据
    Retrofit请求数据对错误以及网络异常的处理
    Retrofit2.0+OkHttp打印Request URL(请求地址参数)
    HUE配置文件hue.ini 的hbase模块详解(图文详解)(分HA集群和非HA集群)
    安装Hue后的一些功能的问题解决干货总结(博主推荐)
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/16145856.html
Copyright © 2020-2023  润新知