1. What is Spring Boot?
SpringBoot -> JavaEE 一栈式 解决方案以简化独立的、产品级别的Spring应用开发
“约定大于配置”思想的实现
2. Why Spring Boot?
(1)快速 创建独立运行的Spring项目以及与主流框架集成;
(2)使用 嵌入式Servlet容器 ,应用无需打成war包;
(3)场景启动器 starters自动依赖与版本控制 ;
(4)大量的 自动配置,简化开发,轻松覆盖默认值;
(5)无需配置xml ,无代码生成,开箱即用;
(6)准生产环境的运行时应用监控;
(7)与云计算天然集成;
3. 什么是微服务?
(1) 2014, Martin Fowler
(2) 架构风格:
<1>一个应用应该是一组小型服务,通过Http的方式进行互通;
<2>每一个功能元素最终都是一个 可动态组合,独立替换,独立升级的软件单元
(3) Spring “三步走”
4. Getting start
4.1 环境约束
- jdk 1.8:Spring Boot推荐 jdk1.7以上
- Maven 3.x
<!-- settings.xml --> <profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> </profile>
- IntelliJ IDEA 2017:配置Maven
- Spring Boot 1.5.9 REALEASE
4.2 Hello World
功能:浏览器发送hello请求,服务器接收请求并处理,响应HelloWorld字符串
- IntelliJ IDEA 创建Maven工程(打包选jar),坐标如下
- 导入Spring Boot相关依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
- 编写用于启动应用的主程序
/** * @SpringBootApplication 来标注一个主程序类,说明这是一个Srping Boot应用 */ @SpringBootApplication public class HelloWorldMainApplication { public static void main(String[] args) { //启动Spring应用 SpringApplication.run(HelloWorldMainApplication.class,args); } }
- 编写相关Controller
@Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello(){ return "hello,world"; } }
- 直接运行主程序测试
- 简化打包,部署
<!-- 给pom.xml添加一个打包此插件,该插件可以将应用打包成一个可执行的jar包;--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
打包成一个jar,使用java -jar命令运行此jar即可部署。 打包时已内嵌Tomcat
4.3 Hello World原理剖析
-
pom.xml中的父项目
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <!--pom.xml中父项目的父项目,真正管理SpringBoot应用中所有依赖的版本 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.5.9.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>
Spring Boot的 版本仲裁 中心:以后导入依赖不需要指定版本;
当然,没有在spring-boot-dependencies里面管理的依赖必须写版本号; -
启动器
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
spring-boot-starter-web -> spring-boot-starter-xxx :
Spring Boot对所有功能场景进行抽取,形成一个个starter(场景启动器),只需要在项目中引入需求的starter,对应场景的所需组件的依赖都会自动导入 ,换句话说,要用什么功能,就引什么场景的starter。当然,依赖的版本是受父项目版本仲裁的。 -
主程序的入口,@SpringBootApplication(核心注解)
@SpringBootApplication 标注在某个类上,表示该类为当前Spring Boot应用的主配置类 ,Spring Boot应该运行该类的 main() 来启动Spring Boot应用【@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 / @EnableAutoConfiguration
(1) @SpringBootConfiguration
<1> 标注在某个类上,表示该类是SpringBoot的一个配置类;
<2> 使用Spring的底层注解 @Configuration 可以达到相同的效果;
<3> 配置类===配置文件,配置类也是容器的一个组件@Component(2) @EnableAutoConfiguration
<1> 表示自动开启配置功能,之前需要手动配置的东西,Spring Boot进行自动化配置
<2> @EnableAutoConfiguration也是一系列注解的组合@AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration
其中包含两个关键要素:@AutoConfigurationPackage / EnableAutoConfigurationImportSelector
要素 说明 @AutoConfigurationPackage 自动配置包,相当于使用Spring底层注解@Import(AutoConfigurationPackages.class),给容器导入一个组件AutoConfigurationPackages
AutoConfigurationPackages的作用:方法调用register(registry, new PackageImport(metadata).getPackageName()) ,底层反射找到@SpringBootApplication的anotation metadata,将主配置类所在包及其子包里面所有的组件扫描并注入Spring容器中EnableAutoConfigurationImportSelector 底层调用其父类AutoConfigurationImportSelector#selectImports(AnnotationMetadata),将所有需要导入的组件以 全类名 的方式返回(组成String[]),给容器导入非常多的自动配置类(xxxAutoConfiguration)即向容器中自动导入当前场景需要的所有组件的自动配置类,并由这些类完成对相应组件自动配置(避免之前手写xml配置功能组件)
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader),启动时自动从 类路径下META-INF/spring.factories中获取EnableAutoConfiguration指定的值
JavaEE整体的整合方案和自动配置都在spring-boot-autoconfigure\1.5.9.RELEASE\spring-boot-autoconfigure-1.5.9.RELEASE.jar//AutoConfigurationImportSelector的核心方法 public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { try { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = this.getAttributes(annotationMetadata); //重要的源码,见下块代码区 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); configurations = this.sort(configurations, autoConfigurationMetadata); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return (String[])configurations.toArray(new String[configurations.size()]); } catch (IOException var6) { throw new IllegalStateException(var6); } } } //getCandidateConfigurations的源码 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //传递了两个参数,第一个点进去是EnableAutoConfiguration.class,第二个点进去是classLoader,点进方法见下方代码块 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); 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; } //loadFactoryNames的源码 public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { //这里就指明了获取列表的位置,所有jar包类路径下META-INF/spring.factories Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); ArrayList result = new ArrayList(); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); //遍历url,转换为一个Properties,拿到factoryClassName指定的value,这个factoryClassName就是传过来EnableAutoConfiguration.class类名 Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); //加入到结果集合中 result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } //结果就是要交给容器的所有组件的全类名列表 return result; } catch (IOException var8) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8); } }
5. 使用Spring Initializer快速创建Spring Boot项目
(1) File -> New Project -> Spring Initializer -> Maven定制坐标等信息 -> 启动器startes选择 -> 向导联网创建
(2) 默认生成的SpringBoot项目特点:
<1> 主程序已经自动生成,只需要编写业务逻辑即可
<2> resources 文件夹中目录结构
static:保存所有的静态资源,如js,css,imgs…
templates:保存所有的模板页面。注意:Spring Boot默认jar包使用嵌入式Tomcat,默认不支持JSP页面,但可以使用“模板引擎”如freemarker,thymeleaf
application.properties:Spring Boot应用的配置文件