简介
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭 建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的 配置。通过这种方式,Spring Boot 致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。其特点如下:
- 创建独立的Spring应用程序
- 嵌入的Tomcat,无需部署war文件
- 简化Maven配置
- 自动配置Spring
- 提供生产就绪型功能,如指标、健康检查和外部配置
- 没有代码生成和不要求配置xml
环境搭建
创建maven工程(不用骨架,打包方式jar)
添加起步依赖
继承SpringBoot的起步依赖
org.springframework.boot spring-boot-starter-parent 2.0.1.RELEASE 导入web的启动依赖
org.springframework.boot spring-boot-starter-web 编写引导类(任意命名)
@SpringBootApplication public class NewSpringBootApplication{ public static void main(String[] args){ SpringApplication.run(NewMySpringBootApplication.class); } }
编写Controller
@Controller public class HelloController{ @RequestMapping("/hello") @ResponseBody //说明返回的是json字符串 public String hello(){ return "hello springboot"; } }
注意事项
所有的SpringBoot项目必须继承SpringBoot的起步依赖
添加依赖时以功能为单位
@SpringBootApplication 声明该类是一个SpringBoot引导类
SpringApplication.run(引导类.class) 表示运行SpringBoot的引导类(引导类和main方法可以分开)
SpringBoot工程的热部署,更改代码后不需要重启项目即可生效
org.springframework.boot spring-boot-devtools 导入坐标后设置IDEA自动编译:
Settings --> Compiler --> select Build project automatically --> apply
press control+shift+/ --> Registry --> select compiler.automake.allow.when.app.running
IDEA快速创建SpringBoot项目
new project --> Spring Initializr --> select dependencies --> [delete .gitignore & mvnw & mvnw.cmd] --> create Controller
@RestController = @Controller + @ResponseBody
原理分析
起步依赖
parent:当前项目 --> 继承spring-boot-starter-parent(处理配置文件,插件管理) --> 继承spring-boot-dependencies(maven 版本约定,依赖管理)
web:spring-boot-starter-web-2.0.1.RELEASE.pom中导入了tomcat,json等坐标
自动配置
@SpringBootApplication
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration //配置类 @EnableAutoConfiguration //允许自动配置 @ComponentScan( //自动扫描组件,约定引导类所在的包及子包所有的类都会扫描 excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication {...}
@SpringBootConfiguration
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration //spring的配置类注解 public @interface SpringBootConfiguration {...}
@EnableAutoConfiguration
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) //当前配置类引入其他配置类 public @interface EnableAutoConfiguration {...}
AutoConfiturationImportSelector.class
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); //调用getAutoConfigurationEntry() AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } } protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationMetadata); //调用getCandidateConfigurations(),返回配置类的全包名 List
configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); } } protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); //错误信息说明了配置类的信息存在spring.factories中 Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations; } org.springframework.boot:spring-boot-autoconfigure:2.2.2.RELEASE/spring-boot-autoconfigure-2.2.2.RELEASE.jar/META-INF/spring.factories
... # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ ...
流程
- 通过配置文件提前进行默认配置
- 用ServerProperties类加载配置
- 用XxxAutoConfiguration类引入
- 用spring.factories存入多个AutoConfiguration全限定类名
- AutoConfigurationImportSelector类加载spring.factories获取配置信息
- @EnableAutoConfiguration引入AutoConfigurationImportSelector完成自动配置
覆盖配置
spring-boot-starter-parent-2.0.1.RELEASE.pom中include标签有application*.yml(.yaml/.properties),可以通过自定义对应配置文件进行覆盖
配置文件
位置:resources目录下
顺序:多个配置文件时,yml > yaml > properties,后加载的会覆盖之前的
yml语法
# 普通数据 name: whteway # 对象(常用) user: username: root password: 1234 # 行内对象配置 user: {username: root,password: 1234}
读取配置信息
@Value 精确,繁琐
@Value("${name}") private String name; @Value("${user.username}") private String username;
@ConfigurationProperties 自动封装,需要配置configuration processor
@Controller @ConfigurationProperties(prefix="user") public class LoginController{ private String username; private String password; //generate getters and setters }
org.springframework.boot spring-boot-configuration-processor true
集成Mybatis
添加起步依赖
org.mybatis.spring.boot mybatis-spring-boot-starter 1.1.1 添加数据库驱动坐标
mysql mysql-connector-java 添加数据库连接信息,application.yml
spring: datasource: driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/dbName?useUnicode=true?characterEncoding=utf8 username=root password=root
建库建表
配置映射关系
UserMapper.xml
SpringBoot的配置文件中配置Mybatis的信息
mybatis: type-aliases-package=com.whteway.entity mapper-locations=classpath:mapper/*Mapper.xml
集成Junit
添加起步依赖
org.springframework.boot spring-boot-starter-test test 编写测试类
@RunWith(SpringRunner.class) @SpringBootTes(classes="引导类全包名") public class Test{ @Test public void test(){...} }
集成SpringDataJPA
添加起步依赖
org.springframework.boot spring-boot-starter-data-jpa 添加数据库驱动坐标
mysql mysql-connector-java 添加数据库连接信息,application.yml
spring: datasource: driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/dbName username=root password=root
建库建表
建实体类
@Entity public class User{ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; private String username; ... }
建接口
public interface UserRepository extends JpaRepository
{ public List findAll(); } SpringBoot的配置文件中配置Mybatis的信息
spring: jpa: database: MySQL show-sql: true generate-ddl: true hibernate: ddl-auto: update naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
集成Redis
添加起步依赖
org.springframework.boot spring-boot-starter-data-redis 配置连接信息
spring: redis: host=127.0.0.1 port=6379
测试
@RunWith(SpringRunner.class) @SpringBootTes(classes="引导类全包名") public class Test{ @Autowired private RedisTemplate
redisTemplate; @Autowired private UserRepository userRepository; @Test public void test(){ String userListJson = redisTemplate.boundValueOps("user.findAll").get(); if(null==userListJson){ List all = userRepository.findAll(); ObjectMapper objectMapper = new ObjectMapper(); userListJson = objectMapper.writeValueAsString(all); redisTemplate.boundValueOps("user.findAll").set(userListJson); } System.out.println(userListJson); } }