在真实的企业级项目中,一个大的项目会由多个子模块组成,每一个模块是一个小的项目,那么每一个模块都有本身的父项目,这个时候就不能再依赖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
注解声明一个建言,此建言直接使用拦截规则做为参数。