mybatis 中文路径报错处理


若依开源项目:https://gitee.com/markbro/ruoyi-plus

当你从本地启动,项目有中文路径的时候,启动报错,报错内容如下:

Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -21
at java.lang.String.substring(String.java:1931)
at org.mybatis.spring.boot.autoconfigure.SpringBootVFS.preserveSubpackageName(SpringBootVFS.java:61)
at org.mybatis.spring.boot.autoconfigure.SpringBootVFS.lambda$list$0(SpringBootVFS.java:53)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at org.mybatis.spring.boot.autoconfigure.SpringBootVFS.list(SpringBootVFS.java:54)
at org.apache.ibatis.io.VFS.list(VFS.java:205)
at org.apache.ibatis.io.ResolverUtil.find(ResolverUtil.java:220)
at org.apache.ibatis.type.TypeAliasRegistry.registerAliases(TypeAliasRegistry.java:130)
at org.mybatis.spring.SqlSessionFactoryBean.buildSqlSessionFactory(SqlSessionFactoryBean.java:434)
at org.mybatis.spring.SqlSessionFactoryBean.afterPropertiesSet(SqlSessionFactoryBean.java:380)
at org.mybatis.spring.SqlSessionFactoryBean.getObject(SqlSessionFactoryBean.java:547)
at com.ruoyi.framework.config.MyBatisConfig.sqlSessionFactory(MyBatisConfig.java:109)
at com.ruoyi.framework.config.MyBatisConfig$$EnhancerBySpringCGLIB$$d02fa549.CGLIB$sqlSessionFactory$0()
at com.ruoyi.framework.config.MyBatisConfig$$EnhancerBySpringCGLIB$$d02fa549$$FastClassBySpringCGLIB$$f8eab79a.invoke()
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at com.ruoyi.framework.config.MyBatisConfig$$EnhancerBySpringCGLIB$$d02fa549.sqlSessionFactory()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 104 common frames omitted

问题解决:

1. 分析问题:

报错代码位置:

return sessionFactory.getObject();

、、、

return rootPath + (rootPath.endsWith("/") ? "" : "/")
+ resource.getURL().toString().substring(baseUrlString.length());
通过这些错误能判断出是中文路径影响的。
第一种解决方案:最简单的办法就是将项目放到英文路径下就不会出现问题。
第二种解决方案:Mybatis的版本 1.3.2 对于中文路径没有问题,目前这个版本是2.2.0。 这两个版本里面的SpringBootVFS这个类的实现方法不一样。
第三种解决方案:

 去掉这行代码也行。

    第四种解决方案:自己写一个SpringBootVFS类。

package com.ruoyi.framework.config.properties;

import org.apache.ibatis.io.VFS;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


public class SpringBootVFSFilter extends VFS {

private final ResourcePatternResolver resourceResolver;

public SpringBootVFSFilter() {
this.resourceResolver = new PathMatchingResourcePatternResolver(getClass().getClassLoader());
}

@Override
public boolean isValid() {
return true;
}

@Override
protected List list(URL url, String path) throws IOException {
Resource[] resources = resourceResolver.getResources("classpath*:" + path + "/**/*.class");
List resourcePaths = new ArrayList();
for (Resource resource : resources) {
resourcePaths.add(preserveSubpackageName(resource.getURI(), path));
}
return resourcePaths;
}

private static String preserveSubpackageName(final URI uri, final String rootPath) {
final String uriStr = uri.toString();
final int start = uriStr.indexOf(rootPath);
return uriStr.substring(start);
}

}
然后在

 在这块加入进去。

完毕。