springboot 概述
SpringBoot能够快速开发,简化部署,适用于微服务
参考嘟嘟大神SpringBoot系列
1. 什么是SpringBoot?
SpringBoot是一个基于Spring4而产生的一个微框架;Spring Boot并不是要成为Spring IO平台里面众多“Foundation”层项目的替代者。Spring Boot的目标不在于为已解决的问题域提供新的解决方案,而是为平台带来另一种开发体验,从而简化对这些已有技术的使用。对于已经熟悉Spring生态系统的开发人员来说,Boot是一个很理想的选择,不过对于采用Spring技术的新人来说,Boot提供一种更简洁的方式来使用这些技术;SpringBoot也是使用微服务架构的最好选择。
SpringBoot能解决那些问题?
SpringBoot使编码更简单,使配置更简单,使部署更简单,使监控更简单
2.SpringBoot 精要
Spring将很多魔法带入了Spring应用程序的开发之中,其中最重要的是以下四个核心。
自动配置:针对很多Spring应用程序常见的应用功能,Spring Boot能自动提供相关配置
起步依赖:告诉Spring Boot需要什么功能,它就能引入需要的库。
命令行界面:这是Spring Boot的可选特性,借此你只需写代码就能完成完整的应用程序,无需传统项目构建。
Actuator:让你能够深入运行中的Spring Boot应用程序,一探究竟。
3.SpringBoot能带给我们什么?
从字面意思理解,Boot是引导,SpringBoot能够帮助开发者快速搭建Spring框架;
SpringBoot能够帮助开发者快速启动一个Web容器;
SpringBoot继承了Spring框架的原有优秀基因;
SpringBoot简化了Spring的开发过程;
SpringBoot更多的是使用了Java Config的方式,对Spring进行配置;
SpringBoot更是一个微服务的起点。
配置文件的优先级
application.properties和application.yml文件可以放在以下四个位置(优先级由高到低):
外置,在相对于应用程序运行目录的/congfig子目录里。
外置,在应用程序运行的目录里
内置,在config包内
内置,在Classpath根目录
同样,这个列表按照优先级排序,也就是说,src/main/resources/config下application.properties覆盖src/main/resources下application.properties中相同的属性,如图:
此外,如果你在相同优先级位置同时有application.properties和application.yml,那么application.properties里的属性里面的属性就会覆盖application.yml。
Profile-多环境配置
在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式(或者.yml),其中{profile}对应你的环境标识,比如:
application-dev.properties:开发环境
application-pro.properties:生产环境
想要使用对应的环境,只需要在application.properties中使用spring.profiles.active属性来设置,值对应上面提到的{profile},这里就是指dev、prod这2个。除了spring.profiles.active来激活一个或者多个profile之外,还可以用spring.profiles.include来叠加profile
spring.profiles.active: dev
spring.profiles.include: prodb,promq
除了可以用profile的配置文件来分区配置我们的环境变量,在代码里,我们还可以直接用@Profile注解来进行配置
启动原理解析
SpringBoot的启动类会用到@SpringBootApplication这个注解
@SpringBootApplication由以下三个注解组成:
@Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration)
@EnableAutoConfiguration
@ComponentScan
@Configuration
@Configuration就是JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,所以,这里的启动类标注了@Configuration之后,本身其实也是一个IoC容器的配置类。
XML跟config配置方式的区别:
@ComponentScan
@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。
我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。
注:所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。
@EnableAutoConfiguration
@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其实一脉相承,简单概括一下就是,借助@Import的支持,收集和注册特定场景相关的bean定义。
@EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。
@EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。
而@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,仅此而已!
SpringFactoriesLoader从指定的配置文件META-INF/spring.factories加载配置。配合@EnableAutoConfiguration使用的话,它更多是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类。
所以,@EnableAutoConfiguration自动配置的魔法骑士就变成了:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
SpringApplication执行流程
SpringApplication的run方法的主要流程大体可以归纳如下:
1) 如果我们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:
根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
推断并设置main方法的定义类。
2) SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了,方法执行伊始,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。
3) 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4) 遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。
5) 如果SpringApplication的showBanner属性被设置为true,则打印banner。
6) 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
7) ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
8) 遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
9) 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
10) 遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
11) 调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12) 查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
13) 正常情况下,遍历执行SpringApplicationRunListener的finished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)
Spring MVC自动配置
Spring Boot为Spring MVC提供适用于多数应用的自动配置功能。在Spring默认基础上,自动配置添加了以下特性:
1)引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
2)对静态资源的支持,包括对WebJars的支持。
3)自动注册Converter,GenericConverter,Formatter beans。
4)对HttpMessageConverters的支持。
5)自动注册MessageCodeResolver。
6)对静态index.html的支持。
7)对自定义Favicon的支持。
如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc对其注解。如果想保留Spring Boot MVC的特性,并只是添加其他的MVC配置(拦截器,formatters,视图控制器等),你可以添加自己的WebMvcConfigurerAdapter类型的@Bean(不使用@EnableWebMvc注解)
默认资源映射
Spring Boot 默认为我们提供了静态资源处理,使用 WebMvcAutoConfiguration 中的配置各种属性。
建议大家使用Spring Boot的默认配置方式,提供的静态资源映射如下(优先级由高到低):
classpath:/META-INF/resources
classpath:/resources
classpath:/static
classpath:/public
可以在上面4个路径下都放一张同名的图片,访问一下即可验证。
任意在上面一个路径下面放上index.html,当访问应用根目录http://lcoalhost:8080时,会直接映射到index.html页面。
对应的配置文件配置如下:
# 默认值为 /**
spring.mvc.static-path-pattern=
# 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
spring.resources.static-locations=这里设置要指向的路径,多个使用英文逗号隔开
我们可以通过修改spring.mvc.static-path-pattern来修改默认的映射,例如我改成/dudu/**,那运行的时候访问 http://lcoalhost:8080/dudu/index.html 才对应到index.html页面。
自定义资源映射addResourceHandlers
如果Spring Boot提供的Sping MVC不符合要求,则可以通过一个配置类(注解有@Configuration的类)加上@EnableWebMvc注解来实现完全自己控制的MVC配置。
当然,通常情况下,Spring Boot的自动配置是符合我们大多数需求的。在你既需要保留Spring Boot提供的便利,有需要增加自己的额外的配置的时候,可以定义一个配置类并继承WebMvcConfigurerAdapter,无需使用@EnableWebMvc注解。
比如,我们想自定义静态资源映射目录的话,只需重写addResourceHandlers方法即可。
通过addResourceHandler添加映射路径,然后通过addResourceLocations来指定路径。我们访问自定义my文件夹中的elephant.jpg 图片的地址为 http://localhost:8080/my/elephant.jpg
如果想指定外部的目录也很简单,直接addResourceLocations指定即可,代码如下:
拦截器addInterceptors
要实现拦截器功能需要完成以下2个步骤:
1.创建我们自己的拦截器类并实现 HandlerInterceptor 接口
2.重写WebMvcConfigurerAdapter中的addInterceptors方法把自定义的拦截器类添加进
首先,自定义拦截器代码:
接着,重写WebMvcConfigurerAdapter中的addInterceptors方法如下:
默认日志Logback
Logback是log4j框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J。
假如maven依赖中添加了spring-boot-starter-logging:
那么,我们的Spring Boot应用将自动使用logback作为应用日志框架
(但是呢,实际开发中我们不需要直接添加该依赖,你会发现spring-boot-starter其中包含了 spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 logback。而Thymeleaf依赖包含了spring-boot-starter,最终我只要引入Thymeleaf即可)
文件输出
默认情况下,Spring Boot将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,则需在application.properties中设置logging.file或logging.path属性。
logging.file,设置文件,可以是绝对路径,也可以是相对路径。如:logging.file=my.log
logging.path,设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:logging.path=/var/log
如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log文件夹生成一个日志文件为 spring.log
注:二者不能同时使用,如若同时使用,则只有logging.file生效
JdbcTemplate的使用
这里需要添加spring-boot-starter-jdbc依赖跟mysql依赖
在src/main/resources/application.properties中配置数据源信息。
Spring的JdbcTemplate是自动配置的,你可以直接使用@Autowired来注入到你自己的bean中来使用。
在dao层的实现类,注入我们需要的JdbcTemplate。
MyBatis的使用
添加mybatis-spring-boot-starter依赖跟mysql依赖,mybatis-spring-boot-starter中已经包含了Jdbc依赖
MyBatis-Spring-Boot-Starter依赖将会提供如下:
自动检测现有的DataSource
将创建并注册SqlSessionFactory的实例,该实例使用SqlSessionFactoryBean将该DataSource作为输入进行传递
将创建并注册从SqlSessionFactory中获取的SqlSessionTemplate的实例。
自动扫描您的mappers,将它们链接到SqlSessionTemplate并将其注册到Spring上下文,以便将它们注入到您的bean中。
就是说,使用了该Starter之后,只需要定义一个DataSource即可(application.properties中可配置),它会自动创建使用该DataSource的SqlSessionFactoryBean以及SqlSessionTemplate。会自动扫描你的Mappers,连接到SqlSessionTemplate,并注册到Spring上下文中。
注解方式(xml方式省略)
Mybatis注解的方式好简单,只要定义一个dao接口,然后sql语句通过注解写在接口方法上。最后给这个接口添加@Mapper注解或者在启动类上添加@MapperScan(“com.dudu.dao”)注解都行。
这些可选的 SQL 注解允许你指定一个类名和一个方法在执行时来返回运行 允许创建动态 的 SQL。 基于执行的映射语句, MyBatis 会实例化这个类,然后执行由 provider 指定的方法. 该方法可以有选择地接受参数对象.(In MyBatis 3.4 or later, it’s allow multiple parameters) 属性: type,method。type 属性是类。method 属性是方法名。 注意: 这节之后是对 类的 讨论,它可以帮助你以干净,容于阅读 的方式来构建动态 SQL。
通用Mapper插件
引入了mybatis相关的一些依赖以及generator的配置,这里generator配置文件指向src/main/resources/mybatis-generator.xml文件,mybatis-generator.xml文件用来自动生成表对应的Model,Mapper以及xml,一会儿会提到。(Mybatis Geneator 详解)
通用Mapper都可以极大的方便开发人员,对单表封装了许多通用方法,省掉自己写增删改查的sql。(通用Mapper插件网址)
对应的application.properties配置:
这里实现一个自己的接口,继承通用的mapper,关键点就是这个接口不能被扫描到,mapper接口不能放在dao包里。
最后在启动类中通过MapperScan注解指定扫描的mapper路径(dao)
IDEA自动生成文件的方法:
根据mybatis-generator.xml文件,自动生成model,mapper,xml文件
MyBatis分页插件
物理分页插件pagehelper,引入依赖
只需在查询list之前使用PageHelper.startPage(int pageNum, int pageSize)方法即可。pageNum是第几页,pageSize是每页多少条。
业务逻辑层(service)的实现
正常情况下具体业务是每个模块的service里面定义许多方法,然后mapper中实现。
但通用Mapper在Spring4中的最佳用法是通用的Service(具体了解)
定义一个通用接口:
具体实现通用接口类
到此基本的增删改查通用service就写好了,具体业务的service就直接继承这个接口即可,也可以添加额外的方法
具体实现service(实现类extends BaseService),然后再mapper文件中(我觉得相当于dao)实现sevice自定义的方法。
在自动生成的xml文件中实现具体方法(相当于dao的实现类):
Spring Loaded 实现热部署
Spring Loaded是一个用于在JVM运行时重新加载类文件更改的JVM代理,Spring Loaded允许你动态的新增/修改/删除某个方法/字段/构造方法,同样可以修改作用在类/方法/字段/构造方法上的注解.也可以新增/删除/改变枚举中的值。
Spring Loaded有两种方式实现,分别是Maven引入依赖方式或者添加启动参数方式
Maven依赖方式
如果用IDEA也可以这样启动
注意:maven依赖的方式只适合spring-boot:run的启动方式,右键那种方式不行。
出现这个说明配置成功
[INFO] Attaching agents: [C:\Users\tengj\.m2\repository\org\springframework\springloaded\1.2.6.RELEASE\springloaded-1.2.6.RELEASE.jar]
还有种方式是右键运行启动类
首先先下载对应的springloaded-1.2.6.RELEASE.jar,可以去上面提到的官网获取(这里直接引用maven依赖已经下载好的路径)
然后打开下图所示的Edit Configurations配置,在VM options中输入:
-javaagent:C:\Users\tengj\.m2\repository\org\springframework\springloaded\1.2.6.RELEASE\springloaded-1.2.6.RELEASE.jar -noverify
上面2种方式随便选择一种即可,当系统通过 mvn spring-boot:run启动或者 右键application debug启动Java文件时,系统会监视classes文件,当有classes文件被改动时,系统会重新加载类文件,不用重启启动服务。(注:IDEA下需要重新编译文件 Ctrl+Shift+F9或者编译项目 Ctrl+F9 )
还可以使用spring-boot-devtools 方式、JRebel插件方式实现热部署
经过简单的测试,发现大多数情况可以使用热部署,不过还是有一些情况下需要重新启动,不可用的情况如下:
1:对于一些第三方框架的注解的修改,不能自动加载,比如:spring mvc的@RequestMapping
2:application.properties的修改也不行
3:log4j的配置文件的修改不能即时生
单元测试
Spring Boot中单元测试类写在在src/test/java目录下,你可以手动创建具体测试类,如果是IDEA,则可以通过IDEA自动创建测试类
最简单的单元测试写法(Service层),顶部只要@RunWith(SpringRunner.class)和SpringBootTest即可,想要执行的时候,鼠标放在对应的方法,右键选择run该方法即可。推荐大家使用该assertThat断言。
有时候需要对Controller层(API)做测试,这时候就得用到MockMvc了,你可以不必启动工程就能测试这些接口。MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
使用MockMvc的时候需要先用MockMvcBuilders使用构建MockMvc对象,如下
MockMvc简单的方法
1. mockMvc.perform执行一个请求
2. MockMvcRequestBuilders.get(“/user/1”)构造一个请求,Post请求就用.post方法
3. contentType(MediaType.APPLICATION_JSON_UTF8)代表发送端发送的数据格式是application/json;charset=UTF-8
4. accept(MediaType.APPLICATION_JSON_UTF8)代表客户端希望接受的数据类型为application/json;charset=UTF-8
5. session(session)注入一个session,这样拦截器才可以通过
6. ResultActions.andExpect添加执行完成后的断言
7. ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看请求的状态响应码是否为200如果不是则抛异常,测试不通过
8. andExpect(MockMvcResultMatchers.jsonPath(“$.author”).value(“嘟嘟MD独立博客”))这里jsonPath用来获取author字段比对是否为嘟嘟 MD独立博客,不是就测试不通过
9. ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息
新断言assertThat使用
JUnit 4.4 结合 Hamcrest 提供了一个全新的断言语法——assertThat。只使用 assertThat 一个断言语句,结合 Hamcrest 提供的匹配符,就可以表达全部的测试思想,。 JUnit 4.4 默认提供一些可读的描述性错误信息
使用asserThat的两个例子:
1. assertThat( [value], [matcher statement] );
2. assertThat(s, anyOf(containsString("a"), containsString("b"))); //表示s里面是否包含“”“a”或者“”“b”
单元测试回滚
单元个测试的时候如果不想造成垃圾数据,可以开启事物功能,记在方法或者类头部添加@Transactional注解即可,如下:
这样测试完数据就会回滚了,不会造成垃圾数据。如果想关闭回滚,只要加上@Rollback(false)注解即可。传入一个参数value,默认true即回滚,false不回滚。如果你使用的数据库是Mysql,有时候会发现加了注解@Transactional 也不会回滚,那么你就要查看一下你的默认引擎是不是InnoDB,如果不是就要改成InnoDB,如下图:
微服务
微服务是一种细粒度的SOA(面向服务架构)
SOA特性: 面向服务 松耦合 模块化 分布式计算 平台无关性 集中管理