[Solved] About the problem that the Sharding-JDBC data source configuration has an underline error

Directory

    • foreword
    • Preamble
    • failure to reproduce
    • Debugging Tour
    • disprove

Foreword

Here is an exploration of the problems that cannot be read after the data source is configured with underscores. In the last article, I emphasized this issue in the article, and it was ambiguous on the Internet. The official documentation did not give detailed instructions, so I spent some time debugging and I have a little experience, and share it here!

Previous text

“Sharding-JDBC Simple Use”
“Sharding-JDBC Master-Sub-Table (Binding Table) Association”
“Sharding-JDBC read-write separation configuration”

Recurrence of failure

In the configuration file, I set an underscore to the data source name, and then reported an error


According to the principle of code debugging, where to click where.

Debug Tour

We look here, which is where the data source is placed org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration.setEnvironment

Map dataSourceProps = (Map)PropertyUtil.handle(environment, prefix + dataSourceName.trim(), Map.class);

This line of code reports an error below, indicating that the problem is thrown from here! ! !
Debugging the code is to do it again and again (who told me to cook, I can only do this, if you have the ability to read the code, it will be better!)


springboot1.x goes to v1, springboot2.x goes to v2, this is not the point

 @SneakyThrows
    private static Object v2(final Environment environment, final String prefix, final Class<?> targetClass) {<!-- -->
        Class<?> binderClass = Class.forName("org.springframework.boot.context.properties.bind.Binder");
        Method getMethod = binderClass.getDeclaredMethod("get", Environment.class);
        Method bindMethod = binderClass.getDeclaredMethod("bind", String.class, Class.class);
        Object binderObject = getMethod.invoke(null, environment);
        String prefixParam = prefix.endsWith(".") ? prefix.substring(0, prefix.length() - 1) : prefix;
        //Here is the key, you can see which method he calls by reflection!
        Object bindResultObject = bindMethod.invoke(binderObject, prefixParam, targetClass);
        Method resultGetMethod = bindResultObject.getClass().getDeclaredMethod("get");
        return resultGetMethod.invoke(bindResultObject);
    }

He calls binder here by reflection

There are many overloads of the bind method in the binder, but it is not important, because he can’t go on at all, indicating that the method that goes in will report an error, so let’s take a closer look

this.bind((ConfigurationPropertyName)ConfigurationPropertyName.of(name), target, (BindHandler)null);

Enter ConfigurationPropertyName.of(name)

all the way into here

look directly here

Elements elements = (new ElementsParser(name, .’, parserCapacity)).parse();

for(int i = 0; i < length; + + i) {<!-- -->
                char ch = this.source.charAt(i);
                if (ch == '[') {<!-- -->
                    if (openBracketCount == 0) {<!-- -->
                        this.add(start, i, type, valueProcessor);
                        start = i + 1;
                        type = ConfigurationPropertyName.ElementType.NUMERICALLY_INDEXED;
                    }

                     + + openBracketCount;
                } else if (ch == ']') {<!-- -->
                    --openBracketCount;
                    if (openBracketCount == 0) {<!-- -->
                        this.add(start, i, type, valueProcessor);
                        start = i + 1;
                        type = ConfigurationPropertyName.ElementType.EMPTY;
                    }
                } else if (!type.isIndexed() & amp; & amp; ch == this.separator) {<!-- -->
                    this.add(start, i, type, valueProcessor);
                    start = i + 1;
                    type = ConfigurationPropertyName.ElementType.EMPTY;
                } else {<!-- -->
                    type = this.updateType(type, ch, i - start);
                }
            }

Directly set the subscript condition of the traversal to 35, which is convenient for you to debug all the time.
https://blog.csdn.net/weixin_43953546/article/details/102807792 Left click on the breakpoint, right click on the input condition

Here we can see that he is traversing the string spring.shardingsphere.datasource.ds0_master, we can probably guess it here, it may be this _, which is illegal here string (guessed correctly)


Breakpoint into the isValidChar method!

In fact, here, we can guess and confirm our guess by looking at the name.

Must be a-z or 0-9 or -, the rest are illegal strings! !

Disprove

Cancel the underline, use a capital M, execute, and an error is reported!