在真實的企業級項目中,一個大的項目會由多個子模塊組成,每一個模塊是一個小的項目,那麼每一個模塊都有本身的父項目,這個時候就不能再依賴spring
提供的父項目了,這時候怎麼辦呢?spring
boot
已經考慮到了這種可能性,下面就來看看怎麼解決的。
單一模塊的時候,咱們會看到咱們的Spring
Boot
項目有個parent
依賴,以下所示:html
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.5.RELEASE</version> <relativePath /> </parent>
在真實的企業級項目中,這部份內容被咱們本身的父模塊佔用了,好比變成了以下:java
<parent> <groupId>org.light4j</groupId> <artifactId>springBoot-basic</artifactId> <version>0.0.1-SNAPSHOT</version> </parent>
這個時候,只須要加以下依賴便可解決原來依賴Spring
Boot
的parent
的問題:git
<dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.4.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
別的部分不須要變更,後面的內容都按照這種方式來進行。github
Spring Boot
一般有一個名爲*Application
的入口類,入口類裏面有一個main
方法,這個main
方法其實就是一個標準的Java
應用的入口。在main
方法中使用SpringApplication.run(HelloApplication.class, args)
,啓動Spring Boot
應用項目。web
@SpringBootApplication
是Spring Boot
的核心註解,它是一個組合註解,對組合註解不瞭解的朋友能夠看前面的文章Spring4.x高級話題(五):組合註解與元註解,SpringBootApplication
源碼以下:redis
@Target({java.lang.annotation.ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Configuration @EnableAutoConfiguration @ComponentScan public @interface SpringBootApplication { public abstract Class<?>[] exclude(); public abstract String[] excludeName(); }
@SpringBootApplication
註解主要組合了@Configuration
,@EnableAutoConfiguration
,@ComponentScan
;若不使用@SpringBootApplication
註解,則能夠在入口類上直接使用@Configuration
,@EnableAutoConfiguration
,@ComponentScan
三個註解的效果是同樣的。
其中@EnableAutoConfiguration
讓Spring
Boot
根據類路徑中的jar
包依賴爲當前項目進行自動配置。spring
例如,添加了spring-boot-starter-web
依賴,會自動添加Tomcat
和Spring MVC
的依賴,那麼Spring
Boot
會對Tomcat
和Spring MVC
進行自動配置。mongodb
又如,添加了spring-boot-starter-jpa
依賴,Spring
Boot
會自動進行JPA
相關的配置。shell
Spring Boot
會自動掃描@SpringBootApplication
所在類的同級包(如org.light4j.springboot.config
)以及下級包裏面的Bean
(若爲JPA
項目還能夠掃描標註@Entity
的實體類)。建議入口類放置在groupId+arctifactID
組合的包名下。數據庫
經過上面的@SpringBootApplication
的源碼能夠看出,關閉特定的自動配置應該使用@SpringBootApplication
註解的exclude
參數,好比要關閉Spring
Boot
對數據源的自動配置,則能夠這樣使用,例如:
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
在Spring Boot
啓動的時候會有一個默認啓動方案,以下圖所示:
若是想把這個圖案修改爲本身的,步驟以下所示:
(1). 在
src/main/resources
下新建一個banner.txt
。
(2). 經過http://patorjk.com/software/taag網站生成字符,如敲入的爲"fffff"
,將網站生成的字符複製到banner.txt
中。
(3). 這時再啓動程序,圖案將變爲以下圖所示:
main
方法裏的內容修改成:SpringApplication application = new SpringApplication(HelloApplication.class); application.setBannerMode(Banner.Mode.OFF); application.run(args);
fluent API
修改成:new SpringApplicationBuilder(HelloApplication.class).bannerMode(Banner.Mode.OFF).run(args);
Spring
Boot
的全局配置文件的做用是對一些默認配置的配置值進行修改。Spring Boot
使用一個全局的配置文件application.properties
或application.yml
進行全局配置,放置在src/main/resources
目錄或者類路徑的/config
下。
Spring Boot
不只支持常規的properties
配置文件,還支持yaml
語言的配置文件。yaml
是以數據爲中心的語言,在配置數據的時候具備面向對象的特徵。
將Tomcat
的默認端口號修改成9090
,並將默認的訪問路徑」/」修改成」/springboot_configFile
「,能夠在application.properties
中添加:
server.port=9090 server.context-path=/springboot_configFile
或者在application.yml
中添加:
server: port:9090 contextPath:/springboot_configFile
從上面的配置能夠看出,在Spring Boot
中,context-path
,contextPath
或者CONTEXT_PATH
形式實際上是相通的。而且,yaml
的配置更簡潔清晰,更多Spring
Boot
經常使用配置請參考官網文檔。
Spring Boot
經過使用starter
pom
使得咱們不須要關注各類依賴庫的處理,不須要具體的配置信息,由Spring
Boot
自動經過classpath
路徑下的類發現須要的Bean
,並織入bean
。
Spring Boot
爲咱們提供了簡化企業級開發絕大多數場景的starter pom
,只要使用了應用場景所須要的starter pom
,相關的技術配置將會消除,就能夠獲得Spring Boot
爲咱們提供的自動配置的Bean
。
官方提供的starter pom
特別多,詳細可參考官網文檔。下面列出部分供參考:
名稱 | 描述 |
---|---|
spring-boot-starter | Spring Boot核心的starter,包含自動配置,日誌,yaml配置文件等的支持 |
spring-boot-starter-actuator | 準生產應用,用來監控和管理應用 |
spring-boot-starter-remote-shell | 提供基於ssh協議的監控和管理 |
spring-boot-starter-amqp | 使用spring-rabbit來支持AMQP |
spring-boot-starter-aop | 使用spring-aop和AspectJ支持面向切面編程 |
spring-boot-starter-batch | 提供對Spring Batch的支持 |
spring-boot-starter-cache | 提供對Spring Cache的支持 |
spring-boot-starter-cloud-connectors | 對雲平臺(Cloud Foundry,Heroku)提供的服務提供簡化的鏈接方式 |
spring-boot-starter-data-elasticsearch | 經過spring-data-elasticsearch對Elasticsearcht提供支持 |
spring-boot-starter-data-gemfire | 經過spring-data-gemfire對GemFire提供支持 |
spring-boot-starter-data-jpa | 對JPA的支持,包含spring-data-jpa,spring-orm和Hibernate |
spring-boot-starter-data-mongodb | 經過spring-data-mongodb對MongoDB提供支持 |
spring-boot-starter-data-rest | 經過spring-data-rest-webmvc將Spring Data respository暴露爲Rest的服務 |
spring-boot-starter-data-solr | 經過spring-data-rest-solr對Apache Solr數據檢索平臺的支持。 |
spring-boot-starter-freemarker | 對FreeMarker模板引擎提供支持 |
spring-boot-starter-groovy-templates | 對Groovy模板引擎提供支持 |
spring-boot-starter-hateoas | 經過spring-hateoas對基於HATEOAS的REST形式的網絡服務的支持 |
spring-boot-starter-hornetq | 經過Hornetq對JMS的支持 |
spring-boot-starter-integration | 對系統集成框架spring-integration的支持 |
spring-boot-starter-jdbc | 對JDBC數據庫的支持 |
spring-boot-starter-jersey | 對Jersery REST形式的網絡服務的支持 |
spring-boot-starter-jta-atomikos | 經過Atomikos對分佈式事務的支持 |
spring-boot-starter-jta-bitronix | 經過Bitronix對分佈式事務的支持 |
spring-boot-starter-mail | 對javax.mail的支持 |
spring-boot-starter-mobile | 對spring-mobile的支持 |
spring-boot-starter-mustache | 對Mustache模板引擎的支持 |
spring-boot-starter-redis | 對鍵值對內存數據庫Redis的支持,包含spring-redis |
spring-boot-starter-security | 對spring-security的支持 |
spring-boot-starter-social-facebook | 經過spring-social-facebook對FaceBook的支持 |
spring-boot-starter-social-linkedin | 經過spring-social-linkedin對LinkedIn的支持 |
spring-boot-starter-social-twitter | 經過spring-social-twitter對Twitter的支持 |
spring-boot-starter-test | 對經常使用的測試框架Junit,Hamcrest和Mockito的支持,包含spring-test模塊 |
spring-boot-starter-thymeleaf | 對Thymeleaf模板引擎的支持,包含於Spring整合的配置 |
spring-boot-starter-velocity | 對Velocity模板引擎的支持 |
spring-boot-starter-web | 對Web項目開發的支持,包含Tomcat和spring-webmvc |
spring-boot-starter-Tomcat | Spring Boot默認的Servlet容器Tomcat |
spring-boot-starter-Jetty | 使用Jetty做爲Servlet容器替換Tomcat |
spring-boot-starter-undertow | 使用Undertow做爲Servlet容器替換Tomcat |
spring-boot-starter-logging | Spring Boot默認的日誌框架Logback |
spring-boot-starter-log4j | 支持使用log4J日誌框架 |
spring-boot-starter-websocket | 對WebSocket開發的支持 |
spring-boot-starter-ws | 對Spring Web Services的支持 |
除了官方starter pom
外,還有第三方爲Spring
Boot
所寫的starter pom
,以下圖所示:
名稱 | 地址 |
---|---|
Handlebars | https://github.com/allegro/handlebars-spring-boot-starter |
Vaadin | https://github.com/vaadin/spring/tree/master/vaadin-spring-boot-starter |
Apache Camel | https://github.com/apache/camel/tree/master/components/camel-spring-boot |
WRO4J | https://github.com/sbuettner/spring-boot-autoconfigure-wro4j |
Spring Batch(高級用法) | https://github.com/codecentric/spring-boot-starter-batch-web |
HDIV | https://github.com/hdiv/spring-boot-starter-hdiv |
Jade Templates (Jadw4j) | https://github.com/domix/spring-boot-starter-jade4j |
Activiti | https://github.com/Activiti/Activiti/tree/master/modules/activiti-spring-boot/spring-boot-starte |
若是有須要咱們也能夠編寫本身的starter
pom
。
Spring Boot
提倡零配置,即無xml
配置,可是在實際項目中,可能有一些特殊要求你必須使用xml
配置,這時候能夠經過在配置類上面使用Spring
提供的@ImportResource
來在加載xml
配置,例如:
@ImportResource(value = { "classpath:some-context.xml","classpath:another-context.xml" })
新建兩個包:org.light4j.springboot.xml.scan
和org.light4j.springboot.xml.noScan
新建Application.java
啓動類,放到包org.light4j.springboot.xml.scan
下,根據Spring
Boot
的掃描原則(掃描從根包到子包的原則),可以掃描到org.light4j.springboot.xml.scan
以及它的子包,org.light4j.springboot.xml.noScan
包以及子包則不能被掃描到,代碼以下:
package org.light4j.springboot.xml.scan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
新建ScanService
和NoScanService
兩個Service
類,根據Spring
Boot
的掃描原則,咱們把ScanService
寫在Spring
Boot
能夠掃描的位置,也即放到包org.light4j.springboot.xml.scan
下,NoScanService
寫在Spring
Boot
沒法掃描到的位置,也即放到包org.light4j.springboot.xml.noScan
下。ScanService.java
代碼以下所示:
package org.light4j.springboot.xml.scan; import org.springframework.stereotype.Service; @Service public class ScanService { public ScanService() { System.out.println("I am ScanService,i can be scan"); } }
NoScanService.java
代碼以下所示:
package org.light4j.springboot.xml.noScan; import org.springframework.stereotype.Service; @Service public class NoScanService { public NoScanService() { System.out.println("I am NoScanService,i can not be scan"); } }
運行Application.java
,看到控制檯打印日誌以下圖所示:
從上面能夠看到,在程序啓動的時候,執行了ScanService
類的構造函數,而NoScanService
沒有執行,這是由於NoScanService
所在的包沒有被掃描到,因此沒有進行初始化。 那麼下面咱們使用xml
配置文件的方式進行引入。
在src/main/resouces
目錄下編寫配置文件application-bean.xml
文件,內容以下所示:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 注入spring boot沒法掃描到的bean. --> <bean id="noScanService" class="org.light4j.springboot.xml.noScan.NoScanService"></bean> </beans>
在啓動類Application
上使用註解@ImportResource(value = { "classpath:application-bean.xml" })
導入bean
的配置文件,修改後的Application
啓動類以下圖所示:
package org.light4j.springboot.xml.scan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; @SpringBootApplication @ImportResource(value = { "classpath:application-bean.xml" }) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
運行Application.java
,如今看到控制檯打印日誌以下圖所示:
從上面能夠看到,在程序啓動的時候,ScanService
和NoScanService
的構造函數都被執行了,兩者構造函數裏的代碼都在控制檯打印。
Spring
Boot
能夠容許使用properties
文件,yaml
文件或者命令行參數做爲外部配置。使用properties
文件,yaml
文件進行配置的例子在以前文章Spring Boot核心(二):Spring Boot的配置文件中已經有過演示,下面專門說命令行參數配置。
Spring
Boot
能夠是基於jar
包運行的,使用以下命令打包:
mvn package
打成jar
包的程序能夠直接經過下面的命令運行:
java -jar xxx.jar
能夠經過如下命令修改Tomcat
端口號:
java -jar xxx.jar --server.port=9090
修改以後Tomcat
將在9090
端口啓動服務。
在以前的文章Spring4.x經常使用配置(二):Spring EL和資源調用中講述了在常規Spring
環境下,注入properties
文件裏面的值的方式,經過@PropertySource
指明properties
文件的位置,而後經過@Value
注入值。在Spring
Boot
裏,咱們只需在application.properties
定義屬性,直接使用@Value
注入值便可。
article.author=feeerss article.name=spring boot
控制器類以下所示:
package org.light4j.springboot.properties.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @Value("${article.author}") private String articleAuthor; @Value("${article.name}") private String articleName; @RequestMapping("/") public String hello() { return "article name is:" + articleName + " and article author is:" + articleName; } }
啓動入口類Application
,訪問http://localhost:8080/,效果以下圖所示:
常規屬性配置文章中使用@Value
注入每一個配置在實際項目中會顯得格外麻煩,由於咱們的配置一般會是許多個,若使用上篇文章的方式則要使用@Value
注入不少次。
Spring
Boot
還提供了基於類型安全的屬性配置方式,經過@ConfigurationProperties
將properties
屬性和一個Bean
及其屬性關聯,從而實現類型安全的配置。
1. 新建Spring Boot項目
2.添加配置
在application.properties
上添加:
article.author=xxxxxxx article.name=spring boot
固然,咱們也能夠新建一個properties
文件,這就須要咱們在@ConfigurationProperties
的屬性locations
裏指定properties
的位置,且須要在入口類上配置。
3. 建立類型安全的Bean
,代碼以下所示:
package org.light4j.springboot.save.properties.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "article") // ① public class ArticleSettings { private String author; private String name; public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
① 經過
ConfigurationProperties
加載properties
文件內的配置,經過prefix
屬性指定properties
的配置的前綴,經過locations
指定properties
文件的位置,例如:
@ConfigurationProperties(prefix = "article",locations={"classpath:config/article.properties"})
本例中,因爲直接配置在application.properties
文件裏面,因此不須要配置locations
屬性。
4. 校驗代碼,修改HelloController
的代碼以下所示:
package org.light4j.springboot.save.properties.controller; import org.light4j.springboot.save.properties.config.ArticleSettings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @Autowired private ArticleSettings articleSettings; //① @RequestMapping("/") public String hello() { return "article name is "+ articleSettings.getName()+" and article author is "+articleSettings.getAuthor(); } }
① 能夠用
@Autowired
直接注入該配置
Spring
Boot
支持Java Util Logging
,Log4J
,Log4J2
和Logback
做爲日誌框架,不管使用哪一種日誌框架,Spring
Boot
已經爲當前使用的日誌框架在控制檯的輸出以及在文件的輸出作好了配置,能夠對比前面文章SpringMvc4.x基礎(一):Spring MVC項目快速搭建中沒有使用Spring
Boot
時候的日誌配置的方式。
默認狀況下,Spring
Boot
使用Logback
做爲日誌框架。
1. 配置日誌文件,格式爲logging.file=文件路徑
:
logging.file=F:/mylog/log.log
2. 配置日誌級別,格式爲logging.level.包名=級別
,以下所示:
logging.level.org.springframework.web = DEBUG
運行程序,能夠看到控制檯輸出DBUG
日誌以下:
在文件路徑下生成了日誌文件,而且裏面也保存了日誌內容,以下圖所示:
Profile
是Spring
用來針對不一樣的環境對不一樣的配置提供支持的,全局Profile
配置使用application-{profile}.properties
(如application-prod.properties
)。
經過在application.properties
中設置spring.profiles.active
的值來指定活動的Profile
配置。
下面將進行一個最簡單的演示,例如咱們分別爲生產(prod
)和開發(dev
)環境,生產環境下端口號爲80
,開發環境下端口號爲8888
1. 新建配置文件
在src/main/resources
下新建三個配置文件表明普通配置文件,開發環境配置文件,生產環境配置環境,文件名分別是application.properties
,application-dev.properties
,application-prod.properties
。
application-prod.properties
文件的內容以下所示:
server.port=80
application-dev.properties
文件的內容以下所示:
server.port=8888
此時src/main/resources
的目錄結構以下所示:
application.properties
增長內容:spring.profiles.active=dev
,啓動程序結果爲:
將文件application.properties
的內容spring.profiles.active=dev
修改成:spring.profiles.active=prod
,啓動程序結果爲:
如:@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
在application.properties 增長debug=true
AOP
是Spring
框架中的一個重要內容,在Spring
boot
裏配置aop
很是簡單,Spring
Boot
對AOP
的默認配置屬性是開啓的,也就是說spring.aop.auto
屬性的值默認是true
,咱們只要引入了AOP
依賴後,默認就已經增長了@EnableAspectJAutoProxy
功能,不須要咱們在程序啓動類上面加入註解@EnableAspectJAutoProxy
。
下面將使用Spring
Boot
經過模擬記錄操做日誌來演示基於註解攔截的AOP
實現方式。
<!-- aop --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
package org.light4j.springboot.aop.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ ElementType.PARAMETER, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Action { String value() default ""; }
package org.light4j.springboot.aop.controller; import org.light4j.springboot.aop.annotation.Action; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @RequestMapping("/") @Action("hello") public String hello() { return "Hello Spring Boot"; } }
@Action
註解加在方法hello()
上面。
package org.light4j.springboot.aop.aspect; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.light4j.springboot.aop.annotation.Action; import org.springframework.stereotype.Component; @Aspect @Component public class LogAspect { // pointCut @Pointcut("@annotation(org.light4j.springboot.aop.annotation.Action)") public void log() { } /** * 前置通知 */ @Before("log()") public void doBeforeController(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Action action = method.getAnnotation(Action.class); System.out.println("action名稱 " + action.value()); // ⑤ } /** * 後置通知 */ @AfterReturning(pointcut = "log()", returning = "retValue") public void doAfterController(JoinPoint joinPoint, Object retValue) { System.out.println("retValue is:" + retValue); } }
①經過
@Aspect
註解聲明該類是一個切面。
②經過@Component
讓此切面成爲Spring
容器管理的Bean
。
③經過@Pointcut
註解聲明切面。
④經過@After
註解聲明一個建言,並使用@Pointcut
定義的切點。
⑤經過反射能夠得到註解上面的屬性,而後作日誌記錄相關的操做,下面的相同。
⑥經過@Before
註解聲明一個建言,此建言直接使用攔截規則做爲參數。