搭建好的Spring boot运行时出现以下问题:
问题一:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified and no embedded datasource could be auto-configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
Process finished with exit code 1
解决方案:
搭建数据库,添加数据库配置信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test spring.datasource.username=root spring.datasource.password=654321 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
所使用的数据库为mysql
问题二:service注入失败
***************************
APPLICATION FAILED TO START
***************************
Description:
Field testInterFace in com.testInterface.TestBootController required a bean of type 'com.testInterface.TestInterface' that could not be found.
Action:
Consider defining a bean of type 'com.testInterface.TestInterface' in your configuration.
根据英文的提示是在配置中找不到一个指定自动注入类型的bean,经过多方排查得出结论: 相信大家对这种异常非常常见,注入失败,这时候问题来了,按照传统的方式,对注入进行检查。service层已经加了@service的注解,怎么还是注入失败了呢,想查看配置文件,发现springboot没有配置文件,那么他是怎么扫描注解的呢?正常情况下加上@Component注解的类会自动被Spring扫描到生成Bean注册到spring容器中,既然他说没找到,也就是该注解被没有被spring识别,问题的核心关键就在application类的注解SpringBootApplication上
这个注解其实相当于下面这一堆注解的效果,其中一个注解就是@Component,在默认情况下只能扫描与控制器在同一个包下以及其子包下的@Component注解,以及能将指定注解的类自动注册为Bean的@Service@Controller和@ Repository
springboot默认按照包顺序注入,所以在创建controller时service还没有注入,springboot不需要传统的xml配置扫描包,只需要添加注解@ComponentScan(basePackages={“com.testInterface”})
注意:红色部分为需要注入的包
问题三:@Autowired注入失败
问题描述:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field userDao in com.lar.testInterface.service.impl.TestInterfaceImpl required a bean of type 'com.lar.testInterface.dao.UserDao' that could not be found.
Action:
Consider defining a bean of type 'com.lar.testInterface.dao.UserDao' in your configuration.
失败注入代码:
解决方案:
controller 是作为控制器被spring 调用的,如果你非要用也得使用@Autowired注入,这样才能得到被spring管理的bean,就没问题了
(一)
SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描!
“Application类”是指SpringBoot项目入口类。这个类的位置很关键:
如果Application类所在的包为:com.boot.app,则只会扫描com.boot.app包及其所有子包,如果service或dao所在包不在com.boot.app及其子包下,则不会被扫描!
即, 把Application类放到dao、service所在包的上级,com.boot.Application
(二)
SpringBoot中Service自动注入很方便,例:
Service.class(接口类)
ServiceImpl.class(实现类)
Controller.class(使用类)
用以上三个类来说一下自动注入:
单项目:分别ServiceImpl头上@Service,Controller中Service对象@Autowired即可享用;
Multi modules 场景,三个(种)类分别在三个module下:
moduleA : Service.class(com.example.moduleA )
moduleB : ServiceImpl.class ( com.example.moduleB )
moduleC : Controller.class ( com.example.moduleC )
此时B依赖A,C依赖A、B,添加好依赖关系。
如何自动注入?
1、接口、实现、使用类,姿势不变,按单项目方式写即可;
2、在moduleC的Application中做手脚!
如果你已经试过scanBasePackages,无论是在@SpringBootApplication方式还是@ComponentScan;
抑或试过@SpringBootApplication、@ComponentScan同时用,当你这么做时,一定是绝望的。
解决办法@SpringBootApplictaion(scanBasePackages="com.example")
核心就是:
Service 及 ServiceImpl均需在com.example包下
因为Service、ServiceImpl同在com.example下(C可以不在),所以我看作是同一次scan过程;
比如若是这样写scanBasePackages={" com.example.moduleA , com.example.moduleB "},则会失败;
当然(@ComponentScan="com.example")也是可以的,因为前者@SpringBootApplication已经包含@ComponentScan;
(三)
mapper(Dao层)
1 package com.demo.mapper; 2 3 import org.apache.ibatis.annotations.Mapper; 4 5 import com.demo.domain.User; 6 7 @Mapper 8 public interface UserMapper { 9 10 public User gYeMian(User u); 11 12 public int sYeMian(User u); 13 14 }
(四)
Application(启动类)
1 package com.demo; 2 3 import org.mybatis.spring.annotation.MapperScan; 4 import org.springframework.boot.SpringApplication; 5 import org.springframework.boot.autoconfigure.SpringBootApplication; 6 7 @SpringBootApplication 8 @MapperScan(value = "com.demo.mapper") 9 public class App 10 { 11 public static void main(String[] args) throws Exception { 12 SpringApplication.run(App.class, args); 13 } 14 }
原因:在mybatis-spring-boot-autoconfigure的jar包中有一个类 MybatisAutoConfiguration,在这个类中的registerBeanDefinitions方法告诉了我们
1 @Override 2 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 3 4 logger.debug("Searching for mappers annotated with @Mapper"); 5 6 ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); 7 8 try { 9 if (this.resourceLoader != null) { 10 scanner.setResourceLoader(this.resourceLoader); 11 } 12 13 List<String> packages = AutoConfigurationPackages.get(this.beanFactory); 14 if (logger.isDebugEnabled()) { 15 for (String pkg : packages) { 16 logger.debug("Using auto-configuration base package '{}'", pkg); 17 } 18 } 19 20 scanner.setAnnotationClass(Mapper.class); 21 scanner.registerFilters(); 22 scanner.doScan(StringUtils.toStringArray(packages)); 23 } catch (IllegalStateException ex) { 24 logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex); 25 } 26 }
(五)
这是由于springBoot启动时,没有扫描到com.lar.testInterface.dao.UserDao ,而在com.lar.testInterface.TestInterface中又使用了@autowired private EnfileDao entFileDao进行装配,所以会发现错误,说没有定义。此时需要在springBoot的启动类上,加个注解:@MapperScan("持久层路径"),这样就会扫描到com.lar.testInterface.dao.UserDao了。