搭建好的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了。