一、什么是SpringBoot ?
SpringBoot就是一个javaweb框架,和springmvc类似,官方的说法是简化开发、约定大于配置。SpringBoot最大的特点就是:自动装配!
为什么要有springboot?它帮我们解决了什么问题?
众所周知,Spring是一个开源框架,从2003年兴起,随着Spring的不断发展,涉及的领域越来越多,项目整合开发需要配置各种各样的文件,配置过程十分繁琐,使得spring的使用变得困难起来。SpringBoot就是在这样的一个背景下被抽象出来的一个开发框架,目的就是为了让大家更容易的使用Spring,更容易的集成其他中间件、软件等。
注意:
SpringBoot本身不提供Spring的核心特性,它不是什么新框架(其实我觉得可以理解成springboot是对spring的再一次封装,使我们用起来更加方便)。
SpringBoot以约定大于配置的核心思想,默认帮我们进行了很多的配置,使我们编写很少的配置信息,或甚至不用配置任何东西直接将依赖导入就能用(这就是springboot的开箱即用)。
SpringBoot的主要优点:
1.为所有Spring开发者更快的入门
2.开箱即用,提供各种默认配置来简化项目配置
3.内嵌式容器简化Web项目
4.没有冗余代码生成和XML配置的要求
二、SpringBoot自动装配原理解析
2.1 pom文件解析
首先我们从pom.xml文件开始来解析,在SpringBoot项目中,pom文件中主要导入了一个parent父项目依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
点进去后会发现还有一个parent父项目依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
以上这个依赖就是SpringBoot项目中的版本控制中心,之后我们在pom文件中导入依赖默认就无需再写版本号了,除非导入的包不在上面的依赖管理中,就要指定版本。
启动器starter:
SpringBoot项目的pom文件中还有很多类似如下的启动器:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
启动器的作用就是把我们需要的功能制作成一个个的启动器,我们需要什么功能就把相应的启动器导入进去,springboot就会帮我们导入该功能所需要的所有依赖。(比如web启动器,导入后它就会帮我们导入web环境所需的所有依赖,redis启动器,帮我们导入redis所需的所有依赖。感觉其实就像是对某些功能的封装,然后我们导入对应的starter就能用了)
2.2 SpringBoot主程序解析
@SpringBootApplication // 此注解的意思是标注此类是一个SpringBoot应用
public class SpringbootbuildApplication {
public static void main(String[] args) {
// 启动springBoot
SpringApplication.run(SpringbootbuildApplication.class, args);
}
}
从上面的方法来看,springboot的所有特性和原理应该都藏在@SpringBootApplication此注解和run()方法中,那么我们分别来解析:
2.2.1 @SpringBootApplication注解解析:
此注解点进去后会发现还有多个注解,其中有如下几个:
A. @ComponentScan:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中
B. @SpringBootConfiguration:此注解表明该类这是一个springboot的配置类
这个注解接着点进去后会发现主要还有:
- @Configuration:表明当前类是个配置类
- @Component:将此类实例化放入ioc容器中(这就表明启动类本身也是一个Spring的组件,负责启动应用)
C. @EnableAutoConfiguration:开启自动配置功能
这个注解就是SpringBoot可以实现自动配置的关键所在!接着点进去这个注解分析里面的内容:
- @AutoConfigurationPackage,自动配置包,此注解里面还有@Import({Registrar.class}),import注解的意思是给spring容器中导入一个组件,导入Registrar.class的作用就是:扫描主启动类所在包以及包里面所有的组件到Spring容器中。(所以这个@AutoConfigurationPackage注解就可以理解为扫描组件到容器中的意思(注意:这里扫描的主要是我们自己代码所在的包))
- @Import({AutoConfigurationImportSelector.class}):
AutoConfigurationImportSelector 这个类的作用是:自动配置导入选择器(这个也是把一些组件扫描到ioc容器中,和上面Registrar.class不同的是,这个主要扫描的是springboot写好的一些配置类)。 - 从这个AutoConfigurationImportSelector 类的源码分析下去会发现有个spring.factories这个文件一直在出现,它就是自动配置的根源所在!
spring.factories这个配置文件有很多,每一个里面又标注了很多的配置类(这些配置类基本都在 org.springframework.boot.autoconfigure包下),通过反射实例化把这些配置类加载到IOC容器中,由此就实现了自动配置!
SpringBoot帮我们写了这么多的配置类,那这些配置类是怎么写的?又是在何时会生效呢?
下面以HttpEncodingAutoConfiguration这个配置类为例来解析:
首先这个类下有如下注释:
@Configuration // 表明这是一个配置类
// 这个注解就是启动后面()里面指定类的配置功能
//例如这个HttpEncodingProperties.class,像这种xxxProperties这种属性类会自动去读取我们写的配置文件(.yaml\.properties),把我们写的配置属性封装到这个属性类中,
//然后再把这个属性类放到spring容器中
@EnableConfigurationProperties({HttpEncodingProperties.class})
// @Conditional是Spring底层的一个注解,它一般用来判断一种条件,可以理解为if(),满足对应的条件则当前配置类生效,比如下面这个就是判断当前应用是否是web应用
@ConditionalOnWebApplication(
type = Type.SERVLET
)
// 判断当前项目中是否有CharacterEncodingFilter这个类
@ConditionalOnClass({CharacterEncodingFilter.class})
// 判断当前项目配置文件中是否存在()里的某个配置
@ConditionalOnProperty(
prefix = "spring.http.encoding",
value = {"enabled"},
matchIfMissing = true
)
所以,SpringBoot给我们提供的这些配置类就是根据不同的条件(@ConditionalOnxxx)来判断当前配置类是否生效
2.3 SpringApplication.run() 方法原理解析:
主程序中的run方法它实际上是开启了一个服务(run方法的解析要比上面注解的更复杂,大致记住以下几点吧),它主要做了以下几件事
- 推断当前应用类型是普通项目还是web项目
- 查找并加载所有的可用初始化器,设置到initializers属性中
- 查找出所有的监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
如果要了解run方法详细的底层原理,可以跟着下图的流程+源码来解析
2.4 SpringBoot自动装配原理总结
- springboot项目的pom文件中有个父依赖spring-boot-dependencies,在这里管理了boot项目中所有的依赖版本,所以我们导入依赖坐标时一般不用写版本号。
- pom文件中有很多功能性的启动器starter,我们需要什么功能就导入对应的启动器即可
- springboot项目在启动时会从类路径下读取所有的spring.factories配置文件,并将spring.factories其中对应的配置类(这些自动配置类都在org.springframework.boot.autoconfigure下)实例化到IOC容器中,以此来实现自动配置。
- 这些自动配置类(xxxAutoConfigurartion)根据**@Conditional注解来判断何时生效**,通过读取xxxProperties属性类(属性类会自动将我们写的配置属性如端口号,数据库连接信息等封装进去)来设置配置属性。然后将这些自动配置类放入IOC容器中,也就完成了springboot的自动配置。
三、IDEA快速创建springboot项目
- spring官方给我们提供了一个springboot项目模板,用idea可以快速创建
- 输入gav,选择java版本
- 选择需要的导入模板,比如web项目,lombok,thymeleaf模板引擎
然后finshed就完成了
四、SpringBoot整合其他技术框架
由于springboot自动装配的特点,在整合其他技术及框架时基本达到了开箱即用的效果,基本都是导入依赖再加上一些极少甚至不用加的一些配置信息即可。(这里的整合是按步骤来的,数据源、mybatis、mvc)
- springboot整合jdbc
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
在application.yaml配置文件中编写数据库连接信息
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
以上两步即可,需要注意的是,springboot默认给我们导入的数据源(数据源就是数据库连接信息存放的地方,也可使说就是数据库连接池,有了数据源我们就可以操作数据库了)是HikariDataSource ,这个数据源号称是javaweb当前最快的数据源。
- springboot整合druid
导入druid数据源依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
springboot因为默认使用hikari数据源,我们要切换成druid数据源只需要在配置文件中指定数据源的type即可
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源(在这里指定数据源使用哪个)
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#(绑定的方法就是我们要自己写一个数据源的配置类,把下面这些配置和数据源DruidSource绑定到一起,然后再把DruidSource注入到ioc容器中)
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
下面我们自己来写一个关于druid数据源的配置类
@Configuration // 标明这是一个配置类
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")// 读取配置文件中我们自己写的配置信息,并将这些属性值注入到DruidDataSource中
@Bean // 将DruidDataSource数据源添加的容器中,不再让springgboot自动创建(因为我们要使用druid数据源专有的属性)
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
Druid还具有数据监控功能,并且自带web界面方便用户查看。但是在使用之前我们还是要进行一定的配置(这是一些固定的配置不用记,需要的时候拿来用即可):
//配置 Druid 监控管理后台的Servlet;
//内置 Servlet 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
// 创建一个map,里面存放一些所需的键值对属性
Map<String, String> initParams = new HashMap<>();
// 设置登录的用户名和密码,这里的key是固定的
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "123456");
//后台允许谁可以访问
//initParams.put("allow", "localhost"):表示只有本机可以访问
//initParams.put("allow", ""):为空或者为null时,表示允许所有访问
initParams.put("allow", "");
//deny:Druid 后台拒绝谁访问
//initParams.put("hhl", "192.168.1.63");表示禁止此ip访问
//设置初始化参数
bean.setInitParameters(initParams);
return bean;
}
//配置 Druid 监控 之 web 监控的 filter
//WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//exclusions:设置哪些请求进行过滤排除掉,从而不进行统计
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
bean.setInitParameters(initParams);
//"/*" 表示过滤所有请求
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
- springboot整合mybatis
导入mybatis依赖(下面这个依赖是mybatis研发的,不是boot哦~)
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
数据源已经在第2点配置过了,再进行些简单的配置即可
mybatis:
type-aliases-package: com.hhl.pojo # 给此包下的javabean配置别名,默认类名首字母小写
mapper-locations: classpath:mybatis/mapper/*.xml # 扫描此路径下存放sql的xml文件
编写xxxdao
@Mapper // 此注解的作用其实就是生成一个该接口的实现类,和SSM整合里面MapperScannerConfigurer的作用差不多
@Repository
public interface DepartmentMapper {
// 获取所有部门信息
List<Department> getDepartments();
// 通过id获得部门
Department getDepartment(Integer id);
}
编写xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.DepartmentMapper">
<select id="getDepartments" resultType="Department">
select * from department;
</select>
</mapper>
mybatis的整合基本达到了开箱即用,导入依赖、配置下别名和扫描的xml包就可以用了!
- web静态资源处理及mvc自动配置扩展
根据boot源码可以得出以下结论,springboot项目中在以下路径下的资源可自动被识别为静态资源(classpath是指根目录,创建项目时那个java、resource包就是根目录):
“classpath:/META-INF/resources/”
“classpath:/resources/”
“classpath:/static/”
“classpath:/public/”
上面是boot默认的存放静态资源的地方,当然我们还可以自定义存放静态资源的路径:
(不配置静态资源过滤的话,jsp访问项目中的静态资源就会访问不到)
spring: # 注意:当你自定义静态资源路径后,上面的boot自动配置的默认静态资源路径就会失效了
resources:
static-locations: classpath:/jingtai/, classpath:/hhl/
mvc自动配置类:WebMvcAutoConfiguration ,这是boot提供的。
spring:
mvc:
view: # 配置视图解析器的前缀和后缀
prefix: /templates/
suffix: .html
我们也可以自己写一个自定义的mvc配置类,实现WebMvcConfigurer接口。
@EnableWebMvc:此注解放到我们自己的mvc配置类上时,就表明我们自己全面接管mvc的配置,不需要springboot的mvc自动配置功能了。(这个一般不用,了解即可)