【soul-admin】SpringCloud元数据注册

在SoulClientController中提供了如下接口:

/**
* Register spring cloud string.
*
* @param springCloudRegisterDTO the spring cloud register dto
* @return the string
*/
@PostMapping("/springcloud-register")
public String registerSpringCloud(@RequestBody final SpringCloudRegisterDTO springCloudRegisterDTO) {
    return soulClientRegisterService.registerSpringCloud(springCloudRegisterDTO);
}

调用了下述方法

@Override
@Transactional
public synchronized String registerSpringCloud(final SpringCloudRegisterDTO dto) {
    MetaDataDO metaDataDO = metaDataMapper.findByPath(dto.getContext() + "/**");
    if (Objects.isNull(metaDataDO)) {
        saveSpringCloudMetaData(dto); // 元数据不存在,则保存SpringClloud元数据到数据库
    }
    String selectorId = handlerSpringCloudSelector(dto); // 处理其中选择器数据
    handlerSpringCloudRule(selectorId, dto); // 处理规则数据
    return SoulResultMessage.SUCCESS;
}

元数据储存

private void saveSpringCloudMetaData(final SpringCloudRegisterDTO dto) {
    Timestamp currentTime = new Timestamp(System.currentTimeMillis());
    MetaDataDO metaDataDO = MetaDataDO.builder()
        .appName(dto.getAppName())
        .path(dto.getContext() + "/**")
        .pathDesc(dto.getAppName() + "spring cloud meta data info")
        .serviceName(dto.getAppName())
        .methodName(dto.getContext())
        .rpcType(dto.getRpcType())
        .enabled(dto.isEnabled())
        .id(UUIDUtils.getInstance().generateShortUuid())
        .dateCreated(currentTime)
        .dateUpdated(currentTime)
        .build();
    metaDataMapper.insert(metaDataDO); // 入库
    // publish AppAuthData's event
    eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.META_DATA, DataEventTypeEnum.CREATE, Collections.singletonList(MetaDataTransfer.INSTANCE.mapToData(metaDataDO)))); // 发送元数据变更事件
}

选择器数据更新 

private String handlerSpringCloudSelector(final SpringCloudRegisterDTO dto) {
    String contextPath = dto.getContext();
    SelectorDO selectorDO = selectorService.findByName(contextPath);
    if (Objects.isNull(selectorDO)) {
        return registerSelector(contextPath, dto.getRpcType(), dto.getAppName(), ""); // 入库变更
    } else {
        return selectorDO.getId();
    }
}

private String registerSelector(final String contextPath, final String rpcType, final String appName, final String uri) {
    SelectorDTO selectorDTO = SelectorDTO.builder()
        .name(contextPath)
        .type(SelectorTypeEnum.CUSTOM_FLOW.getCode())
        .matchMode(MatchModeEnum.AND.getCode())
        .enabled(Boolean.TRUE)
        .loged(Boolean.TRUE)
        .continued(Boolean.TRUE)
        .sort(1)
        .build();
    if (RpcTypeEnum.DUBBO.getName().equals(rpcType)) {
        selectorDTO.setPluginId(getPluginId(PluginEnum.DUBBO.getName()));
    } else if (RpcTypeEnum.SPRING_CLOUD.getName().equals(rpcType)) {
        selectorDTO.setPluginId(getPluginId(PluginEnum.SPRING_CLOUD.getName()));
        selectorDTO.setHandle(GsonUtils.getInstance().toJson(buildSpringCloudSelectorHandle(appName)));
    } else if (RpcTypeEnum.SOFA.getName().equals(rpcType)) {
        selectorDTO.setPluginId(getPluginId(PluginEnum.SOFA.getName()));
        selectorDTO.setHandle(appName);
    } else if (RpcTypeEnum.TARS.getName().equals(rpcType)) {
        selectorDTO.setPluginId(getPluginId(PluginEnum.TARS.getName()));
        selectorDTO.setHandle(appName);
    } else {
        //is divide
        DivideUpstream divideUpstream = buildDivideUpstream(uri);
        String handler = GsonUtils.getInstance().toJson(Collections.singletonList(divideUpstream));
        selectorDTO.setHandle(handler);
        selectorDTO.setPluginId(getPluginId(PluginEnum.DIVIDE.getName()));
        upstreamCheckService.submit(selectorDTO.getName(), divideUpstream);
    }
    SelectorConditionDTO selectorConditionDTO = new SelectorConditionDTO();
    selectorConditionDTO.setParamType(ParamTypeEnum.URI.getName());
    selectorConditionDTO.setParamName("/");
    selectorConditionDTO.setOperator(OperatorEnum.MATCH.getAlias());
    selectorConditionDTO.setParamValue(contextPath + "/**");
    selectorDTO.setSelectorConditions(Collections.singletonList(selectorConditionDTO));
    return selectorService.register(selectorDTO);
}

@Override
public String register(final SelectorDTO selectorDTO) {
    SelectorDO selectorDO = SelectorDO.buildSelectorDO(selectorDTO);
    List<SelectorConditionDTO> selectorConditionDTOs = selectorDTO.getSelectorConditions();
    if (StringUtils.isEmpty(selectorDTO.getId())) {
        selectorMapper.insertSelective(selectorDO);
        selectorConditionDTOs.forEach(selectorConditionDTO -> {
        selectorConditionDTO.setSelectorId(selectorDO.getId());
            selectorConditionMapper.insertSelective(SelectorConditionDO.buildSelectorConditionDO(selectorConditionDTO)); // 入库
        });
    }
    publishEvent(selectorDO, selectorConditionDTOs); // 发布事件
    return selectorDO.getId();
}

Rule数据注册 

private void handlerSpringCloudRule(final String selectorId, final SpringCloudRegisterDTO dto) {
    RuleDO ruleDO = ruleMapper.findByName(dto.getRuleName());
    if (Objects.isNull(ruleDO)) {
        registerRule(selectorId, dto.getPath(), dto.getRpcType(), dto.getRuleName());
    }
}

private void registerRule(final String selectorId, final String path, final String rpcType, final String ruleName) {
    RuleHandle ruleHandle = RuleHandleFactory.ruleHandle(RpcTypeEnum.acquireByName(rpcType), path);
    RuleDTO ruleDTO = RuleDTO.builder()
        .selectorId(selectorId)
        .name(ruleName)
        .matchMode(MatchModeEnum.AND.getCode())
        .enabled(Boolean.TRUE)
        .loged(Boolean.TRUE)
        .sort(1)
        .handle(ruleHandle.toJson())
        .build();
    RuleConditionDTO ruleConditionDTO = RuleConditionDTO.builder()
        .paramType(ParamTypeEnum.URI.getName())
        .paramName("/")
        .paramValue(path)
        .build();
    if (path.indexOf("*") > 1) {
        ruleConditionDTO.setOperator(OperatorEnum.MATCH.getAlias());
    } else {
        ruleConditionDTO.setOperator(OperatorEnum.EQ.getAlias());
    }
    ruleDTO.setRuleConditions(Collections.singletonList(ruleConditionDTO));
    ruleService.register(ruleDTO);
}

@Override
public String register(final RuleDTO ruleDTO) {
    RuleDO ruleDO = RuleDO.buildRuleDO(ruleDTO);
    List<RuleConditionDTO> ruleConditions = ruleDTO.getRuleConditions();
    if (StringUtils.isEmpty(ruleDTO.getId())) {
        ruleMapper.insertSelective(ruleDO);
        ruleConditions.forEach(ruleConditionDTO -> {
        ruleConditionDTO.setRuleId(ruleDO.getId());
            ruleConditionMapper.insertSelective(RuleConditionDO.buildRuleConditionDO(ruleConditionDTO)); // 入库
            });
    }
    publishEvent(ruleDO, ruleConditions); // 发布规则变更事件
    return ruleDO.getId();
}

而在客户端,【soul-bootstrap】需要向【soul-admin】注册数据

对于普通的的请求,需要在 SpringCloudClientBeanPostProcessor 中使用 BeanPostProcessor 后置处理进行注册请求

如果配置了full,则使用Spring事件机制,进行全局注册。

/**
* The type Soul spring cloud client configuration.
*
* @author xiaoyu
*/
@Configuration
public class SoulSpringCloudClientConfiguration {
    /**
    * Spring cloud client bean post processor spring cloud client bean post processor.
    *
    * @param soulSpringCloudConfig the soul spring cloud config
    * @param env the env
    * @return the spring cloud client bean post processor
    */
    @Bean
    public SpringCloudClientBeanPostProcessor springCloudClientBeanPostProcessor(final SoulSpringCloudConfig soulSpringCloudConfig, final Environment env) {
        return new SpringCloudClientBeanPostProcessor(soulSpringCloudConfig, env);
    }

    /**
    * Context register listener context register listener.
    *
    * @param soulSpringCloudConfig the soul spring cloud config
    * @param env the env
    * @return the context register listener
    */
    @Bean
    public ContextRegisterListener contextRegisterListener(final SoulSpringCloudConfig soulSpringCloudConfig, final Environment env) {
        return new ContextRegisterListener(soulSpringCloudConfig, env);
    }

    /**
    * Soul spring cloud config soul spring cloud config.
    *
    * @return the soul spring cloud config
    */
    @Bean
    @ConfigurationProperties(prefix = "soul.springcloud")
    public SoulSpringCloudConfig soulSpringCloudConfig() {
        return new SoulSpringCloudConfig();

    }
}

@Slf4j

public class SpringCloudClientBeanPostProcessor implements BeanPostProcessor {
    private final ThreadPoolExecutor executorService;

    private final String url;

    private final SoulSpringCloudConfig config;

    private final Environment env;

    /**
    * Instantiates a new Soul client bean post processor.
    *
    * @param config the soul spring cloud config
    * @param env the env
    */
    public SpringCloudClientBeanPostProcessor(final SoulSpringCloudConfig config, final Environment env) {
        ValidateUtils.validate(config, env);
        this.config = config;
        this.env = env;
        this.url = config.getAdminUrl() + "/soul-client/springcloud-register";
        executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
    }

    @Override
    public Object postProcessAfterInitialization(@NonNull final Object bean, @NonNull final String beanName) throws BeansException {
        if (config.isFull()) {
            return bean;
        }
        Controller controller = AnnotationUtils.findAnnotation(bean.getClass(), Controller.class);
        RestController restController = AnnotationUtils.findAnnotation(bean.getClass(), RestController.class);
        RequestMapping requestMapping = AnnotationUtils.findAnnotation(bean.getClass(), RequestMapping.class);
        if (controller != null || restController != null || requestMapping != null) {
            String prePath = "";
            SoulSpringCloudClient clazzAnnotation = AnnotationUtils.findAnnotation(bean.getClass(), SoulSpringCloudClient.class);
            if (Objects.nonNull(clazzAnnotation)) {
                if (clazzAnnotation.path().indexOf("*") > 1) {
                    String finalPrePath = prePath;
                    executorService.execute(() -> RegisterUtils.doRegister(buildJsonParams(clazzAnnotation, finalPrePath), url, RpcTypeEnum.SPRING_CLOUD));
                    return bean;
                }
                prePath = clazzAnnotation.path();
            }
            final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(bean.getClass());
            for (Method method : methods) {
                SoulSpringCloudClient soulSpringCloudClient = AnnotationUtils.findAnnotation(method, SoulSpringCloudClient.class);
                if (Objects.nonNull(soulSpringCloudClient)) {
                    String finalPrePath = prePath;
                    executorService.execute(() -> RegisterUtils.doRegister(buildJsonParams(soulSpringCloudClient, finalPrePath), url, RpcTypeEnum.SPRING_CLOUD));
                }
            }
        }
        return bean;
    }

    private String buildJsonParams(final SoulSpringCloudClient soulSpringCloudClient, final String prePath) {
        String contextPath = config.getContextPath();
        String appName = env.getProperty("spring.application.name");
        String path = contextPath + prePath + soulSpringCloudClient.path();
        String desc = soulSpringCloudClient.desc();
        String configRuleName = soulSpringCloudClient.ruleName();
        String ruleName = ("".equals(configRuleName)) ? path : configRuleName;
        SpringCloudRegisterDTO registerDTO = SpringCloudRegisterDTO.builder()
            .context(contextPath)
            .appName(appName)
            .path(path)
            .pathDesc(desc)
            .rpcType(soulSpringCloudClient.rpcType())
            .enabled(soulSpringCloudClient.enabled())
            .ruleName(ruleName)
            .build();
        return OkHttpTools.getInstance().getGson().toJson(registerDTO);
    }
}

@Slf4j
public class ContextRegisterListener implements ApplicationListener<ContextRefreshedEvent> {
    private final AtomicBoolean registered = new AtomicBoolean(false);
    private final String url;
    private final SoulSpringCloudConfig config;
    private final Environment env;

    /**
    * Instantiates a new Context register listener.
    *
    * @param config the soul spring cloud config
    * @param env the env
    */
    public ContextRegisterListener(final SoulSpringCloudConfig config, final Environment env) {
        ValidateUtils.validate(config, env);
        this.config = config;
        this.env = env;
        this.url = config.getAdminUrl() + "/soul-client/springcloud-register";
    }

    @Override
    public void onApplicationEvent(final ContextRefreshedEvent contextRefreshedEvent) {
        if (!registered.compareAndSet(false, true)) {
            return;
        }
        if (config.isFull()) {
            RegisterUtils.doRegister(buildJsonParams(), url, RpcTypeEnum.SPRING_CLOUD);
        }
    }

    private String buildJsonParams() {
        String contextPath = config.getContextPath();
        String appName = env.getProperty("spring.application.name");
        String path = contextPath + "/**";
        SpringCloudRegisterDTO registerDTO = SpringCloudRegisterDTO.builder()
            .context(contextPath)
            .appName(appName)
            .path(path)
            .rpcType(RpcTypeEnum.SPRING_CLOUD.getName())
            .enabled(true)
            .ruleName(path)
            .build();
        return OkHttpTools.getInstance().getGson().toJson(registerDTO);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值