Springboot Mybatis 打包jar扫描bean与mapper问题研究与解决
SpringBootLean 是对springboot学习与研究项目,是根据实际项目的形式对进行配置与处理,欢迎star与fork。
[oschina 地址]
http://git.oschina.net/cmlbeliever/SpringBootLearning
[github 地址]
https://github.com/cmlbeliever/SpringBootLearning
最近在项目中集成以全注解的方式Mybatis,配置了自动bean包与mapper所在包
db.mybatis.mapperLocations=classpath*:com/cml/springboot/sample/db/resource/*
db.mybatis.typeAliasesPackage=com.cml.springboot.sample.bean
db.mybatis.typeHandlerPackage=com.cml.springboot.framework.mybatis.typehandler
这些配置直接在ide上运行都是ok的,但是经过打包成jar包后,就一直报错提示找打不到对应的bean或者对应的mapper。主要错误如下:
Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'logbean'. Cause: java.lang.ClassNotFoundException: Cannot find class: logbean
***************************
APPLICATION FAILED TO START
***************************
Description:
Field logMapper in com.cml.springboot.sample.service.impl.LogServiceImpl required a bean of type 'com.cml.springboot.sample.db.LogMapper' that could not be found.
Action:
Consider defining a bean of type 'com.cml.springboot.sample.db.LogMapper' in your configuration.
针对以上问题,在新开的分支deploy_jar_bugfind上进行研究,找到了一个临时解决办法,就是配置mybat-configuration.xml将对应的bean都配置到xml上。
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<typeAliases>
<typeAlias type="com.cml.springboot.sample.bean.LogBean" alias="logbean"/>
<typeAlias type="com.cml.springboot.sample.bean.User" alias="user"/>
</typeAliases>
<typeHandlers>
<typeHandler javaType="org.joda.time.DateTime"
handler="com.cml.springboot.framework.mybatis.typehandler.JodaDateTimeTypeHandler" />
<typeHandler javaType="org.joda.time.LocalTime"
handler="com.cml.springboot.framework.mybatis.typehandler.JodaLocalTimeTypeHandler" />
</typeHandlers>
</configuration>
但是这个仅仅适合小项目并且bean少的情况,假如在打项目上,可能有几十上百的bean,都要一一配置岂不是累死人了,而且容易出bug。
于是继续研究,首先自定义DefaultSqlSessionFactoryBean取代默认的SqlSessionFactoryBean,并且在buildSqlSessionFactory()方法上对bean扫描的配置进行一步步log拆分,主要代码如下:
if (hasLength(this.typeAliasesPackage)) {
String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
for (String packageToScan : typeAliasPackageArray) {
logger.debug("##################################################################################");
List<String> children = VFS.getInstance().list(packageToScan.replace(".", "/"));
logger.debug("findclass:" + children);
logger.debug("##################################################################################");
logger.debug("DefaultSqlSessionFactoryBean.buildSqlSessionFactory.registerAliases:" + packageToScan);
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
resolverUtil.find(new ResolverUtil.IsA(Object.class), packageToScan);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
logger.debug(
"DefaultSqlSessionFactoryBean.buildSqlSessionFactory.typeAliasesPackage.scanClass:" + typeSet);
for (Class<?> type : typeSet) {
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
String alias = type.getSimpleName();
String key = alias.toLowerCase(Locale.ENGLISH);
logger.debug(
"DefaultSqlSessionFactoryBean.buildSqlSessionFactory.typeAliasesPackage.scan:" + key);
}
}
configuration.getTypeAliasRegistry().registerAliases(packageToScan,
typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Scanned package: '" + packageToScan + "' for aliases");
}
}
}
发现在ide上运行的时候是可以扫描到指定的bean,但是在jar上就扫描不到了。主要问题找到了,就是对代码的扫描问题,原本想自定义configuration的,但是发现好多类都是依赖configuration这个类,于是便放弃这个想法,转而研究扫描不到bean的问题。
继续研究源码,得知bean的扫描是通过ResolverUtil这个类进行的,并且ResolverUtil扫描是通过VFS进行扫描的,主要代码:
public ResolverUtil<T> find(Test test, String packageName) {
String path = getPackagePath(packageName);
try {
List<String> children = VFS.getInstance().list(path);
for (String child : children) {
if (child.endsWith(".class"))
addIfMatching(test, child);
}
} catch (IOException ioe) {
log.error("Could not read package: " + packageName, ioe);
}
return this;
}
结合log上的信息,工程上默认使用的是Mybatis的DefaultVFS进行扫描。查看这个类代码后也没发现什么问题,转而求救于百度与谷歌,经过多方搜索,找到了Mybatis官网issue (地址:https://github.com/mybatis/mybatis-3/issues/325)这里有对这些问题进行说明。根据issue的描述与各大神的回答,定位到了问题是DefaultVFS在获取jar上的class问题。
在mybat/spring-boot-starter工程上找到了SpringBootVFS,这个类重写了class扫描功能,通过spring进行扫描。
于是将SpringBootVFS拷贝到工程上,并且添加到VFS实现上去,代码如下:
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DataSource datasource, MybatisConfigurationProperties properties)
throws Exception {
log.info("*************************sqlSessionFactory:begin***********************" + properties);
VFS.addImplClass(SpringBootVFS.class);
DefaultSqlSessionFactoryBean sessionFactory = new DefaultSqlSessionFactoryBean();
sessionFactory.setDataSource(datasource);
sessionFactory.setTypeAliasesPackage(properties.typeAliasesPackage);
sessionFactory.setTypeHandlersPackage(properties.typeHandlerPackage);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources(properties.mapperLocations));
// sessionFactory
// .setConfigLocation(new PathMatchingResourcePatternResolver().getResource(properties.configLocation));
SqlSessionFactory resultSessionFactory = sessionFactory.getObject();
log.info("===typealias==>" + resultSessionFactory.getConfiguration().getTypeAliasRegistry().getTypeAliases());
log.info("*************************sqlSessionFactory:successs:" + resultSessionFactory
+ "***********************" + properties);
return resultSessionFactory;
}
这样mybaits打包jar后扫描问题完美解决。
综上,解决SpringBoot Mybatis打包jar后问题处理完毕,已提交到git项目master分支和deploy_jar_bugfind
http://git.oschina.net/cmlbeliever/SpringBootLearning
解决办法:
- 通过mybatis-configuration.xml进行配置
- 通过SpringBootVFS进行自动扫描配置(推荐)
Springboot Mybatis 打包jar扫描bean与mapper问题研究与解决的更多相关文章
- SpringBoot 项目打包后获取不到resource下资源的解决
SpringBoot 项目打包后获取不到resource下资源的解决 在项目中有几个文件需要下载,然后不想暴露真实路径,又没有CDN,便决定使用接口的方式来获取文件.最初的时候使用了传统的方法来获取文 ...
- (二十二)SpringBoot之使用mybatis generator自动生成bean、mapper、mapper xml
一.下载mybatis generator插件 二.生成generatorConfig.xml new一个generatorConfig.xml 三.修改generatorConfig.xml 里面的 ...
- SpringBoot Maven多模块整合MyBatis 打包jar
最近公司开始新的项目,框架选定为SpringBoot+Mybatis,本篇主要记录了在IDEA中搭建SpringBoot多模块项目的过程. 源码:https://github.com/12641561 ...
- SpringBoot引入第三方jar的Bean的三种方式
在SpringBoot的大环境下,基本上很少使用之前的xml配置Bean,主要是因为这种方式不好维护而且也不够方便. 因此本篇博文也不再介绍Spring中通过xml来声明bean的使用方式. 一.注解 ...
- 关于用maven创建的springboot工程打包jar后找不到配置文件的问题
你的resources文件夹的名称写错了!!! 如果不在pom中配置build的资源路径,那么你的资源文件名必须默认是“resources”! 解决办法有两个: 1.修改文件夹名称 2.添加pom的b ...
- SpringBoot环境下使用测试类注入Mapper接口报错解决
当我们在进行开发中难免会要用到测试类,而且测试类要注入Mapper接口,如果测试运行的时候包空指针异常,看看测试类上面的注解是否用对! 正常测试我们需要用到的注解有这些: @SpringBootTes ...
- springboot linux打包后访问不到resources 下面的模板文件
在本地是可以直接获取模板文件并下载,但是服务器上就不行 本地代码: @Overridepublic void downArchRelayTemplate(HttpServletRequest requ ...
- DB数据源之SpringBoot+MyBatis踏坑过程(二)手工配置数据源与加载Mapper.xml扫描
DB数据源之SpringBoot+MyBatis踏坑过程(二)手工配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许进制转载 吐槽之后应该有所改了,该方式可以作为一种过渡方式 ...
- DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描
DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许禁止转载 系列目录连接 DB数据源之Spr ...
随机推荐
- Java多台中成员访问特点
多态中的成员访问特点: A:成员变量 编译看左边,运行看左边 B:构造方法 创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化 C:成员方法 编译看左边,运行看右边.//因为调用对象时,子 ...
- 负载均衡服务之HAProxy基础配置(四)
前文我们聊了haproxy的状态页配置,状态页中显示各参数的含义,以及基于cookie做会话保持的配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12776 ...
- Xshell下载和连接Linux
Xshell下载和连接Linux 第一步.Xshell的下载 方法1:从官网下载个人使用时免费的,商业使用是要收费的. http://www.xshellcn.com/ 方法二2:百度云下载Xshel ...
- Windows Server挂载NFS共享
NFS:即为网络文件系统. 主要功能:通过网络(局域网)让不同的主机系统之间可以共享文件或目录. 主要用途:NFS网络文件系统一般被用来存储共享视频,图片,附件等静态资源文件. 关于端口使用说明: 1 ...
- http协议请求流程分析
http协议请求流程分析 用户输入URL(地址链接)(http://www.baidu.com:80/tools.html)客户端获取到端口及主机名后,客户端利用DNS解析域名,首先客户端的浏览器会先 ...
- 配置IIS5.5/6.0 支持 Silverlight
在安装完Silverlight1.1 Alpha后,要使自己的IIS服务器支持Silverlight的浏览还需要配置一下IIS网站的 Http头->MIME映射添加内容如下:扩展名 ...
- POJ2389 Bull Math【大数】
Bull Math Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15040 Accepted: 7737 Descri ...
- SQL Server 字段和对应的说明操作(SQL Server 2005 +)
为什么80%的码农都做不了架构师?>>> 添加说明 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value ...
- mysql建立ssl安全连接的配置
mysql建立ssl安全连接的配置 1.环境.IP.安装包: centOS 5.4 虚拟机了两台服务器 mysql-5.1.48.tar.gz openssl-0.9.8b.tar.gz server ...
- 算法竞赛进阶指南--在单调递增序列a中查找>=x的数中最小的一个(即x或x的后继)
while (l < r) { int mid = (l + r) / 2; if (a[mid] >= x) r = mid; else l = mid + 1; }