springboot基础篇
# 一、官方文档
2.4版本文档 (opens new window) 最新版本文档 (opens new window)
查看版本新特性:https://github.com/spring-projects/spring-boot/wiki#release-notes
[2.4版本新特性](Spring Boot 2.4 Release Notes · spring-projects/spring-boot Wiki (github.com) (opens new window)) [2.5版本新特性](Spring Boot 2.5 Release Notes · spring-projects/spring-boot Wiki (github.com) (opens new window))
# 二、自定义banner
# 第一步:编写图案
Spring Boot banner在线生成工具 (opens new window)
# 第二步:修改启动类
原本我们的启动类,启动时的输出语句是这样的:
public static void main(String[] args) {
//SpringApplication.run(TestApplication.class, args);
SpringApplication springApplication = new SpringApplication(TestApplication.class);
springApplication.setBannerMode(Banner.Mode.CONSOLE);
springApplication.run(args);
}
2
3
4
5
6
# (一)banner模式中有三种形式:
OFF, CONSOLE,LOG;
# (二)banner里的spring版本号
${application.version}
这个是MANIFEST.MF文件中的版本号
${application.formatted-version}
这个是上面的的版本号前面加v后上括号
${spring-boot.version}
这个是springboot的版本号
${spring-boot.formatted-version}
同上
# (三)控制banner的样式
Spring提供了三个枚举类来设定字符的颜色,分别是:
AnsiColor: 用来设定字符的前景色 ${AnsiColor.BRIGHT_MAGENTA}
AnsiBackground: 用来设定字符的背景色
AnsiStyle: 用来控制加粗、斜体、下划线等等。
${AnsiColor.BRIGHT_YELLOW} ▄▄▄▄▄ ▄ ▄ ▄▄▄▄
▄▀ █▄█ █▀ ▀█
${AnsiColor.BRIGHT_RED} ▄▀ ▄█▄ █ █
${AnsiColor.BRIGHT_YELLOW} █▄▄▄▄ ▄▀ ▀▄ ██▄█▀
█
▀
${AnsiColor.BRIGHT_CYAN}${AnsiStyle.BOLD}Spring Boot版本:${spring-boot.version}
${AnsiColor.WHITE},-----.,-----.,-----.,-----.,-----.,-----.,-----.,-----.,-----.,-----.,-----.,-----.
'-----''-----''-----''-----''-----''-----''-----''-----''-----''-----''-----''-----'
2
3
4
5
6
7
8
9
参考文章:用了自定义Banner后,SpringBoot瞬间变的高大上了 (opens new window)
# 三、序列化
# 序列化Long转成String
问题:由于JS中Number的精度为
16位
(最大位17位,第17位精度不准),我们的ID用的Number 18位,传到客户端会丢失最后两位; 解决方式:Long序列化成String,传到客户端;
# 日期的序列化与反序列化
/**
* JacksonConfig 配置时间转换规则
* {@link ZxpJavaTimeModule}、默认时区等
*
* @author L.cm
* @author lengleng
* @author lishangbu
* @date 2020-06-15
*/
@Configuration
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class JacksonConfig implements WebMvcConfigurer {
private static final String ASIA_SHANGHAI = "Asia/Shanghai";
@Bean
@ConditionalOnMissingBean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> {
builder.locale(Locale.CHINA);
builder.timeZone(TimeZone.getTimeZone(ASIA_SHANGHAI));
builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
builder.serializerByType(Long.class, ToStringSerializer.instance);
builder.modules(new ZxpJavaTimeModule());
};
}
/**
* 增加GET请求参数中时间类型转换 {@link ZxpJavaTimeModule}
* <ul>
* <li>HH:mm:ss -> LocalTime</li>
* <li>yyyy-MM-dd -> LocalDate</li>
* <li>yyyy-MM-dd HH:mm:ss -> LocalDateTime</li>
* </ul>
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setTimeFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
registrar.setDateFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
registrar.registerFormatters(registry);
}
/**
* 避免form 提交 context-type 不规范中文乱码
* @return Filter
*/
@Bean
public OrderedCharacterEncodingFilter characterEncodingFilter() {
OrderedCharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(StandardCharsets.UTF_8.name());
filter.setForceEncoding(true);
filter.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filter;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
自定义序列化器
/**
* java 8 时间默认序列化
*
* @author L.cm
* @author lishanbu
*/
public class ZxpJavaTimeModule extends SimpleModule {
public ZxpJavaTimeModule() {
super(PackageVersion.VERSION);
// ======================= 时间序列化规则 ===============================
// yyyy-MM-dd HH:mm:ss
this.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
// yyyy-MM-dd
this.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
// HH:mm:ss
this.addSerializer(LocalTime.class,
new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
// ======================= 时间反序列化规则 ==============================
// yyyy-MM-dd HH:mm:ss
this.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
// yyyy-MM-dd
this.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
// HH:mm:ss
this.addDeserializer(LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
参考文章:
SpringBoot中对LocalDateTime进行格式化并解析 (opens new window)
# 四、代码测试
. junit4和junit5两个版本差别比较大
//这里只写SpringBootTest这个注解; 如果是junit4的话, 就要加上@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Test
void contextLoads() {
}
@BeforeAll
public static void beforeAll(){
LOG.info("beforeAll");
}
@BeforeEach
public void beforeEach(){
LOG.info("beforeEach"); //mockMvc = MockMvcBuilders.standaloneSetup(new IndexController()).build();
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@AfterEach
public void afterEach(){
LOG.info("afterEach");
}
@AfterAll
public static void afterAll(){
LOG.info("afterAll");
}
@Test
public void testTwo() throws Exception {
RequestBuilder request = MockMvcRequestBuilders.get("/index/getData")
.param("searchPhrase","ABC") //传参
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON); //请求类型 JSON
MvcResult mvcResult = mockMvc.perform(request)
.andExpect(MockMvcResultMatchers.status().isOk()) //期望的结果状态 200
.andDo(MockMvcResultHandlers.print()) //添加ResultHandler结果处理器,比如调试时 打印结果(print方法)到控制台
.andReturn(); //返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;
int status = mvcResult.getResponse().getStatus(); //得到返回代码
String content = mvcResult.getResponse().getContentAsString(); //得到返回结果
LOG.info("status:" + status + ",content:" + content);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@Slf4j
public class DataSourceMetaDataTest {
@BeforeAll
public static void init() {
log.info("init...");
}
@AfterAll
public static void destroy() {
log.info("destroy...");
}
@Test
public void test1() {
log.info("test1...");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 五、修改springboot依赖包的版本
1、查看spring-boot-dependencies
里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置即可
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
2
3
# 六、starter场景启动器
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景 https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
2
3
4
5
6
# 七、自动配置
# 1.2、自动配置
# 自动配好Tomcat
- 引入Tomcat依赖。
- 配置Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
2
3
4
5
6
# 自动配好SpringMVC
- 引入SpringMVC全套组件
- 自动配好SpringMVC常用组件(功能)
# 自动配好Web常见功能,如:字符编码问题
SpringBoot帮我们配置好了所有web开发的常见场景
默认的包结构
主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
无需以前的包扫描配置
想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.atguigu")
或者@ComponentScan 指定扫描路径
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
2
3
4
5
# 源码分析
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
2
3
4
5
# @SpringBootConfiguration
其绑定注解@Configuration
, 即是一个配置类
# @ComponentScan
包扫描器
# @EnableAutoConfiguration
1、@AutoConfigurationPackage
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
2
3
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
// 截取部分代码
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2、@Import(AutoConfigurationImportSelector.class)
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
2
3
4
5
6
7
如org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
# 按需开启自动配置项
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration 按照条件装配规则(@Conditional),最终会按需配置。
# 修改默认配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
给容器中加入了文件上传解析器;
2
3
4
5
6
7
8
9
10
# 总结:
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
生效的配置类就会给容器中装配很多组件
只要容器中有这些组件,相当于这些功能就有了
定制化配置
- 用户直接自己@Bean替换底层的组件
- 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties
# 八、容器功能
# 2.1、组件添加
# 1、@Configuration(proxyBeanMethods = false)
相当于写了一个xml配置文件,里面可以定义bean 同时配置类也添加到了容器
配置里面bean的循环依赖问题,
proxyBeanMethods = true
,即默认Full模式
,配置类变成代理加强类,里面的bean都是单例。最佳实战
- 配置类组件之间无依赖关系用
Lite模式
加速容器启动过程,减少判断 - 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用
Full模式
- 配置类组件之间无依赖关系用
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
*
*/
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
################################@Configuration测试代码如下########################################
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
public class MainApplication {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
//3、从容器中获取组件
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:"+(tom01 == tom02));
//4、Full模式返回: com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
//保持组件单实例
User user = bean.user01();
User user1 = bean.user01();
System.out.println(user == user1); // Full模式返回true; Lite模式返回false,相当于又new了一个bean
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:"+(user01.getPet() == tom)); // Full模式返回true; Lite模式返回false,即注入了一个新的bean
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
SSM三大框架整合详细教程(Spring+SpringMVC+MyBatis) - Jay36 - 博客园 (cnblogs.com) (opens new window)
# 2、@Bean、@Component、@Controller、@Service、@Repository
# 3、@ComponentScan、@Import
@Import(SpringUtil.class) // bean名称为全路径
# 4、@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
# 2.2、原生配置文件引入
# 1、@ImportResource
# 2.3、配置绑定
# 1、@ConfigurationProperties
只有这一个注解,还没有添加到容器, 可以与组件添加的注解结合使用,如
@Component
@EnableConfigurationProperties
# 2、@EnableConfigurationProperties + @ConfigurationProperties
@EnableConfigurationProperties
写在配置类上
# 3、@Component + @ConfigurationProperties
# 总结:
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
生效的配置类就会给容器中装配很多组件
只要容器中有这些组件,相当于这些功能就有了
定制化配置
- 用户直接自己@Bean替换底层的组件
- 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值
# 九、最佳实践
- 引入场景依赖
using-boot-starter (opens new window)
查看自动配置了哪些(选做)
- 自己分析,引入场景对应的自动配置一般都生效了
- 配置文件中
debug=true
开启自动配置报告。Negative
(不生效)Positive
(生效)
- 配置文件中
是否需要修改
- 自己分析。xxxxProperties绑定了配置文件的哪些。
自定义加入或者替换组件
@Bean、@Component。。。
自定义器 XXXXXCustomizer自定义器
... ..
# @Import高级用法
# 给容器中注册组件的方法:
- 包扫描+组件标注注解(@Controller @Service @Component @Repository )
- @Bean[导入第三方包里面的组件] ,如整合springsecurity
- @Import[快速给容器中导入一个组件],id默认是全类名。
- ImportSelector接口 返回需要导入的组件的全类名数组, 自定义逻辑,返回需要导入的组件,自定义一个类且要实现ImportSelector接口中的selectImports()方法
- ImportBeanDefinitionRegistrar接口 手动注册到容器中。
- 使用Spring提供的FactoryBean(工厂Bean),区别于普通的bean。
/**
* 自定义逻辑,返回需要导入的组件
* @author liayun
*
*/
public class MyImportSelector implements ImportSelector {
// 返回值:就是要导入到容器中的组件的全类名
// AnnotationMetadata:当前标注@Import注解的类的所有注解信息,也就是说不仅能获取到@Import注解里面的信息,还能获取到其他注解的信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 在这一行打个断点,debug调试一下
// 方法不要返回null值,否则会报空指针异常, 可以返回一个空数组
// return new String[]{}; // 可以返回一个空数组
return new String[]{"com.meimeixia.bean.Bule", "com.meimeixia.bean.Yellow"};
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 当前标注了@Import注解的类上的--所有注解信息--
* @param registry BeanDefinition注册类:把所有需要添加到容器中的bean,
* 调用BeanDefinitionRegistry.registerBeanDefinition()手动注册
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean color = registry.containsBeanDefinition("com.example.bean.Color");
boolean food = registry.containsBeanDefinition("com.example.bean.Food");
// 判断容器中是否有指定的bean,有的话才会注册Book.class
if (color&&food){
// 注册bean时,可以指定bean的名称
// 指定Bean定义信息:(Bean的类型、作用域等)
RootBeanDefinition beanDefinition = new RootBeanDefinition(Book.class);
registry.registerBeanDefinition("MyBook",beanDefinition);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# factory工厂示例
@Configuration
==== 使用自定义的MyImportBeanDefinitionRegistrar ===
@Import({Color.class, Animal.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
===================================================
public class MyConfig2 {
/**
* @return 将自己创建的Color类的FactoryBean注入到容器中
*/
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
public class ColorFactoryBean implements FactoryBean<Color> {
/**
*
* @return 返回一个Color对象,这个对象会返回到容器中
* @throws Exception
*/
public Color getObject() throws Exception {
return new Color();
}
/**
* 很重要
* @return 将来通过该FactoryBean注入到容器中的bean,根据bean的id获取到的bean的类型就是该方法返回的类型
*/
public Class<?> getObjectType() {
return Color.class;
}
/**
*
* @return 如果返回值为true, 表示这是一个单实例对象,在容器中只会保存一份。
* 如果返回值为false,表示这个是一个多实例对象,每次获取都会创建一个新的实例
*/
public boolean isSingleton() {
return true;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Test
public void test05(){
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);
String[] beans = annotationConfigApplicationContext.getBeanDefinitionNames();
for (String s : beans) {
System.out.println(s);
}
// 工厂Bean获取的是调用getObject创建的对象 拿到的是com.example.bean.Color。
Object bean1 = annotationConfigApplicationContext.getBean("colorFactoryBean");
System.out.println("Color类的FactoryBean:"+bean1.getClass());
// 就要从容器中获取对应类的工厂bean 加 & 标识
Object bean2 = annotationConfigApplicationContext.getBean("&colorFactoryBean");
System.out.println("Color类的FactoryBean:"+bean2.getClass());
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Spring与其它框架整合时,用的特别多,例如整合Mybaties
参考视频: 尚硅谷Spring注解驱动教程(雷丰阳源码级讲解)_哔哩哔哩_bilibili (opens new window)
参考笔记: 历时三个月,史上最详细的Spring注解驱动开发系列教程终于出炉了,给你全新震撼_李阿昀的博客-CSDN博客 (opens new window)
# springboot启动源码分析
# Springboot2核心
# 1、自动配置AutoConfig
简单配置甚至零配置即可运行项目
@Configuration:配置类
@EnableConfigurationProperties():开启某属性类,里面封装的是属性信息,相当于@ConfigurationProperties加载application.properties里面的信息,并用@Component将类交由spring管理
@ConditionalOnClass():当这个类存在时,再进行下面的步骤,否则就不进行下面的步骤了
@AutoConfigureAfter():当自动配置完成后,再执行里面的类
@ConfigurationOnMissBean():当这个bean不存在时,再添加bean类
@Bean:添加bean类
2
3
4
5
6
# 2、起步依赖 Starter
jar包的引入,解决jar版本冲突问题
# 3、actuator:springboot程序监控器
# 4、CLI:命令行
# 打成war包
# 1、修改war插件版本
默认是2,需要有web.xml文件,改成版本3以上,则不需要web.xml
<plugin>
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-war-plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin>
2
3
4
5
6
# 2、修改启动类
继承SpringBootServletInitializer,重写里面的configure即可
@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DemoApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2
3
4
5
6
7
8
9
10
11
12
# 3、修改tomcat的作用域
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> <!-- 不会被打到包里面-->
</dependency>
2
3
4
5
强烈不建议使用SpringBoot发布war包,原因有三:
1、默认的SpringBoot支持静态资源以jar包的方式发布部署
2、前后端分离,后端使用SpringBoot开发,前段就无所谓了,完全可以不依赖SpringBoot
3、在服务端加入Swagger插件,直接通过接口做测试,无需web界面
# Springboot Maven插件
Spring Boot2.4 Maven Plugin Documentation官方文档 (opens new window)
参考文章
Spring Boot 2 学习笔记(1 / 2)_KISS-CSDN博客 (opens new window)
第一季:SpringBoot2核心技术-基础入门 · 语雀 (yuque.com) (opens new window)
# 官方properties文档:
Common Application Properties (spring.io) (opens new window)