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();
}
}
}
.