SpringBoot学习笔记
cnblogs 2024-07-18 08:09:01 阅读 75
微服务阶段
javaSE:OOP
mySQL:持久化
html+css+js+jquery+框架:视图,框架不熟练,css不好;
javaweb:独立开发MVC三层架构的的网站:原始
ssm:框架:简化了我们的开发流程,配置也开始较为复杂;
war:tomcat运行
spring再简化:springBoot-jar:内嵌tomcat;微服务架构!
服务越来越多:springcloud!
高内聚,低耦合
微服务(Microservices)——Martin Flower阅读笔记
整体风格(monolithic style):一个完整应用程序(monolithic application)构建成一个单独的单元。企业级应用通常被构建成三个主要部分:客户端用户界面(由运行在客户机器上的浏览器的 HTML 页面、Javascript 组成)、数据库(由许多的表构成一个通用的、相互关联的数据管理系统)、服务端应用。服务端应用处理 HTTP 请求,执行领域逻辑(domain logic),检索并更新数据库中的数据,使用适当的 HTML 视图发送给浏览器。服务端应用是完整的 ,是一个单独的的逻辑执行。任何对系统的改变都涉及到重新构建和部署一个新版本的服务端应用程序。(单一应用程序的弊端,可拓展性较差,维护难度较大)
微服务架构风格(microservice architectural style):把应用程序构建为一套服务。事实是,服务可以独立部署和扩展,每个服务提供了一个坚实的模块边界,甚至不同的服务可以用不同的编程语言编写。它们可以被不同的团队管理。
微服务风格的特性:
组件化(Componentization )与服务(Services)
围绕业务功能的组织
不是按照技术构建团队而是按照业务进行组建,意味着团队内将由不同技术方向的成员构成,如UI工程师、后端工程师、数据工程师等,而非先前的单一专业。
产品不是项目:团队应该负责产品的整个生命周期
强化终端及弱化通道:微服务的应用致力松耦合和高内聚
分散治理:不同的需求,不同的业务,不同的微服务,不同的技术,不同的语言,相同的项目。
分散数据管理:当对概念模式下决心进行分散管理时,微服务也决定着分散数据管理。微服务让每个服务管理自己的数据库:无论是相同数据库的不同实例,或者是不同的数据库系统。这种方法叫Polyglot Persistence(多种持久化方法)。微服务架构强调服务间事务的协调,并清楚的认识一致性只能是最终一致性以及通过补偿运算处理问题。
基础设施自动化:微服务的出现使得系统的运维测试工作难度加大,需要对系统的打包发布测试等环节尽可能的采取自动化手段进行,因此有必要对软件开发流程中的部分环节采取自动化改进。
容错性设计:使用服务作为组件的一个结果在于应用需要有能容忍服务的故障的设计。任务服务可能因为供应商的不可靠而故障,客户端需要尽可能的优化这种场景的响应。跟整体构架相比,这是一个缺点,因为它带来的额外的复杂性。
服务可以随时故障,快速故障检测,乃至,自动恢复变更非常重要。监控系统可以提供一种早期故障告警系统,让开发团队跟进并调查。对于微服务框架来说,这相当重要,因为微服务相互的通信可能导致紧急意外行为。
设计改进:决定拆分我们应用的原则是什么呢?首要的因素,组件可以被独立替换和更新的,这意味着我们寻找的关键在于,我们要想象着重写一个组件而不影响它们之前的协作关系。事实上,许多的微服务小组给它进一步的预期:服务应该能够报废的,而不是要长久的发展的。其次,可代替是模块化开发中的一个特例,它是用模块来应对需要变更的。把组件改成服务,增加了细化发布计划的一个机会。
微服务是未来吗?
微服务构架风格是一个非常重要的想法:一个值得企业应用中认真考虑的东西。
微服务架构的成功依赖于软件如何拆分成适合的模块。指出不同模块的准确边界实际上是非常困难的。改良设计要承认边界的权益困境和因此带来的易于重构的重要性。
spring Boot
环境:
jdk:1.8
maven:3.6.1
springboot:最新版
IDEA
一、第一个SpringBoot程序
1.1 如何创建springboot项目
方法一:可以在管网配置后直接下载,导入IDEA开发(Spring Initializr)或者使用aliyun的Cloud Native App Initializer (aliyun.com)来创建新的springboot项目
注:aliyun目前支持使用java8创建springboot项目,
方法二:直接使用IDEA创建一个springboot项目(其实和官网类似,一般开发直接在IDEA中创建)
注:如果初学者电脑安装的是1.8,可以额外安装jdk17
1.2 Springboot自动装配原理
pom.xml
- spring-boot-dependencies:核心依赖在父工程中!
- 我们在写或者引入一些springboot依赖的时候,不需要指定版本,就是因为有这些版本仓库
启动器
<code><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
启动器说白了就是springboot的启动场景
比如spring-boot-starter-web,它就会帮我们自动导入web环境的所有依赖!
springboot会将所有的功能场景都变成一个个的启动器
我们要使用什么功能,就只需要找到对应的启动器就可以了
所有springboot启动器列表(version2.7.18)Spring Boot Reference Documentation
主程序
//程序主入口
//本身就是spring的一个组件
//@SpringBootApplication标注这个类是一个springboot的应用
@SpringBootApplication
public class SpringBoot17Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot17Application.class, args);
}
}
注解:
@SpringBootConfiguration:springboot的配置
@Configuration:spring的配置类
@Component:说明这也是一个spring的组件
@EnableAutoConfiguration:自动配置,获取pom中的全部依赖并导入
@AutoConfigurationPackage:自动配置包
@Import({AutoConfigurationPackages.Registrar.class}):自动配置`包注册`
@Import({AutoConfigurationImportSelector.class}):自动配置导入选择器
//获取所有的配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
.getCandidates();
Assert.notEmpty(configurations,
"No auto configuration classes found in "
+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
需要注意,springboot2和3在这个地方的写法略微有些不同,上面的是springboot3的代码,下满是2的
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
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;
}
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
META-INF/spring.factories:自动配置的核心文件
结论:springboot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立。如果导入了对应的start,就有对应的启动器了,有了启动器,自动装配就会生效,然后就配置成功。
- springboot在启动的时候,从类路径下/META-INF/spring.factories获取指定的值;
- 将这些自动配置的类导入容器,自动配置就会生效,帮程序员进行自动配置
- 以前我们需要自动配置的东西,现在springboot帮我们做了
- 整合JavaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure
- 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器中。
- 容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件,并自动配置,@Configuration
- 有了自动配置类,免去了我们手动编写配置类的需求。
1.3 SpringApplication.Run
SpringApplication.run分析
public static void main(String[] args) {
SpringApplication.run(SpringLearningApplication.class, args);
}
该方法分成两部分,一部分是SpringApplication的实例化,另一个是run方法的执行。
SpringApplication分析
这个类主要做了以下四件事情
- 推断应用的类型是普通项目还是Web项目
- 查找并加载所有可用的初始化器,设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
构造器如下:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = Collections.emptySet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
this.applicationStartup = ApplicationStartup.DEFAULT;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
Docker:进程
关于Springboot,谈谈个人理解:
- 自动装配
- run()
全面接管SpringMVC的配置
1.4 SpringBoot:配置文件及自动装配原理
配置文件
SpringBoot使用一个全局配置文件,配置文件名称是固定的(application)
- application.properties(等号取值)
- 语法结构:key=value
- application.yml(冒号取值,一定注意空格)
- 语法结构:key:空格 value
配置文件的作用:修改SpringBoot自动装配的默认值,因为SpringBoot在底层都给我们自动配置好了;
- application.properties(等号取值)
YAML
标记语言
- 以前的配置文件,大多数使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml
yaml配置
server:
port: 8081
xml配置
<server>
<port>8081</port>
</server>
YAML基本语法
spring.application.name=springboot-02-config
# 官方配置太多了,需要了解原理:一通百通
# properties智能保存键值对
# 注意,yaml文件对空格的要求十分严格,一旦空格有误容易导致上下级属性关系错位
# 可以注入到配置类中
# 普通的key-value
server:
port: 8081
# 还可以存储对象
student:
name: wut
age: 25
# 或者将对象写在行内
student1: {name: wut,age: 24}
# 甚至可以保存数组
pets:
- cat
- dog
- pig
# 数组也可以这么写
pets1: [cat,dog,pig]
松散绑定
使用@ConfigurationProperties(prefix = "xxx")注解可以进行松散绑定,采取驼峰命名规则就可以实现前后端赋值,但是注意如果是字段上采取@Value("xx")这种针对某个单一字段进行辅助,没有松散绑定,需要字段名一致才能实现。
JSR303数据校验
相当于在赋值的时候添加一层过滤器,对赋值内容进行校验,有点类似于前端的内容检查。
开启方法是在类上添加@Validated注解
-
@ConfigurationProperties @Value 功能 批量注入配置文件中的属性 一个个指定代码中参数取值 松散绑定(松散语法) 支持 不支持 SpEl(Spring Expression Language) 不支持 支持 JSR303数据校验 支持 不支持 复杂类型封装 支持 不支持
注:
在使用@ConfigurationProperties(prefix = "xxx")注解时,会出现这样的东西,原因是“Spring Boot配置注解执行器没有配置”。配置注解执行器配置完成后,当执行类中已经定义了对象和该对象的字段后,在配置文件中对该类赋值时,便会非常方便的弹出提示信息。但不配置也不影响系统运行。解决这个问题的方法如下:
<code><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
这个地方有一个需要注意的地方,如果当前springboot版本为2.3.0以上,则需要手动在springboot的启动中引入相关的校验包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
另外注意一点springboot3不再支持使用原来的javax.validatio,需要使用jakarta.validation,这一点是springboot2和springboot3之间的区别。
多环境配置以及配置文件位置
配置环境优先级,springboot项目一共有四个地方可以配置相关环境,分别是
optional:classpath:/config/
optional:file:./config/*/
optional:classpath:custom-config/
optional:file:./custom-config/
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。