SpringBoot快速入门
- Spring cloud:分布式应用
- Spring Security:web安全
0.知识回顾
- javaSE:主要学习OOP的思想
- MySql:持久化
- html+css+js+jquery+框架:视图层
- ssm:框架,简化了开发,配置较为复杂
war:在tomact中运行
- Spring再简化:SpringBoot-jar,内嵌tomcat,微服务架构
- 服务越来越多:Springcloud
1.简介
1.1学习总结
Springboot学习路线
- 是什么
- 配置如何编写yaml
- 自动装配原理
- 集成web开发:业务核心
- 集成数据库Druid:分布式数据分析平台
- 分布式开发:Dubbo+zookeeper
- swagger:接口文档
- 任务调度
- SpringSecurity:Shiro
SpringClud
- 微服务
- 快速入门
- Restful
- Eureka
- Ribbon
- Feign
- Hystrix
- Zuul路由网关
- SpringCloud Config
1.2环境要求
- jdk:1.8
- Spring Boot2.xx
- Maven
- IDEA
1.3Spring boot
- Spring:一个轻量级开发框架,为了解决企业级应用开发的复杂性而创建的,简化开发
如何简化开发
- 基于Pojo轻量级和最小侵入性编程
- 通过IOC,依赖注入和面向接口实习那松耦合
- 基于切面(AOP)和惯例式声明编程
- 通过切面和模板减少样式代码
SpringBoot
java web开发框架,Spring boot 帮我们简单,快速的创建一个独立的,生产级别的Spring应用,大多数SpringBoot 应用只需要少量配置即可快速整合Spring平台和第三方技术
特性
- 快速创建 独立SpringYingyong
- 直接嵌入 Tomact,Jetty
- 提供可选的starter,简化应用整合
- 为每个场景准备了一个依赖
- 没有冗余代码和XML配置要求
1.4什么是微服务
- 微服务是一种架构模式,提倡单一应用程序划分一组小服务,每个服务运行在自己独立的进程内,服务之间,互相协调,互相配置,为用户提倡最终的价值;
- 服务之间采用轻量级的通信机制互相沟通,每个服务围绕具体的业务构建,并且能够被独立的部署在生产环境中,
- 尽量避免统一的,集中式管理的服务管理机制,对具体的一个服务而言,根据上下文,选择合适的语言,工具,对齐构建,可以有一个非常轻量的集中式管理来协调业务,可以使用不同的语言编写,也可以用不同的数据储存
1.5创建一个Springboot项目
- 在springboot网站创建后下载(不推荐,IDEA已经集成Springboot开发环境)
- 直接使用IDEA创建
项目结构见上图
2.原理初探
2.1pom.xml
-
父依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.14</version> <relativePath/> <!-- lookup parent from repository --> </parent>
这里导入了一个父项目,用来管理项目的资源过滤和插件
-
我们查看其文件
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.7.14</version> </parent>
这是真正管理所有依赖版本的地方,SpringBoot的版本控制中心
所以我们导入大部分依赖,可以不写版本
web启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
-
导入这个依赖会,会自动导入web环境的所有依赖
-
所以我们使用什么功能,只需要找到对应的启动器即可
2.2主启动类
@SpringBootApplication//标注这是一个springboot应用
public class SpringStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringStudyApplication.class, args);//通过反射将对象启动
}
}
注解
在@SpringBootApplication
注解下
@SpringBootConfiguration
:Springboot配置类
@Configuration:spring配置类,对应spring的
xml
文件,相当于原来向bean注入的bean.xml文件@Component:spring组件负责启动应用
@EnableAutoConfiguration
:开启自动配置功能
@AutoConfigurationPackage
:自动配置包@Import({Registrar.class}) public @interface AutoConfigurationPackage { }
imort:Spring底层注解,给容器导入一个组件
@Import(AutoConfigurationPackages.Registrar.class)
:自动配置包注册// 获得候选的配置 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //这里的getSpringFactoriesLoaderFactoryClass()方法 //返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryCl ass(), 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; }
继续向下查看你,该方法调用了 SpringFactoriesLoader的静态方法,我们查看该方法
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); //这里它又调用了 loadSpringFactories 方法 return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }
继续点击
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { //获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注 的类本身 MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //去获取一个资源 "META-INF/spring.factories" Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); //将读取到的资源遍历,封装成为一个Properties while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryClassName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName, factoryName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
多次出现一个文件
spring.factories
,我们搜索打开会发现很多自动配置的文件,这就是自动配置的根源所在
结论
- SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取
EnableAutoConfiguration指定的值 - 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
- 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
- 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需
要的所有组件 , 并配置好这些组件 ; - 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作
方法
分析方法主要分两部分呢,一部分是实例化,一部分是方法的执行
SpringBootApplication实例化
- 判断应用是普通项目还是web项目
- 查找加载所有可用初始化器,设置到initalizers属性中
- 找出所有应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
run()方法
3.配置文件
3.1yaml语法
可以有两种配置文件,名称是固定的
-
application.properties
:key=value -
application.yml
: key: 空格 value;强大之处在于可以给实体类赋值 -
标记语言:以前的配置文件,大多数使用xml配置,
xml配置
<server> <port>8081<port> </server>
yaml配置
server: prot: 8080
- 空格不能省略
- 缩进控制层级关系
- 大小写十分敏感
3.2yaml注入配置文件
yaml更加强大的地方在于他可以直接给实体类进行赋值
3.2.1原始赋值方法
-
编写实体类
@Component //注册bean到容器中,使得这个类可以被扫描到 public class User { private String name; private Integer age; //有参无参构造、get、set方法、toString()方法 }
-
原来是如何给bean注入属性值的??
@Value
,我们可以测试一下@Component //注册bean public class User { @Value("张飞") private String name; @Value("18") private Integer age; }
-
进行测试
@SpringBootTest class SpringStudyApplicationTests { @Autowired//讲User注入进来 User user; @Test void contextLoads() { System.out.println(user); } }
3.2.2通过yaml文件赋值
- 编写User类
/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
名字必须一样
*/
@Component
@ConfigurationProperties(prefix = "user")//指向对应的yaml文件中的对应配置
public class User {
private String username;
private Integer age;
}
-
配置文件
#给user属性进行值的注入 user:#与prefix相对应 username: kobe age: 25
-
测试
同上
3.2.3 指定配置文件加载
@PorpertySource
:加载指定配置文件
@configurationProperties
:默认从全局配置文件中获取值
-
在setting中将字符集设置为UTF-8
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gLYLVIVQ-1692879253166)(C:\Users\LuckyRui\AppData\Roaming\Typora\typora-user-images\image-20230824112930486.png)]
-
在代码中指定加载user.properties文件
@Component @ConfigurationProperties(prefix = "user") @PropertySource("classpath:user.properties")//指定加载文件 public class User { private String username; private Integer age; }
-
测试
占位符
-
配置文件中还可使用占位符
user: name: qinjiang${random.uuid} # 随机uuid age: ${random.int} # 随机int
总结对比
1、@ConfigurationProperties只需要写一次即可 , @Value则需要每个字段都添加
2、松散绑定:这个什么意思呢? 比如我的yaml中写的last-name,这个和lastName是一样的, - 后面跟着的字母默认是大写的。这就是松散绑定。可以测试一下
3、JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性
4、复杂类型封装,yaml中可以封装对象 , 使用value就不支持。
使用场景
- 配置yaml和配置properties都可以获取到值 , 但是强烈推荐 yaml;
- 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;
- 如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties,不要犹豫!
4.JSR303数据检验和多环境切换
4.1JSR3.3
- 作用:用来检验输入内容的(前端同样可以实现)
- SpringBoot中使用
@validated
来检验数据,如果数据异常则会抛出异常,方便统一处理
-
导入对应的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
-
修改对应的实体类
@Component @ConfigurationProperties(prefix = "user") @Validated//数据校验 public class User { private String username; private Integer age; @Email(message = "邮箱格式错误")//必须是邮箱格式,否则发送邮箱格式错误 private String email; }
-
测试同上
其他规则
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) string is between min and max included.
日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则
.......等等
除此以外,我们还可以自定义一些数据校验规则
4.2 多环境切换
配置文件优先级
优先级1:项目路径下的config文件夹配置文件
优先级2:项目路径下配置文件
优先级3:资源路径下的config文件夹配置文件
优先级4:资源路径下配置文件
-
配置名称
application-{profile}.properties/yml
- application-test.properties:测试环境配置
- application-dev.properties:开发环境配置
-
在
application.properties
色湖之激活哪个环境#比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试; #我们启动SpringBoot,就可以看到已经切换到dev下的配置了; spring.profiles.active=dev
yaml的多文档块
#默认激活环境
server:
port: 8081
#选择要激活那个环境块
spring:
profiles:
active: prod#激活哪个模块
--- #分割线
server:
port: 8083
spring:
profiles: dev #配置环境的名称
---
server:
port: 8084
spring:
profiles: prod #配置环境的名称
5.SpringBootWeb开发总览
- 最大特点:自动装配
- xxxAutoConfiguration:向容器中自动配置组件
- xxProperties:自动配置类
解决的问题
- 导入静态资源
- 首页
- 写jsp的地方,模板引擎Thymeleaf
- 装配和扩展SpringMVC
- 增删改查
- 拦截器
5.1静态资源处理
SpringBoot中惊天资源的位置是有规定的,在 WebMvcAutoConfiguration
有体现
包的自动导入
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
// 已禁用默认资源处理
logger.debug("Default resource handling disabled");
return;
}
// 缓存控制
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
// webjars 配置
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
// 静态资源配置
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
- 所有的 /webjars/** , 都需要去 classpath:/META-INF/resources/webjars/ 找对应的资源;
- webjars,本质就是以jar导入我们的静态资源,网址查看需要的web开发需要的webjars
https://www.webjars.org
静态资源映射
我们项目中的静态资源改如何导入呢?可以存放在以下四个文件夹
- classpath:项目所在路径
"classpath:/META-INF/resources/"
"classpath:/resources/"
"classpath:/static/"
"classpath:/public/"
-
设置类
// 进入方法 public String[] getStaticLocations() { return this.staticLocations; } // 找到对应的值 private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS; // 找到路径 classpath就是-> resources资源目录 private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
6.SpringMVC自动配置原理
Springboot对SpringMVC做了哪些配置,是如何定制的呢?
6.1MVC配置
Spring MVC Auto-configuration
// Spring Boot为Spring MVC提供了自动配置,它可以很好地与大多数应用程序一起工作。
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
// 自动配置在Spring默认设置的基础上添加了以下功能:
The auto-configuration adds the following features on top of Spring’s defaults:
// 包含视图解析器
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
// 支持静态资源文件夹的路径,以及webjars
Support for serving static resources, including support for WebJars
// 自动注册了Converter:
// 转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
// Formatter:【格式化器,比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象】
Automatic registration of Converter, GenericConverter, and Formatter beans.
// HttpMessageConverters
// SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
Support for HttpMessageConverters (covered later in this document).
// 定义错误代码生成规则的
Automatic registration of MessageCodesResolver (covered later in this document).
// 首页定制
Static index.html support.
// 图标定制
Custom Favicon support (covered later in this document).
// 初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
/*
如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己
的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义
实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
*/
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration
(interceptors, formatters, view controllers, and other features), you can add your own
@Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide
custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or
ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
// 如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc进行注释。
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.
ContentNegotiatingViewResolver
-
内容协商视图解析器
-
组合所有的视图解析器
-
自动配置了
ViewResolver
(SpringMVC的视图解析器)也就是说可以根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染,转发,重定向
6.2格式器和转化器
- 找到格式转换器
@Bean
@Override
public FormattingConversionService mvcConversionService() {
// 拿到配置文件中的格式化规则
WebConversionService conversionService =
new WebConversionService(this.mvcProperties.getDateFormat());
addFormatters(conversionService);
return conversionService;
}
-
点进去
public String getDateFormat() { return this.dateFormat; } /** * Date format to use. For instance, `dd/MM/yyyy`. 默认的 */ private String dateFormat;
可以看到在我们的Properties文件中,我们可以进行自动配置它!
如果配置了自己的格式化方式,就会注册到Bean中生效,我们可以在配置文件中配置日期格式化的规则:
spring:
mvc:
date-format:
7.如何写一个web网站
前端
- 框架:组件,需要自己手动组合拼接
- 栅格系统
- 导航栏
- 侧边栏
- 模板:使用推荐模板,别人写好的,我们拿来改成自己需要的
开发过程
- 分别建立前端后端项目,测试通信
- 设计数据库
- 前端独立运行
- 数据接口对接:json
- 前后端联调
8.Springboot与数据库联动
对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。
Spring Boot 底层都是采用 Spring Data 的方式进行统一处理各种数据库,Spring Data 也是 Spring 中与 Spring Boot、Spring Cloud 等齐名的知名项目。
Sping Data 官网:https://spring.io/projects/spring-data
数据库相关的启动器 :可以参考官方文档:
https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
我们主要使用MyBatisPlus,具体内容可看MybatisPlus,这里我们介绍一下其他操作
8.1整合Druid数据源
注意不支持windows系统
优势
-
替换DBCP和C3P0,提供了一个高效,功能强大,可扩展性好的数据库连接池
-
可以监控数据库访问性能。内置StatFilter插件,能够详细分析SQL执行性能
-
数据库加密
-
SQL执行日志,提供了不同的LogFilter,能够支持Common-Logging,Log4j和jdkLog
按需选择对应的LogFilter,监控应用的数据库访问情况
-
扩展JDBC,如果有底层的编程需求,可以很方便的编写
步骤
-
添加依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency>
-
切换数据源
spring: datasource: username: root password: "000000" driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true type: com.alibaba.druid.pool.DruidDataSource
-
测试类中注入DataSource,然后获取他