sharding sphere 4.1.1 - 各种表达式的解析器(居于groovy)

1、使用groovy引擎进行处理

.

/**
 * @see org.apache.shardingsphere.core.strategy.route.ShardingStrategyFactory
 */
@Slf4j
public class ExpressionParserTest {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        {
            String actualDataNodes = "demo_sphere_$->{0..1}_test.tb_user_$->{(0..2).collect{t ->t.toString().padLeft(2,'0')}}";
            TableRule tableRule = new TableRule(actualDataNodes);
        }

        {
            // https://juejin.cn/post/6844903977348235271
            String algorithmExpressionStr = "tb_users_$->{(user_id % 3).toString().padLeft(3,\"0\")}";
            // algorithmExpressionStr = "t_user$->{user_id % 3}";

            InlineShardingStrategy shardingStrategy = new InlineShardingStrategy("user_id", algorithmExpressionStr);

            PreciseShardingValue shardingValue = new PreciseShardingValue("tb_users", "user_id", 1);
            String tableName = shardingStrategy.execute(shardingValue);
            log.info("tableName = {}", tableName);
        }

        {
            String actualDataNodes = "demo_sphere_$->{0..1}_test.tb_user_$->{(0..2).collect{t ->t.toString().padLeft(2,'0')}}";
            new GroovyShell().evaluateMain(actualDataNodes);
        }
    }

    static class GroovyShell {
        private static final Map<String, Script> SCRIPTS = new HashMap<>();
        private static final groovy.lang.GroovyShell SHELL = new groovy.lang.GroovyShell();

        public void evaluateMain(String expressionInput) {
            StringBuilder expression = new StringBuilder(InlineExpressionParser.handlePlaceHolder(expressionInput));
            if (!expressionInput.startsWith("\"")) {
                expression.insert(0, "\"");
            }
            if (!expressionInput.endsWith("\"")) {
                expression.append("\"");
            }

            Object segment = evaluate(expression.toString());
            flatten(segment);
        }

        /**
         * @see org.apache.shardingsphere.underlying.common.config.inline.InlineExpressionParser#flatten(java.util.List)
         */
        private void flatten(final Object segment) {
            List<String> result = new ArrayList<>();
            log.info("segment = {}", segment);
            if (segment instanceof GString) {
                result.addAll(assemblyCartesianSegments((GString) segment));
            } else {
                result.add(segment.toString());
            }
            log.info("result = {}", result);
        }

        private Object evaluate(final String expression) {
            Script script;
            if (SCRIPTS.containsKey(expression)) {
                script = SCRIPTS.get(expression);
            } else {
                script = SHELL.parse(expression);
                SCRIPTS.put(expression, script);
            }
            return script.run();
        }

        private List<String> assemblyCartesianSegments(final GString segment) {
            // 笛卡尔积
            Set<List<String>> cartesianValues = getCartesianValues(segment);
            log.info("cartesianValues = {}", cartesianValues);

            //
            List<String> result = new ArrayList<>(cartesianValues.size());
            for (List<String> each : cartesianValues) {
                result.add(assemblySegment(each, segment));
            }
            return result;
        }

        private Set<List<String>> getCartesianValues(final GString segment) {
            List<Set<String>> result = new ArrayList<>(segment.getValues().length);
            log.info("values length = {}", segment.getValues().length);
            log.info("strings length = {}", segment.getStrings().length);
            for (Object each : segment.getValues()) {
                if (null == each) {
                    continue;
                }
                log.info("each = {}", each);
                if (each instanceof Collection) {
                    if (each instanceof groovy.lang.IntRange) ;
                    log.info("each instanceof Collection = {}", true);
                    result.add(Sets.newLinkedHashSet(Collections2.transform((Collection<Object>) each, Object::toString)));
                } else {
                    result.add(Sets.newHashSet(each.toString()));
                }
            }

            // 笛卡尔积
            return Sets.cartesianProduct(result);
        }

        /**
         * 装配字符串
         */
        private String assemblySegment(final List<String> cartesianValue, final GString segment) {
            log.info("cartesianValue = {}, segment = {}", cartesianValue, segment);
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < segment.getStrings().length; i++) {
                result.append(segment.getStrings()[i]);
                if (i < cartesianValue.size()) {
                    result.append(cartesianValue.get(i));
                }
            }
            return result.toString();
        }
    }

    /**
     * @see org.apache.shardingsphere.core.rule.TableRule
     */
    static class TableRule {

        public TableRule(String actualDataNodes) {
            List<String> dataNodes = new InlineExpressionParser(actualDataNodes).splitAndEvaluate();
            log.info("dataNodes = {}", dataNodes);
        }

    }

    /**
     * @see org.apache.shardingsphere.core.strategy.route.inline.InlineShardingStrategy
     */
    static class InlineShardingStrategy {
        private final String shardingColumn;
        private final Closure<?> closure;

        public InlineShardingStrategy(final String shardingColumn, final String algorithmExpressionStr) {
            this.shardingColumn = shardingColumn;

            String algorithmExpression = InlineExpressionParser.handlePlaceHolder(algorithmExpressionStr.trim());
            closure = new InlineExpressionParser(algorithmExpression).evaluateClosure();
        }

        private String execute(final PreciseShardingValue shardingValue) {
            Closure<?> result = closure.rehydrate(new Expando(), null, null);
            result.setResolveStrategy(Closure.DELEGATE_ONLY);
            result.setProperty(shardingColumn, shardingValue.getValue());
            return result.call().toString();
        }
    }
}

.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值