huangxz
2026-02-16 6ae9a3490efdc15db0857991413277707a37dea9
修复 ShardingSphere 5.0.0 + Spring Boot 2.x 启动时 algorithm-expression 为 null 的问题,更新本地配置文件以支持新的 sharding-algorithms 配置
1个文件已添加
1个文件已修改
271 ■■■■■ 已修改文件
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/config/ShardingAlgorithmPropsFixer.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/application-local.yml 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/config/ShardingAlgorithmPropsFixer.java
New file
@@ -0,0 +1,87 @@
package com.xiaopeng.maintenance.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.Properties;
/**
 * 修复 ShardingSphere 5.0.0 + Spring Boot 2.x 启动时 algorithm-expression 为 null 的问题。
 *
 * 根因:算法名含下划线(如 xp_clock_in_inline),Spring Boot 2.x 的 Binder 在
 * bind("...xp_clock_in_inline.props") 时抛 InvalidConfigurationPropertyNameException,
 * 导致 ShardingSphere 的 AbstractAlgorithmProvidedBeanRegistry 读取 props 失败。
 *
 * 修复方式:通过顶层 Binder.bind(不含下划线路径段)获取完整算法配置,
 * 然后手动设置到对应 BeanDefinition 的 props 属性中。
 *
 * 该修复对所有环境生效(本地 + Nacos),因为 Binder 下划线问题与配置来源无关。
 */
@Component
public class ShardingAlgorithmPropsFixer implements BeanFactoryPostProcessor, EnvironmentAware, Ordered {
    private static final String ALGO_PREFIX = "spring.shardingsphere.rules.sharding.sharding-algorithms";
    private Environment environment;
    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
    @Override
    @SuppressWarnings("unchecked")
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String, Object> algorithms;
        try {
            algorithms = Binder.get(environment)
                    .bind(ALGO_PREFIX, Map.class)
                    .orElse(null);
        } catch (Exception e) {
            return;
        }
        if (algorithms == null) {
            return;
        }
        for (Map.Entry<String, Object> entry : algorithms.entrySet()) {
            String algoName = entry.getKey();
            Object value = entry.getValue();
            if (!(value instanceof Map)) {
                continue;
            }
            if (!beanFactory.containsBeanDefinition(algoName)) {
                continue;
            }
            Map<String, Object> algoConfig = (Map<String, Object>) value;
            Object propsObj = algoConfig.get("props");
            if (!(propsObj instanceof Map)) {
                continue;
            }
            Map<String, Object> propsMap = (Map<String, Object>) propsObj;
            Properties props = new Properties();
            for (Map.Entry<String, Object> pe : propsMap.entrySet()) {
                if (pe.getValue() != null) {
                    props.put(pe.getKey(), pe.getValue().toString());
                }
            }
            BeanDefinition bd = beanFactory.getBeanDefinition(algoName);
            bd.getPropertyValues().addPropertyValue("props", props);
        }
    }
}
xp-robotaxi-maintenance-boot/src/main/resources/application-local.yml
@@ -81,133 +81,141 @@
      sharding:
        tables:
          xp_charging_record:
            standard:
              sharding-column: vehicle_id
              sharding-algorithm-name: xp_charging_record_inline
            actual-data-nodes: xp0.xp_charging_record_$->{0..19}
            table-strategy:
              standard:
                sharding-column: vehicle_id
                sharding-algorithm-name: xp_charging_record_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_clock_in:
            standard:
              sharding-column: app_user_id
              sharding-algorithm-name: xp_clock_in_inline
            actual-data-nodes: xp0.xp_clock_in_$->{0..9}
            table-strategy:
              standard:
                sharding-column: app_user_id
                sharding-algorithm-name: xp_clock_in_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_task:
            standard:
              sharding-column: vehicle_id
              sharding-algorithm-name: xp_task_inline
            actual-data-nodes: xp0.xp_task_$->{0..19}
            table-strategy:
              standard:
                sharding-column: vehicle_id
                sharding-algorithm-name: xp_task_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_task_handle_detail:
            standard:
              sharding-column: task_id
              sharding-algorithm-name: xp_task_handle_detail_inline
            actual-data-nodes: xp0.xp_task_handle_detail_$->{0..19}
            table-strategy:
              standard:
                sharding-column: task_id
                sharding-algorithm-name: xp_task_handle_detail_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_task_handle_detail_routine:
            standard:
              sharding-column: task_id
              sharding-algorithm-name: xp_task_handle_detail_routine_inline
            actual-data-nodes: xp0.xp_task_handle_detail_routine_$->{0..19}
            table-strategy:
              standard:
                sharding-column: task_id
                sharding-algorithm-name: xp_task_handle_detail_routine_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_vehicle_detection:
            standard:
              sharding-column: task_id
              sharding-algorithm-name: xp_vehicle_detection_inline
            actual-data-nodes: xp0.xp_vehicle_detection_$->{0..9}
            table-strategy:
              standard:
                sharding-column: task_id
                sharding-algorithm-name: xp_vehicle_detection_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_vehicle_preparation:
            standard:
              sharding-column: task_id
              sharding-algorithm-name: xp_vehicle_preparation_inline
            actual-data-nodes: xp0.xp_vehicle_preparation_$->{0..9}
            table-strategy:
              standard:
                sharding-column: task_id
                sharding-algorithm-name: xp_vehicle_preparation_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_vehicle_repair:
            standard:
              sharding-column: task_id
              sharding-algorithm-name: xp_vehicle_repair_inline
            actual-data-nodes: xp0.xp_vehicle_repair_$->{0..9}
            table-strategy:
              standard:
                sharding-column: task_id
                sharding-algorithm-name: xp_vehicle_repair_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_work_order:
            standard:
              sharding-column: feedback_user_phone
              sharding-algorithm-name: xp_work_order_inline
            actual-data-nodes: xp0.xp_work_order_$->{0..9}
            table-strategy:
              standard:
                sharding-column: feedback_user_phone
                sharding-algorithm-name: xp_work_order_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_work_order_log:
            standard:
              sharding-column: work_order_id
              sharding-algorithm-name: xp_work_order_log_inline
            actual-data-nodes: xp0.xp_work_order_log_$->{0..19}
            table-strategy:
              standard:
                sharding-column: work_order_id
                sharding-algorithm-name: xp_work_order_log_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
      sharding-algorithms:
        xp_charging_record_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_charging_record_${vehicle_id % 20}
        xp_clock_in_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_clock_in_${app_user_id % 10}
        xp_task_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_task_${vehicle_id % 20}
        xp_task_handle_detail_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_task_handle_detail_${task_id % 20}
        xp_task_handle_detail_routine_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_task_handle_detail_routine_${task_id % 20}
        xp_vehicle_detection_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_vehicle_detection_${task_id % 10}
        xp_vehicle_preparation_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_vehicle_preparation_${task_id % 10}
        xp_vehicle_repair_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_vehicle_repair_${task_id % 10}
        xp_work_order_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_work_order_${feedback_user_phone % 10}
        xp_work_order_log_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_work_order_log_${work_order_id % 20}
        single-table:
          tables:
            - xp0.xp_check_location
            - xp0.xp_fleet
            - xp0.xp_fleet_operations
            - xp0.xp_fleet_vehicle
            - xp0.xp_policy_application
            - xp0.xp_position
            - xp0.xp_scheduling
            - xp0.xp_scheduling_detail
            - xp0.xp_shift
            - xp0.xp_task_rule
            - xp0.xp_task_rule_role
            - xp0.xp_vehicle
            - xp0.xp_vehicle_clean
            - xp0.xp_vehicle_description
        sharding-algorithms:
          xp_charging_record_inline:
            type: INLINE
            props:
              algorithm-expression: xp_charging_record_$->{vehicle_id % 20}
          xp_clock_in_inline:
            type: INLINE
            props:
              algorithm-expression: xp_clock_in_$->{app_user_id % 10}
          xp_task_inline:
            type: INLINE
            props:
              algorithm-expression: xp_task_$->{vehicle_id % 20}
          xp_task_handle_detail_inline:
            type: INLINE
            props:
              algorithm-expression: xp_task_handle_detail_$->{task_id % 20}
          xp_task_handle_detail_routine_inline:
            type: INLINE
            props:
              algorithm-expression: xp_task_handle_detail_routine_$->{task_id % 20}
          xp_vehicle_detection_inline:
            type: INLINE
            props:
              algorithm-expression: xp_vehicle_detection_$->{task_id % 10}
          xp_vehicle_preparation_inline:
            type: INLINE
            props:
              algorithm-expression: xp_vehicle_preparation_$->{task_id % 10}
          xp_vehicle_repair_inline:
            type: INLINE
            props:
              algorithm-expression: xp_vehicle_repair_$->{task_id % 10}
          xp_work_order_inline:
            type: INLINE
            props:
              algorithm-expression: xp_work_order_$->{feedback_user_phone % 10}
          xp_work_order_log_inline:
            type: INLINE
            props:
              algorithm-expression: xp_work_order_log_$->{work_order_id % 20}
        key-generators:
          snowflake:
            type: SNOWFLAKE
      single-table:
        default-data-source-name: xp0
    props:
      sql-show: true
      sql-simple: true