JSP支持
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId><!--支持jsp格式-->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId><!--支持jsp一些语法-->
<version>1.2</version>
<scope>compile</scope>
</dependency>
application.yml
相关配置
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
Config
文件需要继承
SpringBootServletInitializer
重写
configure()
方法
当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:
src/main/resources/templates
。当然也可以修改这个路径,具体如何修改,可在后续各模板引擎的配置属性中查询并修改。
Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:
举例:我们可以在
src/main/resources/
目录下创建
static
,在该位置放置一个图片文件。启动程序后,尝试访问
http://localhost:8080/d.jpg
。如能显示图片,则配置成功。PS:在此目录下放入
favicon.ico
,页面会自动加载图标。
在Spring Boot中使用Thymeleaf,只需要引入下面依赖,并在默认的模板路径
src/main/resources/templates
下编写模板文件即可完成。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
更多Thymeleaf的页面语法,还请访问Thymeleaf的官方文档查询使用。
统一异常处理
创建全局异常处理类:通过使用
@ControllerAdvice
定义统一的异常处理类,而不是在每个
Controller
中逐个定义。
@ExceptionHandler
用来定义函数针对的异常类型,最后将
Exception
对象和请求URL映射到
error.html
中
@ControllerAdvice
public class GlobalExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error/500";
@ExceptionHandler(value = RuntimeException.class)// 用来定义函数针对的异常类型
public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("url", req.getRequestURL());
mav.addObject("exception", e);
mav.setViewName(DEFAULT_ERROR_VIEW);// 将Exception对象和请求URL映射到error.html中
return mav;
通过@ControllerAdvice
统一定义不同Exception映射到不同错误处理页面。而当我们要实现RESTful API时,返回的错误是JSON格式的数据,而不是HTML页面,这时候也能轻松支持。本质上,只需在@ExceptionHandler
之后加入@ResponseBody
,就能让处理函数return的内容转换为JSON格式。
Reactor 本质就是: jdk8 stream + jdk9 reactive stream
Reactive Programming 作为观察者(Observer)的延伸,不同于传统的命令编程方式(Imperative programming)同步拉取数据的方式,如迭代器模式(Iterator)。而是采用数据发布者同步或异步地推送到数据流(Data Streams)的方案。当该数据流订阅者监听到传播变化时,立即作出响应动作。在实现层面上,Reactive Programming可结合函数式编程简化面向对象语言语法的臃肿性,屏蔽并发实现的复杂细节,提供数据流的有序操作,从而达到提升代码的可读性,以及减少Bug出现的目的。同时,Reactive Programming结合背压(Backpressure)的技术解决发布生成数据的速率高于订阅端消费的问题。
添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
webFlux支持通过Controller方式来进行调用,也可以通过Router方式进行调用:
TestController
中,举例说明了通过servlet的阻塞I/O 和 reactive stream非阻塞的差别,可以提高吞吐量(但并不能解决性能问题),以及Mono
和 Flux
的区别。UserController
列举了Flux的常规用法。
补充:服务事件发送 server-sent events(适用于服务器向前端推送数据的场景):
需要设置响应的Content-Type="text/event-stream"
设置编码类型CharacterEncoding=utf-8
指定事件标识:event:${eventName}\n
事件内容:
格式:data + 数据内容 + 2个回车
栗子:data:${dataContent}\n\n
var sse = new EventSource("SSE"); // 传入请求地址url
sse.onmessage = function(e){
console.log("message:", e.data, e);
sse.addEventListener("${eventName}", function(e){
console.log("listen event:", e.data);
// 满足条件后断开,否则会继续重连
if(e.data == 3) {
sse.close();
});
UserHandler
AllRouters
HttpHandler
->
Server
(Netty或Servlet3.1+)处理
响应式在网页请求下,看到差别并不是很大,它更多适用于服务器之间的Rest调用,异步非阻塞特性才能更好的呈现出来,更有价值。
服务之间的Rest调用参考: IUserApi
在
pom.xml
加入如下依赖集成 WebSocket:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
创建一个 WebSocket 配置类
WebSocketConfiguration
,在配置类上加入注解
@EnableWebSocket
,表明开启 WebSocket,内部实例化 ServerEndpointExporter 的 Bean,该 Bean 会自动注册
@ServerEndpoint
注解声明的端点,代码如下:
@Configuration
@EnableWebSocket
public class WebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
使用 @ServerEndpoint
定义一个端点服务类,在端点服务类中,可以定义 WebSocket 的打开@OnOpen
、关闭@OnClose
、错误@OnError
和接收客户端消息@OnMessage
的方法,具体参考:WsServerEndpoint
不同客户端访问时,会为每个客户端生成自己的端点实例,所以要想为每个客户端推送不同的消息,需要记录下每个客户端对应的端点实例,参考WsClientsManager。之后,根据不同客户端获取到对应实例中的session
来进行sendMsg。
因为Spring容器中的对象采用单实例方式,不同客户端连接时会生成不同的WebSocket对象,无法按照对象方式来直接使用容器对象,可以把容器对象定义为WebSocket的类属性。在容器启动时,注册类属性,其后生成的对象都可以使用容器对象。
仅需要添加devtools依赖:
<!--支持热部署,devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),注意:因为其采用的虚拟机机制,该项重启是很快的-->
<!--Intellij要想支持还需要进一步设置,自行google-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<!-- optional=true,依赖不会传递,该项目依赖devtools;之后依赖myboot项目的项目如果想要使用devtools,需要重新引入 -->
<optional>true</optional>
</dependency>
<plugins>
<plugin>
<!--用于将应用打成可直接运行的jar-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--支持热部署-->
<configuration>
<fork>true</fork>
</configuration>
</plugin>
<!-- spring Boot在编译的时候,是有默认JDK版本的,如果我们期望使用我们要的JDK版本的话,那么要配置呢 -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
Swagger2
它可以轻松的整合到Spring Boot
中,并与Spring MVC
程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。
首先添加相关依赖:
<!--Swagger2依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
其次,添加Swagger2相关依赖配置Swagger2Config。
在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,而描述主要来源于函数等命名产生,对用户并不友好,我们通常需要自己增加一些说明来丰富文档内容。如下所示,我们通过@ApiOperation
注解来给API增加说明、通过@ApiImplicitParams
、@ApiImplicitParam
注解来给参数增加说明。具体使用参看示例。
启动Spring Boot程序,访问:http://localhost:8080/swagger-ui.html
Spring 事件 - 监听器(同步/异步):
ApplicationEvent
ApplicationContextEvent
ApplicationListener
@EventListener
ApplicationEventPublisher
ApplicationEventMulticaster
SimpleApplicationEventMulticaster
事件发布,实际是调用AbstractApplicationContext.publishEvent(event)
,其内部调用了AbstractApplicationEventMulticaster
获取对应的Listener(如果Listener是SmartApplicationListener
类型,对应的Listener的获取是根据EventType
和sourceType
去决定的),由相应的Listener执行onApplicationEvent(event)
。
Spring自己是支持异步方式处理事件(通过新的线程方式)通过,@Async
@EventListener
想采用其他方式的异步响应处理,如MQ方式,可以实现ApplicationListener
,实现onApplicationEvent(event)
方法,该方法判断是否开启异步enableAsync(),来采用自定义异步执行器public MQ asyncExecutor()。
使用Spring event步骤:
定义监听器Listener有三种方式
无序监听器ApplicationListener(监听器事件过多,具体执行顺序是不保证的)
重试一个失败的操作有时是必要的,Spring Batch
提供了重试策略,添加相关依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
在Config
类中添加@EnableRetry
开启重试支持
重试方式有两种:
添加redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
如需要开启缓存支持,需要在Config
类中增加@EnableCaching
注解开启缓存功能。
application.yml
中添加redis相关配置
RedisTemplate
及其序列化方式设置,参考RedisConfig
@CacheConfig
相关使用参考CacheService
添加相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
测试用例类前需要添加@RunWith(SpringRunner.class)
和@SpringBootTest
,如若有数据库相关测试用例需加@Transactional
测试完成后进行回滚
若是需要对JPA接口进行单元测试,可以使用@DataJpaTest
添加依赖(使用的MySQL)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
关于数据库连接相关设置
spring:
datasource:
url: jdbc:mysql://localhost:3306/msg?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
username: root
password: root
dao层接口需要加@Mapper
注解,之后spring会自动扫描到
具体sql写入与dao层接口同名的XML文件中
补充:由于IntelliJ IDEA的原因,放在java目录下xml文件最后不会被编译,导致运行时找不到dao的实现接口,解决方法在pom.xml添加:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
多数据源配置
a.多数据库yml配置
demo:
datasource:
master:
url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
slave:
url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
b.相关config,具体代码
* 配置多数据源 @Configuration public class DataSourceConfig { * 主数据源 @Primary @Bean(name = "masterDataSource") @Qualifier("masterDataSource") @ConfigurationProperties(prefix="demo.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); * 从数据源 @Bean(name = "slaveDataSource") @Qualifier("slaveDataSource") @ConfigurationProperties(prefix="demo.datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); * 主数据源详情配置 @Configuration // 制定分库的mapper文件地址,以及分库到层代码 @MapperScan(basePackages = "com.gtw.mybatis.repository.mapper.master", sqlSessionTemplateRef = "masterSqlSessionTemplate") public class MasterDataSourceConfig { * 创建SqlSessionFactory @Primary @Bean(name = "masterSqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setDataSource(dataSource); // sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() // .getResources("classpath*:mapper/master/*.xml")); return sessionFactoryBean.getObject(); * 创建事务管理 @Primary @Bean(name = "masterTransactionManager") public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); * 将SqlSessionFactory包装到SqlSessionTemplate中 @Primary @Bean(name = "masterSqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory);此种方式指明哪个包下dao接口或配置文件走哪个数据库,缺点很明显,相同的dao接口和配置文件要复制多份到不同包路径下,不易维护和扩展。
具体使用主从分离的读写方式,可以参看mybatis-master-slave
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
JPA提供了@CreatedDate
等审计功能,自动生成创建时间、修改时间、创建人等,开启审计功能需要在Config
文件中加@EnableJpaAuditing
,参考审计示例
仓储层Repository
接口不需要进行实现,只要继承Repository
就好(还有其他CrudRepository
等等),具体可参考仓储层接口定义
分页功能与模糊查询功能可参考分页与模糊查询
其他功能,如需请参考官方文档
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-collections</artifactId>
<version>${querydsl.version}</version>
</dependency>
工程构建时需要引入插件,这样会在工程模块的target/generated-sources/java对应目录下会生成相应的查询类QClass
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<!-- If you are not using JPA or JDO -->
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.QuerydslAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
集合查询的querysql使用,参考Querydsl使用
Jpa集成Querysql,引入依赖与插件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--querydsl支持-->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
<classifier>apt</classifier>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<!--JPAAnnotationProcessor查找使用javax.persistence.Entity注释注释的域类型,并为它们生成查询类型-->
<!--<outputDirectory>target/generated-sources/java</outputDirectory>-->
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Repository层使用QueryDsl,需要继承QueryDslPredicateExecutor,参考ProductRepository
也可用使用JPAQueryFactory,参考OrderRepositoryCustomer
Oauth2相关介绍理解,参考本人博客理解Oauth2
Oauth2 Server
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--oauth2-->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
关于Oauth2ServerConfig
请参考SecurityConfig
用户名和密码的校验,需要指定UserService
,UserService
需要继承UserDetailsService
指定Token
的缓存方式
指定密码的加密方式
设置AuthenticationManager
认证服务配置
资源服务配置
Spring Boot Starter 是一个 Maven 或 Gradle 模块,其唯一目的是提供 "启动" 某个特性所需的所有依赖项。可以包含一个或多个 Auto-Configure Module (自动配置模块)的依赖项,以及可能需要的任何其他依赖项。这样,在Spring 启动应用程序中,只需要添加这个 starter 依赖就可以使用其特性。
通常一个完整的 starter 需要包含下面两个组件:
来自 Spring 官方的 starter 都是 以 spring-boot-starter
开头,比如:
如果我们自定义 starter 功能名称叫acme
,那么我们的命名是这样的:
acme-spring-boot-starter
acme-spring-boot-autoconfigure
如果 starter 中用到了配置 keys,也要注意不要使用 Spring Boot 使用的命名空间。
先来全局看一下项目结构:
一级目录结构:
├── pom.xml ├── gtw-spring-boot-autoconfigure ├── gtw-spring-boot-sample └── gtw-spring-boot-starter二级目录结构:
├── pom.xml ├── gtw-spring-boot-autoconfigure │ ├── pom.xml │ └── src ├── gtw-spring-boot-sample │ ├── pom.xml │ └── src └── gtw-spring-boot-starter ├── pom.xml └── src创建一个空的父亲 Maven Module,主要提供依赖管理,这样 SubModule 不用单独维护依赖版本号:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Compile dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 属性是要在 application.yml 中使用的,当需要使用这些属性时,为了让ID 给出更友好的提示,需要在 pom.xml 中添加依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
对于类路径上的每个自动配置类,Spring Boot 必须计算 @Conditional… 条件值,用于决定是否加载自动配置及其所需的所有类,
根据 Spring 启动应用程序中 starter 的大小和数量,这可能是一个非常昂贵的操作,并且会影响启动时间,
为了提升启动时间,需要在 pom.xml 中添加一个依赖.
这样,Spring Boot 在启动期间读取这些元数据,可以过滤出不满足条件的配置,而不必实际检查这些类,提升启动速度
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
@Data
@ConfigurationProperties(prefix = "gtw.greeting")
public class GtwProperties {
* GreetingProperties 开关
boolean enable = false;
* 需要打招呼的成员列表
List<String> members = new ArrayList<>();
用 @Configuration
注解标记类 AutoConfiguration,作为 starter 的入口点。这个配置包含了需要提供starter特性的所有 @Bean
定义:
@Configuration
@EnableConfigurationProperties(GtwProperties.class)
@ConditionalOnProperty(value = "gtw.greeting.enable", havingValue = "true")
@ConditionalOnClass(DefaultSqlSession.class)
public class GtwAutoConfiguration {
@Bean
public GreetingService greetingService(GtwProperties gtwProperties){
return new GreetingService(gtwProperties.getMembers());
在 resources 目录下新建文件 META-INF/spring.factories
,向文件写入内容:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gtw.spring.boot.autoconfigure.GtwAutoConfiguration
Spring 启动时会在其 classpath 中所有的 spring.factoreis
文件,并加载里面的声明配置,AutoConfiguration 类就绪后,我们的 Spring Boot Starter 就有了一个自动激活的入口点。
关于条件配置,参考 @Conditional注解,灵活配置 Spring Boot
是一种用于声明在应用中扮演“组件”角色的注解,实现单个功能。当任何组件标注它时,被视作组件扫描的候选对象。
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
// 加载单一配置内容,只有一种模式
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
接口编程方式
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({CacheConfigurationImportSelector.class})
public @interface EnableCaching {
static class CacheConfigurationImportSelector implements ImportSelector {
CacheConfigurationImportSelector() {
// 可条件化,支持多种模式的配置
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
CacheType[] types = CacheType.values();
String[] imports = new String[types.length];
for(int i = 0; i < types.length; ++i) {
imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
return imports;
允许在Bean装配时增加前置条件判断
Spring注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnClassCondition.class}) // 实现方式在这里
public @interface ConditionalOnClass {
Class<?>[] value() default {};
String[] name() default {};
底层装配技术
Spring 模式注解装配
Spring @Enable
模块装配
Spring 条件装配
Spring 工厂加载机制
实现类:SpringFactoriesLoader
配置资源:META-INF/spring.factories
Starter Module 构建很简单,可以认为它就是一个空 module,除了依赖 Auto-Configure Module,其唯一作用就是为了使用 starter 功能特性提供所有必须依赖,所以为 starter module 的 pom.xml 文件添加如下内容:
<dependencies>
<dependency>
<groupId>com.gtw.starter</groupId>
<artifactId>gtw-spring-boot-autoconfigure</artifactId>
<version>${gtw.autoconfigure.version}</version>
</dependency>
<!-- 在此处添加其他必要依赖,保证starter可用 -->
</dependencies>
同样在 resources 目录下新建文件 META-INF/spring.providers
, 其内容如下:
providers: gtw-spring-boot-autoconfigure
该文件主要作用是说明 starter module 的依赖信息,多个依赖以逗号分隔就好,该文件不会影响 starter 的使用,可有可无。
可以通过 Spring Initializr 正常初始化一个 Spring Boot 项目 (gtw-spring-boot-sample),引入刚刚创建的 starter 依赖,在 sample pom.xml 中添加依赖:
<dependencies>
<!-- spring boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- gtw-starter -->
<dependency>
<groupId>com.gtw.starter</groupId>
<artifactId>gtw-spring-boot-starter</artifactId>
<version>${gtw.starter.version}</version>
</dependency>
</dependencies>
配置 application.yml 属性:
gtw:
greeting:
enable: true
members:
- 韩梅梅
使用测试:
@SpringBootApplication
public class SampleApplication {
@Autowired
private GreetingService greetingService;
@PostConstruct
public void sayHello(){
greetingService.sayHello();
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);