Spring Boot 1.4.2部署Tomcat7遇依赖及MyBatis配置异常求助
我来帮你拆解并解决这两个部署时碰到的问题,这类场景在Spring Boot 1.x搭配Tomcat 7的项目里其实挺常见的,咱们一步步来排查:
一、org.springframework.beans.factory.UnsatisfiedDependencyException 依赖注入失败异常
这个异常的核心是Spring没法给applicationServiceImpl里的applicationDao字段完成依赖注入,根源是applicationDao这个Bean本身创建失败了。给你几个排查方向:
检查Dao层的注解与扫描配置
确保你的applicationDao接口被@Mapper(MyBatis官方注解)或者@Repository(Spring注解)标记了,同时主启动类要通过@MapperScan("com.yourpackage.dao")指定Dao层所在的包路径,让Spring能扫描到这个接口并生成代理Bean。验证MyBatis Mapper XML的配置
如果是用XML编写SQL的话,确认application.properties或application.yml里的mybatis.mapper-locations配置路径正确,比如mybatis.mapper-locations=classpath:mappers/*.xml,而且XML文件确实放在src/main/resources/mappers/目录下,文件名和Dao接口名称对应(比如ApplicationDao.xml对应ApplicationDao.java)。排查Tomcat部署的文件权限与路径
你提到的异常路径里包含OnlineChannelBackend-0.0.1-SNAPSHOT,要确认Tomcat对这个解压后的war包目录有读写权限,避免因为权限不足导致Spring无法读取Bean定义文件。
二、MybatisAutoConfiguration$$EnhancerBySpringCGLIB 抛出NoUniqueBeanDefinitionException
这个异常说明Spring容器里存在多个同类型的Bean,MyBatis的自动配置类不知道该选择哪一个,常见原因和解决办法:
指定主数据源(多数据源场景)
如果你的项目配置了多个数据源,必须给其中一个数据源Bean加上@Primary注解,告诉Spring这是默认优先使用的数据源,这样MyBatis的自动配置就能找到唯一的数据源来创建相关Bean了。示例:@Bean @Primary public DataSource primaryDataSource() { // 主数据源配置 return new DriverManagerDataSource(...); }避免重复配置MyBatis组件
检查是否同时使用了@MapperScan和手动配置的SqlSessionFactory、SqlSessionTemplate,这种重复配置会导致容器里生成多个同类型Bean。建议统一配置方式:要么完全依赖Spring Boot的MyBatis自动配置,要么手动配置所有MyBatis相关Bean,不要混合使用。排查依赖冲突
用Maven的mvn dependency:tree或者Gradle的./gradlew dependencies命令查看项目依赖树,检查是否存在不同版本的MyBatis、Spring Core或Tomcat相关依赖,冲突的版本可能导致Bean创建逻辑混乱,排除掉冲突的依赖即可。
通用排查小贴士
- 查看完整异常栈:不要只停留在顶层异常信息,往下翻嵌套的异常细节,里面会给出更具体的错误原因(比如找不到Mapper XML、数据源连接失败、Bean类型不匹配等)。
- 本地先验证:先在本地用Spring Boot内置的Tomcat运行项目,如果本地正常,那问题大概率出在外部Tomcat的部署配置上(比如war包结构不正确、Tomcat全局JVM参数配置问题)。
- 确认War包结构合规:Spring Boot打包成war包时,主启动类必须继承
SpringBootServletInitializer并重写configure方法,确保外部Tomcat能正确启动Spring应用:@SpringBootApplication public class OnlineChannelBackendApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(OnlineChannelBackendApplication.class); } public static void main(String[] args) { SpringApplication.run(OnlineChannelBackendApplication.class, args); } }
内容的提问来源于stack exchange,提问作者osama yaccoub

