文章目录
- SpringBoot
- 创建SpringBoot应用
- 官网
- IDEA
- pom.xml文件
- 启动类
- 整合SpringMVC
- 整合配置类
- 静态资源处理
- Filter
- Tomcat
- 其他配置
- 整合MyBatis
- 约定大于配置的原理
- 配置文件中的值的获取
- yml形式的配置文件
- 约定大于配置的说明
- 注解
- 配置文件配置项
SpringBoot
- SpringBoot简化Spring阶段的配置繁琐的工作
- 快速搭建一个独立的生产级别的Spring应用
- 快速引入项目相关依赖
- 开箱即用,约定大于配置,大多数应用只需要极少的Spring配置
- 内置JavaEE容器(内置了Tomcat),可以以
jar
包的方式启动 - 核心点约定大于配置
- 提供一些约定项(其实就是默认值),在应用程序启动过程中,向容器中注册默认组件
创建SpringBoot应用
官网
- https://start.spring.io/
- 选择groupId、ArtifactId、版本号、扫描包、JDK版本、项目构建方式、开发语言、引入的其他依赖来创建SpringBoot应用
- 点击Generate会下载一个zip压缩包,解压开就是一个SpringBoot应用,同时也是一个Maven工程
IDEA
- 基本配置
pom.xml文件
- 引入的依赖中,artifactid中有一个starter这样的一个词,这样的依赖就叫其starter依赖
spring-boot-starter
- SpringBoot本身的依赖,所有的SpringBoot应用都有这个依赖
spring-boot-starter-xxx
- SpringBoot官方提供的依赖(groupid → org.springframework.boot),提供的是SpringBoot对xxx技术的支持
- 比如
spring-boot-starter-web
就是SpringBoot对web技术的支持 - 比如
spring-boot-starter-tomcat
就是SpringBoot对Tomcat的支持 - 比如
spring-boot-starter-json
就是SpringBoot对Json的支持
- 比如
- SpringBoot官方提供的依赖(groupid → org.springframework.boot),提供的是SpringBoot对xxx技术的支持
xxx-spring-boot-starter
第三方框架提供的依赖,提供的是SpringBoot对xxx技术的支持- 比如mybatis-spring-boot-starter,SpringBoot对MyBatis技术的支持
- 比如pagehelper-spring-boot-starter
- 通常在SpringBoot中要使用某一项技术,只需要引入其starter依赖就可以了
- 为什么引入其starter依赖就可以了?
- starter依赖中关联了其他依赖,当我们引入starter依赖的时候,会将该技术所需要的其他的依赖一同引入进来
- 举个例子:使用mybatis的话,引入mybatis-spring-boot-starter,mybatis、mybatis-spring、spring-jdbc都会被引入进来
- starter依赖中通常会包含另外一个依赖autoconfigure依赖
- autoconfigure依赖能够帮我们做自动配置,自动配置里最主要的是自动注册默认的组件
- starter依赖中关联了其他依赖,当我们引入starter依赖的时候,会将该技术所需要的其他的依赖一同引入进来
启动类
- SpringBoot应用最终打包为
Jar
包,packaging的默认值也是jar
- 运行jar包的命令:
java -jar frontend.jar
- 执行的jar包的main方法:
Start-Class: com.coo1heisenberg.frontend.FrontendApplication
- 启动类:main方法所处的类 → 启动类的包目录就是SpringBoot应用默认的扫描包目录
整合SpringMVC
- spring-boot-starter-web
整合配置类
- 配置类在SpringBoot阶段是可以使用的,但是有些内容产生了变化
- 不需要写扫描包目录了 → springboot提供的默认的扫描包目录:启动类所在的包目录
- 在配置类上增加
@EnableWebMvc
或@Configuration
- 如果使用@EnableWebMvc意味着全面接管SpringMVC的相关配置,默认配置失效
- 如果使用**@Configuration**意味着做的是配置项的补充 → 建议使用
eg:
// @EnableWebMvc
// @ComponentScan("")
/**
* 默认扫描包是启动类所在的包目录
*/
@Configuration
/**
* @Configuration:配置项的增量补充,存量(默认配置)是自动配置
*
* @EnableWebMvc:全面接管SpringMVC的配置,默认配置失效 → 通常不全面接管
*/
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
}
静态资源处理
- WebMvcConfigurer接口中的
addResourceHandlers(registry)
registry.addResourceHandler("映射范围").addResourceLocations("静态资源所处的位置")
- 上面这种方式可以在配置类中使用
- SpringBoot也给我们做了默认的配置
- mapping映射范围:
/**
- location资源所处的位置:
classpath:/public/
、classpath:/static/
、classpath:/META-INF/
等
- mapping映射范围:
- SpringBoot给我们提供了默认配置使用的是默认值;我们仍然可以使用其默认的配置,我们可以指定自定义的值
- 自定义的配置
- 配置文件是
.properties
→key=value
- 通过指定的key提供value,SpringBoot可以自动读取这些key对应的值
- 配置文件是
eg:
# http://localhost:8080/pic/1.jpg
# http://localhost:8080/pic/2.jpg
# path
spring.web.resources.static-locations=file:d:/test_photo/
# 文件路径
spring.mvc.static-path-pattern=/pic/**
# 执行 registry.addResourceHandler("映射范围").addResourceLocations("静态资源所处的位置")
# 会自动读取这两个值
总结:
- 静态资源处理
- 啥都不做采用默认值
- 配置文件中按照指定的key来提供对应的值
- 也可以写配置类
Filter
- 仍然可以使用
OncePerRequestFilter
,使用Filter直接将其注册为容器中的组件就会生效
eg:
@Component
public class CustomFilter extends OncePerRequestFilter {
@Autowired
XXXService xxxService;
@Autowired
XXXMapper xxxMapper;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
System.out.println("servlet执行之前");
filterChain.doFilter(request, response);
}
}
- 好处:配置起来方便;也可以使用容器中的其他组件
- HandlerInterceptor还是配置类的配置方式 →
addInterceptors
方法
eg:
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
}
Tomcat
- 端口号:
server.port
- 上下文路径:
server.servlet.context-path
eg:
# Tomcat配置
server.port=8080
server.servlet.context-path=/demo1
其他配置
- 配置类
- 配置文件
- prefix(前缀)为:
spring.web
- prefix(前缀)为:
spring.mvc
- 早期的一些SpringBoot版本:
spring.resources
→ 它现在变了spring.web.resources
- prefix(前缀)为:
- jackson的一些配置:
eg:
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
# 时区信息
spring.jackson.time-zone=GMT+8
整合MyBatis
- 引入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
- 提供配置项的值
- SpringBoot会根据这些默认向容器中注册DataSource组件的type:HikariCP( 默认的连接池)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
- 如果使用
druid
连接池,要使用全限定类名
# 将数据源修改为了Druid
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
- 需要提供:Mapper接口的包目录
@MapperScan
→ 写在启动类上就行
@MapperScan("com.coo1heisenberg.demo1.mapper")
@SpringBootApplication
public class Demo1WebApplication {
public static void main(String[] args) {
SpringApplication.run(Demo1WebApplication.class, args);
}
}
约定大于配置的原理
配置文件中的值的获取
- 现在自己向容器中注册一个DataSource,想把driverClassName、url、username、password这样的一些值写在配置文件中
- 没有从配置文件中取值
@Configuration
public class DataSourceConfiguration1 {
/**
* 魔法值:Magic value
* 指的是写死了的值,不能修改
*/
String driverClassName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8";
String userName = "root";
String password = "123456";
@Bean
public DataSource dataSource1() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
- @Value
${}
引用配置文件中的值,给@Value
注解对应的成员变量赋值- 注意事项:在容器中的组件中才可以使用@Value
@Configuration
public class DataSourceConfiguration2 {
/**
* SpEL(Spring Expression Language)写法
*/
@Value("${coo1heisenberg.datasource.driver-class-name}")
String driverClassName; // = "com.mysql.jdbc.Driver";
@Value("${coo1heisenberg.datasource.url}")
String url; // = "jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8";
@Value("${coo1heisenberg.datasource.username}")
String userName; // = "root";
@Value("${coo1heisenberg.datasource.password}")
String password; // = "123456";
@Bean
public DataSource dataSource2() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
coo1heisenberg.datasource.driver-class-name=com.mysql.jdbc.Driver
coo1heisenberg.datasource.url=jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8
coo1heisenberg.datasource.username=root
coo1heisenberg.datasource.password=123456
- @ConfigurationProperties
- 使用
set
方法给成员变量赋值 - 注意事项:在容器中的组件中才可以使用
@ConfigurationProperties
仍然是从配置文件中根据key来获得对应的值- key=@ConfigurationProperties注解的prefix属性值 + 成员变量名
- 使用
@Configuration
@Data
@ConfigurationProperties(prefix = "coo1heisenberg.datasource3")
public class DataSourceConfiguration3 {
String driverClassName; // = "com.mysql.jdbc.Driver";
String url; // = "jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8";
String userName; // = "root";
String password; // = "123456";
@Bean
public DataSource dataSource3() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
coo1heisenberg.datasource3.driver-class-name=com.mysql.jdbc.Driver
coo1heisenberg.datasource3.url=jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8
coo1heisenberg.datasource3.username=root
coo1heisenberg.datasource3.password=123456
- @EnableConfigurationProperties和@ConfigurationProperties
- 只有
Properties
组件注册过程有差别,其他的均一致 @EnableConfigurationProperties
注解写在配置上,其value属性写的Class数组,将Class数组对应的类注册为容器中的组件
- 只有
eg:
@ConfigurationProperties(prefix = "coo1heisenberg.datasource4")
@Data
public class DataSourceProperties4 {
String driverClassName; // = "com.mysql.jdbc.Driver";
String url; // = "jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8";
String userName; // = "root";
String password; // = "123456";
}
@Configuration
@EnableConfigurationProperties(DataSourceProperties4.class)
public class DataSourceConfiguration4 {
// @Autowired
// DataSourceProperties4 dataSourceProperties4;
DataSourceProperties4 dataSourceProperties4;
public DataSourceConfiguration4(DataSourceProperties4 dataSourceProperties4) {
this.dataSourceProperties4 = dataSourceProperties4;
}
@Bean
public DataSource dataSource3() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(dataSourceProperties4.getDriverClassName());
dataSource.setUrl(dataSourceProperties4.getUrl());
dataSource.setUsername(dataSourceProperties4.getUserName());
dataSource.setPassword(dataSourceProperties4.getPassword());
return dataSource;
}
}
coo1heisenberg.datasource4.driver-class-name=com.mysql.jdbc.Driver
coo1heisenberg.datasource4.url=jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode=true&characterEncoding=utf-8
coo1heisenberg.datasource4.username=root
coo1heisenberg.datasource4.password=123456
yml形式的配置文件
- 和
properties
一样都是key=value
形式的配置文件,只不过语法上有区别 - 可以将前面的
properties
配置文件修改为yml
配置文件- 如果key是多级的,比如
spring.datasource.driver-clsss-name
,这个就是3级,yml 要写 冒号、换行、空格缩进(几个空格都可以,但是同一级要对齐) - 等于:yml 要写 冒号 空格
- 如果有相同的前缀,省略掉重复的前缀
- 如果key是多级的,比如
eg:
spring:
web:
resources:
static-locations: file:d:/test_photo/
mvc:
static-path-pattern: /pic/**
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/coo1heisenberg?userUnicode:true&characterEncoding:utf-8
username: root
password: 123456
server:
port: 8080
servlet:
context-path: /demo1
约定大于配置的说明
- SpringBoot实现约定大于配置主要做的事情是帮我们注册一些默认的组件,而默认的组件是自动自动配置类来进行配置的
- 自动配置类:主要加载的使用autoconfigure依赖中的**/META-INF/spring.factories**文件里提供了自动配置类的列表
- 最近的几个版本的SpringBoot也提供了另外的一个位置的配置类:
/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@EnableAutoConfiguration
注解上有一个注解@Import({AutoConfigurationImportSelector.class})
@Import
注解可以直接写配置类Class → 把这个配置类注册为容器中的组件@Import
注解写的Class实现了Selector接口 → selectImports方法,返回值String[] → 配置类的全限定类名
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 读取/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 读取/META-INF/spring.factories 里的 org.springframework.boot.autoconfigure.EnableAutoConfiguration这个key对应的值
}
}
注解
@ConditionalOnXXX
→ 满足XXX条件其他的注解生效@ConditionalOnMissingXXX
→ 满足缺少XXX条件,其他的注解生效
eg:
// 应用程序中要引入对应的类 → 要有对应的依赖 → starter引入的
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
// 容器中DataSource类型的组件只有一个
@ConditionalOnSingleCandidate(DataSource.class)
eg:
- @Bean和@ConditionalOnMissingBean通常同时出现
- 如果你没有注册组件,那么
@Bean
生效,注册默认组件 - 如果你注册了组件,那么
@Bean
不会生效,就不会注册默认组件,以你注册的组件为准 - 综上可以得约定大于配置
- 如果你没有注册组件,那么
@Bean
@ConditionalOnMissingBean({TransactionManager.class})
DataSourceTransactionManager transactionManager(Environment environment, DataSource dataSource, ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
DataSourceTransactionManager transactionManager = this.createTransactionManager(environment, dataSource);
transactionManagerCustomizers.ifAvailable((customizers) -> {
customizers.customize(transactionManager);
});
return transactionManager;
}
.....
配置文件配置项
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.7.10</version>
</dependency>
- 这个依赖会帮我们新增对应的json
- 生成之后,在
resources
目录下新增一个文件夹META-INF
- 生成之后,在
eg:
{
"groups": [
{
"name": "coo1heisenberg.datasource3",
"type": "com.coo1heisenberg.demo2.config3.DataSourceConfiguration3",
"sourceType": "com.coo1heisenberg.demo2.config3.DataSourceConfiguration3"
},
{
"name": "coo1heisenberg.datasource4",
"type": "com.coo1heisenberg.demo2.config4.DataSourceProperties4",
"sourceType": "com.coo1heisenberg.demo2.config4.DataSourceProperties4"
}
],
"properties": [
{
"name": "coo1heisenberg.datasource3.driver-class-name",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config3.DataSourceConfiguration3"
},
{
"name": "coo1heisenberg.datasource3.password",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config3.DataSourceConfiguration3",
"defaultValue": "123456"
},
{
"name": "coo1heisenberg.datasource3.url",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config3.DataSourceConfiguration3"
},
{
"name": "coo1heisenberg.datasource3.user-name",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config3.DataSourceConfiguration3"
},
{
"name": "coo1heisenberg.datasource4.driver-class-name",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config4.DataSourceProperties4"
},
{
"name": "coo1heisenberg.datasource4.password",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config4.DataSourceProperties4"
},
{
"name": "coo1heisenberg.datasource4.url",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config4.DataSourceProperties4"
},
{
"name": "coo1heisenberg.datasource4.user-name",
"type": "java.lang.String",
"sourceType": "com.coo1heisenberg.demo2.config4.DataSourceProperties4"
}
],
"hints": []
}