重庆住房城乡建设网站,昌宁县住房和城乡建设网站,常州微信网站制作,足球网站开发SpringBoot——感谢尚硅谷官方文档 1 Spring与SpringBoot1、Spring能做什么1.1、Spring的能力1.2、Spring的生态1.3、Spring5重大升级1.3.1、响应式编程1.3.2、内部源码设计 2、为什么用SpringBoot2.1、SpringBoot优点2.2、SpringBoot缺点 3、时代背景3.1、微服务3.2、分布式分… SpringBoot——感谢尚硅谷官方文档 1 Spring与SpringBoot1、Spring能做什么1.1、Spring的能力1.2、Spring的生态1.3、Spring5重大升级1.3.1、响应式编程1.3.2、内部源码设计 2、为什么用SpringBoot2.1、SpringBoot优点2.2、SpringBoot缺点 3、时代背景3.1、微服务3.2、分布式分布式的困难分布式的解决 3.3、云原生上云的困难上云的解决 4、如何学习SpringBoot4.1、官网文档架构 2 SpringBoot2入门1、系统要求1.1、maven设置 2、HelloWorld2.1、创建maven工程2.2、引入依赖2.3、创建主程序2.4、编写业务2.5、测试2.6、简化配置2.7、简化部署 3 了解自动配置原理1、SpringBoot特点1.1、依赖管理1.2、自动配置SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面 2、容器功能2.1、组件添加1、Configuration2、Bean、Component、Controller、Service、Repository3、ComponentScan、Import4、Conditional 2.2、原生配置文件引入1、ImportResource 2.3、配置绑定1、ConfigurationProperties2、EnableConfigurationProperties ConfigurationProperties3、Component ConfigurationProperties 3、自动配置原理入门3.1、引导加载自动配置类1、SpringBootConfiguration2、ComponentScan3、EnableAutoConfiguration1、AutoConfigurationPackage2、Import(AutoConfigurationImportSelector.class) 3.2、按需开启自动配置项3.3、修改默认配置3.4、最佳实践 4、开发小技巧4.1、Lombok4.2、dev-tools4.3、Spring Initailizr项目初始化向导0、选择我们需要的开发场景1、自动依赖引入2、自动创建项目结构3、自动编写好主配置类 4 SpringBoot核心功能1、文件类型1.1、properties1.2、yaml1.2.1、简介1.2.2、基本语法1.2.3、数据类型1.2.4、示例 2、配置提示 5 Web开发1、SpringMVC自动配置概览2、简单功能分析2.1、静态资源访问1、静态资源目录2、静态资源访问前缀3、webjar 2.2、欢迎页支持2.3、自定义 Favicon2.4、静态资源配置原理1、配置类只有一个有参构造器2、资源处理的默认规则3、欢迎页的处理规则4、favicon 3、请求参数处理0、请求映射1、rest使用与原理2、请求映射原理 1、普通参数与基本注解1.1、注解1.2、Servlet API1.3、复杂参数imgimg1.4、自定义对象参数 2、POJO封装过程3、参数处理原理1、HandlerAdapter2、执行目标方法3、参数解析器-HandlerMethodArgumentResolver4、返回值处理器5、如何确定目标方法每一个参数的值5.1、挨个判断所有参数解析器那个支持解析这个参数5.2、解析这个参数的值5.3、自定义类型参数 封装POJO img6、目标方法执行完成7、处理派发结果 4、数据响应与内容协商1、响应JSON1.1、jackson.jarResponseBodyimg1、返回值解析器2、返回值解析器原理 img1.2、SpringMVC到底支持哪些返回值1.3、HTTPMessageConverter原理1、MessageConverter规范2、默认的MessageConverter 2、内容协商1、引入xml依赖2、postman分别测试返回json和xml3、开启浏览器参数方式内容协商功能4、内容协商原理5、自定义 MessageConverter 5、视图解析与模板引擎1、视图解析1、视图解析原理流程 2、模板引擎-Thymeleaf1、thymeleaf简介2、基本语法1、表达式2、字面量3、文本操作4、数学运算5、布尔运算6、比较运算7、条件运算8、特殊操作 3、设置属性值-th:attr4、迭代5、条件运算 6、属性优先级 3、thymeleaf使用1、引入Starter2、自动配置好了thymeleaf 3、页面开发 4、构建后台管理系统1、项目创建2、静态资源处理3、路径构建4、模板抽取5、页面跳转6、数据渲染 6、拦截器1、HandlerInterceptor 接口2、配置拦截器3、拦截器原理 7、文件上传1、页面表单2、文件上传代码3、自动配置原理 8、异常处理1、错误处理1、默认规则2、定制错误处理逻辑3、异常处理自动配置原理4、异常处理步骤流程 9、Web原生组件注入Servlet、Filter、Listener1、使用Servlet API2、使用RegistrationBean 10、嵌入式Servlet容器1、切换嵌入式Servlet容器2、定制Servlet容器 11、定制化原理1、定制化的常见方式2、原理分析套路 6 数据访问1、SQL1、数据源的自动配置-**HikariDataSource**1、导入JDBC场景img2、分析自动配置1、自动配置的类 3、修改配置项4、测试 2、使用Druid数据源1、druid官方github地址2、自定义方式1、创建数据源2、StatViewServlet3、StatFilter 3、使用官方starter方式1、引入druid-starter2、分析自动配置3、配置示例 3、整合MyBatis操作1、配置模式2、注解模式3、混合模式 4、整合 MyBatis-Plus 完成CRUD1、什么是MyBatis-Plus2、整合MyBatis-Plus3、CRUD功能 2、NoSQL1、Redis自动配置2、RedisTemplate与Lettuce3、切换至jedis 07、单元测试1、JUnit5 的变化2、JUnit5常用注解3、断言assertions1、简单断言2、数组断言3、组合断言4、异常断言5、超时断言6、快速失败 4、前置条件assumptions5、嵌套测试6、参数化测试7、迁移指南08、指标监控1、SpringBoot Actuator1、简介2、1.x与2.x的不同3、如何使用4、可视化 2、Actuator Endpoint1、最常使用的端点2、Health Endpoint3、Metrics Endpoint4、管理Endpoints1、开启与禁用Endpoints2、暴露Endpoints 3、定制 Endpoint1、定制 Health 信息 2、定制info信息1、编写配置文件2、编写InfoContributor 3、定制Metrics信息1、SpringBoot支持自动适配的Metrics2、增加定制Metrics 4、定制Endpoint 09、原理解析1、Profile功能1、application-profile功能2、Profile条件装配功能3、profile分组 2、外部化配置1、外部配置源2、配置文件查找位置3、配置文件加载顺序4、指定环境优先外部优先后面的可以覆盖前面的同名配置项 3、自定义starter1、starter启动原理2、自定义starter 4、SpringBoot原理1、SpringBoot启动过程2、Application Events and Listeners 仅自用如有侵权立刻删——感谢【尚硅谷】官方文档
1 Spring与SpringBoot
1、Spring能做什么
1.1、Spring的能力 1.2、Spring的生态
https://spring.io/projects/spring-boot
覆盖了
web开发
数据访问
安全控制
分布式
消息服务
移动开发
批处理
…
1.3、Spring5重大升级
1.3.1、响应式编程 1.3.2、内部源码设计
基于Java8的一些新特性如接口默认实现。重新设计源码架构。
2、为什么用SpringBoot
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.
能快速创建出生产级别的Spring应用
2.1、SpringBoot优点 Create stand-alone Spring applications 创建独立Spring应用 Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files) 内嵌web服务器 Provide opinionated ‘starter’ dependencies to simplify your build configuration 自动starter依赖简化构建配置 Automatically configure Spring and 3rd party libraries whenever possible 自动配置Spring以及第三方功能 Provide production-ready features such as metrics, health checks, and externalized configuration 提供生产级别的监控、健康检查及外部化配置 Absolutely no code generation and no requirement for XML configuration 无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
2.2、SpringBoot缺点
人称版本帝迭代快需要时刻关注变化封装太深内部原理复杂不容易精通
3、时代背景
3.1、微服务
James Lewis and Martin Fowler (2014) 提出微服务完整概念。https://martinfowler.com/microservices/
In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.-- James Lewis and Martin Fowler (2014) 微服务是一种架构风格 一个应用拆分为一组小型服务 每个服务运行在自己的进程内也就是可独立部署和升级 服务之间使用轻量级HTTP交互 服务围绕业务功能拆分 可以由全自动部署机制独立部署 去中心化服务自治。服务可以使用不同的语言、不同的存储技术
3.2、分布式 分布式的困难 远程调用 服务发现 负载均衡 服务容错 配置管理 服务监控 链路追踪 日志管理 任务调度 …
分布式的解决
SpringBoot SpringCloud 3.3、云原生
原生应用如何上云。 Cloud Native
上云的困难 服务自愈 弹性伸缩 服务隔离 自动化部署 灰度发布 流量治理 …
上云的解决 4、如何学习SpringBoot
4.1、官网文档架构 查看版本新特性
https://github.com/spring-projects/spring-boot/wiki#release-notes 2 SpringBoot2入门
1、系统要求 Java 8 兼容java14 . Maven 3.3 idea 2019.1.2
1.1、maven设置
mirrorsmirroridnexus-aliyun/idmirrorOfcentral/mirrorOfnameNexus aliyun/nameurlhttp://maven.aliyun.com/nexus/content/groups/public/url/mirror/mirrorsprofilesprofileidjdk-1.8/idactivationactiveByDefaulttrue/activeByDefaultjdk1.8/jdk/activationpropertiesmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.targetmaven.compiler.compilerVersion1.8/maven.compiler.compilerVersion/properties/profile/profiles
12345678910111213141516171819202122232、HelloWorld
需求浏览发送/hello请求响应 HelloSpring Boot 2
2.1、创建maven工程
2.2、引入依赖
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.4.RELEASE/version/parentdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency/dependencies
12345678910111213142.3、创建主程序
/*** 主程序类* SpringBootApplication这是一个SpringBoot应用*/
SpringBootApplication
public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplication.class,args);}
}
12345678910112.4、编写业务
RestController
public class HelloController {RequestMapping(/hello)public String handle01(){return Hello, Spring Boot 2!;}}
12345678910112.5、测试
直接运行main方法
2.6、简化配置
application.properties
server.port8888
12.7、简化部署 buildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build
12345678把项目打成jar包直接在目标服务器执行即可。
注意点
取消掉cmd的快速编辑模式
3 了解自动配置原理
1、SpringBoot特点
1.1、依赖管理
父项目做依赖管理
依赖管理
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.4.RELEASE/version
/parent他的父项目parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.3.4.RELEASE/version/parent几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
123456789101112131415开发导入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、所有场景启动器最底层的依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactIdversion2.3.4.RELEASE/versionscopecompile/scope
/dependency
123456789101112无需关注版本号自动版本仲裁
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar要写版本号。
12可以修改默认版本号
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置propertiesmysql.version5.1.43/mysql.version/properties
123451.2、自动配置 自动配好Tomcat 引入Tomcat依赖。 配置Tomcat
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-tomcat/artifactIdversion2.3.4.RELEASE/versionscopecompile/scope/dependency
123456自动配好SpringMVC 引入SpringMVC全套组件 自动配好SpringMVC常用组件功能 自动配好Web常见功能如字符编码问题 SpringBoot帮我们配置好了所有web开发的常见场景 默认的包结构 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来 无需以前的包扫描配置 想要改变扫描路径SpringBootApplication(scanBasePackages“com.atguigu”) 或者ComponentScan 指定扫描路径
SpringBootApplication
等同于
SpringBootConfiguration
EnableAutoConfiguration
ComponentScan(com.atguigu.boot)
12345各种配置拥有默认值 默认配置最终都是映射到某个类上如MultipartProperties 配置文件的值最终会绑定每个类上这个类会在容器中创建对象 按需加载所有自动配置项 非常多的starter 引入了哪些场景这个场景的自动配置才会开启 SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面 …
2、容器功能
2.1、组件添加
1、Configuration 基本使用 Full模式与Lite模式 示例 最佳实战 配置 类组件之间无依赖关系用Lite模式加速容器启动过程减少判断 配置类组件之间有依赖关系方法会被调用得到之前单实例组件用Full模式
#############################Configuration使用示例######################################################
/*** 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、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca1654a892MyConfig 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);User user01 run.getBean(user01, User.class);Pet tom run.getBean(tom, Pet.class);System.out.println(用户的宠物(user01.getPet() tom));}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778792、Bean、Component、Controller、Service、Repository
3、ComponentScan、Import * 4、Import({User.class, DBHelper.class})* 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名****/Import({User.class, DBHelper.class})
Configuration(proxyBeanMethods false) //告诉SpringBoot这是一个配置类 配置文件
public class MyConfig {
}
1234567891011Import 高级用法 https://www.bilibili.com/video/BV1gW411W7wy?p8
4、Conditional
条件装配满足Conditional指定的条件则进行组件注入 测试条件装配
Configuration(proxyBeanMethods false) //告诉SpringBoot这是一个配置类 配置文件
//ConditionalOnBean(name tom)
ConditionalOnMissingBean(name tom)
public class MyConfig {/*** Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象* return*/Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值就是组件在容器中的实例public User user01(){User zhangsan new User(zhangsan, 18);//user组件依赖了Pet组件zhangsan.setPet(tomcatPet());return zhangsan;}Bean(tom22)public Pet tomcatPet(){return new Pet(tomcat);}
}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);}boolean tom run.containsBean(tom);System.out.println(容器中Tom组件tom);boolean user01 run.containsBean(user01);System.out.println(容器中user01组件user01);boolean tom22 run.containsBean(tom22);System.out.println(容器中tom22组件tom22);}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546472.2、原生配置文件引入
1、ImportResource
beans.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsdbean idhaha classcom.atguigu.boot.bean.Userproperty namename valuezhangsan/propertyproperty nameage value18/property/beanbean idhehe classcom.atguigu.boot.bean.Petproperty namename valuetomcat/property/bean
/beans
ImportResource(classpath:beans.xml)
public class MyConfig {}测试boolean haha run.containsBean(haha);boolean hehe run.containsBean(hehe);System.out.println(hahahaha);//trueSystem.out.println(hehehehe);//true
1234567891011121314151617181920212223242.3、配置绑定
如何使用Java读取到properties文件中的内容并且把它封装到JavaBean中以供随时使用
public class getProperties {public static void main(String[] args) throws FileNotFoundException, IOException {Properties pps new Properties();pps.load(new FileInputStream(a.properties));Enumeration enum1 pps.propertyNames();//得到配置文件的名字while(enum1.hasMoreElements()) {String strKey (String) enum1.nextElement();String strValue pps.getProperty(strKey);System.out.println(strKey strValue);//封装到JavaBean。}}}
123456789101112131、ConfigurationProperties
/*** 只有在容器中的组件才会拥有SpringBoot提供的强大功能*/
Component
ConfigurationProperties(prefix mycar)
public class Car {private String brand;private Integer price;public String getBrand() {return brand;}public void setBrand(String brand) {this.brand brand;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price price;}Overridepublic String toString() {return Car{ brand brand \ , price price };}
}
123456789101112131415161718192021222324252627282930313233342、EnableConfigurationProperties ConfigurationProperties
3、Component ConfigurationProperties
EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
123453、自动配置原理入门
3.1、引导加载自动配置类
SpringBootConfiguration
EnableAutoConfiguration
ComponentScan(excludeFilters { Filter(type FilterType.CUSTOM, classes TypeExcludeFilter.class),Filter(type FilterType.CUSTOM, classes AutoConfigurationExcludeFilter.class) })
public interface SpringBootApplication{}1234567891、SpringBootConfiguration
Configuration。代表当前是一个配置类
2、ComponentScan
指定扫描哪些Spring注解
3、EnableAutoConfiguration
AutoConfigurationPackage
Import(AutoConfigurationImportSelector.class)
public interface EnableAutoConfiguration {}
1231、AutoConfigurationPackage
自动配置包指定了默认的包规则
Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public interface AutoConfigurationPackage {}//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来MainApplication 所在包下。
123452、Import(AutoConfigurationImportSelector.class)
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用ListString configurations getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 MapString, ListString loadSpringFactories(Nullable ClassLoader classLoader)得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories1234567文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301313.2、按需开启自动配置项
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则Conditional最终会按需配置。
123.3、修改默认配置 BeanConditionalOnBean(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 incorrectlyreturn resolver;}
给容器中加入了文件上传解析器
12345678910SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
BeanConditionalOnMissingBeanpublic CharacterEncodingFilter characterEncodingFilter() {}
1234总结 SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration 每个自动配置类按照条件进行生效默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定 生效的配置类就会给容器中装配很多组件 只要容器中有这些组件相当于这些功能就有了 定制化配置 用户直接自己Bean替换底层的组件 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration — 组件 — xxxxProperties里面拿值 ---- application.properties
3.4、最佳实践 引入场景依赖 https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter 查看自动配置了哪些选做 自己分析引入场景对应的自动配置一般都生效了 配置文件中debugtrue开启自动配置报告。Negative不生效\Positive生效 是否需要修改 参照文档修改配置项 https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties 自己分析。xxxxProperties绑定了配置文件的哪些。 自定义加入或者替换组件 Bean、Component。。。 自定义器 XXXXXCustomizer …
4、开发小技巧
4.1、Lombok
简化JavaBean开发 dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencyidea中搜索安装lombok插件
简化JavaBean开发
NoArgsConstructor
//AllArgsConstructor
Data
ToString
EqualsAndHashCode
public class User {private String name;private Integer age;private Pet pet;public User(String name,Integer age){this.name name;this.age age;}}简化日志开发
Slf4j
RestController
public class HelloController {RequestMapping(/hello)public String handle01(RequestParam(name) String name){log.info(请求进来了....);return Hello, Spring Boot 2!你好name;}
}
1234567891011121314151617181920212223242526272829303132333435363738394041424.2、dev-tools dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdoptionaltrue/optional/dependency
12345项目或者页面修改以后CtrlF9
4.3、Spring Initailizr项目初始化向导
0、选择我们需要的开发场景 1、自动依赖引入 2、自动创建项目结构 3、自动编写好主配置类 4 SpringBoot核心功能
配置文件
1、文件类型
1.1、properties
同以前的properties用法
1.2、yaml
1.2.1、简介
YAML 是 “YAML Ain’t Markup Language”YAML 不是一种标记语言的递归缩写。在开发的这种语言时YAML 的意思其实是“Yet Another Markup Language”仍是一种标记语言。
非常适合用来做以数据为中心的配置文件
1.2.2、基本语法 key: valuekv之间有空格 大小写敏感 使用缩进表示层级关系 缩进不允许使用tab只允许空格 缩进的空格数不重要只要相同层级的元素左对齐即可 #表示注释 字符串无需加引号如果要加与表示字符串内容 会被 转义/不转义
1.2.3、数据类型
字面量单个的、不可再分的值。date、boolean、string、number、null
k: v
1对象键值对的集合。map、hash、set、object
行内写法 k: {k1:v1,k2:v2,k3:v3}
#或
k: k1: v1k2: v2k3: v3
123456数组一组按次序排列的值。array、list、queue
行内写法 k: [v1,v2,v3]
#或者
k:- v1- v2- v3
1234561.2.4、示例
Data
public class Person {private String userName;private Boolean boss;private Date birth;private Integer age;private Pet pet;private String[] interests;private ListString animal;private MapString, Object score;private SetDouble salarys;private MapString, ListPet allPets;
}Data
public class Pet {private String name;private Double weight;
}
1234567891011121314151617181920# yaml表示以上对象
person:userName: zhangsanboss: falsebirth: 2019/12/12 20:12:33age: 18pet: name: tomcatweight: 23.4interests: [篮球,游泳]animal: - jerry- marioscore:english: first: 30second: 40third: 50math: [131,140,148]chinese: {first: 128,second: 136}salarys: [3999,4999.98,5999.99]allPets:sick:- {name: tom}- {name: jerry,weight: 47}health: [{name: mario,weight: 47}]
12345678910111213141516171819202122232425262、配置提示
自定义的类和配置文件绑定一般没有提示。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependencybuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationexcludesexcludegroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactId/exclude/excludes/configuration/plugin/plugins/build
12345678910111213141516171819202122235 Web开发 1、SpringMVC自动配置概览
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置)
The auto-configuration adds the following features on top of Spring’s defaults: Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans. 内容协商视图解析器和BeanName视图解析器 Support for serving static resources, including support for WebJars (covered later in this document)). 静态资源包括webjars Automatic registration of Converter, GenericConverter, and Formatter beans. 自动注册 ConverterGenericConverterFormatter Support for HttpMessageConverters (covered later in this document). 支持 HttpMessageConverters 后来我们配合内容协商理解原理 Automatic registration of MessageCodesResolver (covered later in this document). 自动注册 MessageCodesResolver 国际化用 Static index.html support. 静态index.html 页支持 Custom Favicon support (covered later in this document). 自定义 Favicon Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document). 自动使用 ConfigurableWebBindingInitializer DataBinder负责将请求数据绑定到JavaBean上
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own Configuration class of type WebMvcConfigurer but without EnableWebMvc.
不用EnableWebMvc注解。使用 **Configuration** **WebMvcConfigurer** 自定义规则
If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.
声明 **WebMvcRegistrations** 改变默认底层组件
If you want to take complete control of Spring MVC, you can add your own Configuration annotated with EnableWebMvc, or alternatively add your own Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of EnableWebMvc.
使用 **EnableWebMvcConfigurationDelegatingWebMvcConfiguration 全面接管SpringMVC**
2、简单功能分析
2.1、静态资源访问
1、静态资源目录
只要静态资源放在类路径下 called /static (or /public or /resources or /META-INF/resources
访问 当前项目根路径/ 静态资源名
原理 静态映射/**。
请求进来先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面
改变默认的静态资源路径
spring:mvc:static-path-pattern: /res/**resources:static-locations: [classpath:/haha/]
1234562、静态资源访问前缀
默认无前缀
spring:mvc:static-path-pattern: /res/**
123当前项目 static-path-pattern 静态资源名 静态资源文件夹下找
3、webjar
自动映射 /webjars/**
https://www.webjars.org/ dependencygroupIdorg.webjars/groupIdartifactIdjquery/artifactIdversion3.5.1/version/dependency
12345访问地址http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径
2.2、欢迎页支持 静态资源路径下 index.html 可以配置静态资源路径 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致welcome page功能失效resources:static-locations: [classpath:/haha/]
123456controller能处理/index
2.3、自定义 Favicon
favicon.ico 放在静态资源目录下即可。
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致 Favicon 功能失效
1232.4、静态资源配置原理
SpringBoot启动默认加载 xxxAutoConfiguration 类自动配置类SpringMVC功能的自动配置类 WebMvcAutoConfiguration生效
Configuration(proxyBeanMethods false)
ConditionalOnWebApplication(type Type.SERVLET)
ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE 10)
AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {}
12345678给容器中配了什么。 Configuration(proxyBeanMethods false)Import(EnableWebMvcConfiguration.class)EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })Order(0)public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
12345配置文件的相关属性和xxx进行了绑定。WebMvcPropertiesspring.mvc、ResourcePropertiesspring.resources
1、配置类只有一个有参构造器 //有参构造器所有参数的值都会从容器中确定
//ResourceProperties resourceProperties获取和spring.resources绑定的所有的值的对象
//WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象
//ListableBeanFactory beanFactory Spring的beanFactory
//HttpMessageConverters 找到所有的HttpMessageConverters
//ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。
//DispatcherServletPath
//ServletRegistrationBean 给应用注册Servlet、Filter....public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,ListableBeanFactory beanFactory, ObjectProviderHttpMessageConverters messageConvertersProvider,ObjectProviderResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizerProvider,ObjectProviderDispatcherServletPath dispatcherServletPath,ObjectProviderServletRegistrationBean? servletRegistrations) {this.resourceProperties resourceProperties;this.mvcProperties mvcProperties;this.beanFactory beanFactory;this.messageConvertersProvider messageConvertersProvider;this.resourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizerProvider.getIfAvailable();this.dispatcherServletPath dispatcherServletPath;this.servletRegistrations servletRegistrations;}
1234567891011121314151617181920212、资源处理的默认规则
Overridepublic 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));}}
spring:
# mvc:
# static-path-pattern: /res/**resources:add-mappings: false 禁用所有静态资源规则
ConfigurationProperties(prefix spring.resources, ignoreUnknownFields false)
public class ResourceProperties {private static final String[] CLASSPATH_RESOURCE_LOCATIONS { classpath:/META-INF/resources/,classpath:/resources/, classpath:/static/, classpath:/public/ };/*** Locations of static resources. Defaults to classpath:[/META-INF/resources/,* /resources/, /static/, /public/].*/private String[] staticLocations CLASSPATH_RESOURCE_LOCATIONS;
123456789101112131415161718192021222324252627282930313233343536373839403、欢迎页的处理规则 HandlerMapping处理器映射。保存了每一个Handler能处理哪些请求。 Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {WelcomePageHandlerMapping welcomePageHandlerMapping new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),this.mvcProperties.getStaticPathPattern());welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());return welcomePageHandlerMapping;}WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,ApplicationContext applicationContext, OptionalResource welcomePage, String staticPathPattern) {if (welcomePage.isPresent() /**.equals(staticPathPattern)) {//要用欢迎页功能必须是/**logger.info(Adding welcome page: welcomePage.get());setRootViewName(forward:index.html);}else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {// 调用Controller /indexlogger.info(Adding welcome page template: index);setRootViewName(index);}}
12345678910111213141516171819202122232425264、favicon
3、请求参数处理
0、请求映射
1、rest使用与原理 xxxMapping Rest风格支持使用HTTP请求方式动词来表示对资源的操作 以前**/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户 现在 /user *GET-*获取用户 *DELETE-*删除用户 *PUT-*修改用户 *POST-*保存用户 核心FilterHiddenHttpMethodFilter 用法 表单methodpost隐藏域 _methodput SpringBoot中手动开启 扩展如何把_method 这个名字换成我们自己喜欢的。 RequestMapping(value /user,method RequestMethod.GET)public String getUser(){return GET-张三;}RequestMapping(value /user,method RequestMethod.POST)public String saveUser(){return POST-张三;}RequestMapping(value /user,method RequestMethod.PUT)public String putUser(){return PUT-张三;}RequestMapping(value /user,method RequestMethod.DELETE)public String deleteUser(){return DELETE-张三;}BeanConditionalOnMissingBean(HiddenHttpMethodFilter.class)ConditionalOnProperty(prefix spring.mvc.hiddenmethod.filter, name enabled, matchIfMissing false)public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {return new OrderedHiddenHttpMethodFilter();}//自定义filterBeanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter(){HiddenHttpMethodFilter methodFilter new HiddenHttpMethodFilter();methodFilter.setMethodParam(_m);return methodFilter;}
12345678910111213141516171819202122232425262728293031323334353637Rest原理表单提交要使用REST的时候 表单提交会带上**_methodPUT** 请求过来被HiddenHttpMethodFilter拦截 请求是否正常并且是POST 获取到**_method**的值。 兼容以下请求PUT.DELETE.PATCH 原生requestpost包装模式requesWrapper重写了getMethod方法返回的是传入的值。 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用****requesWrapper的。
Rest使用客户端工具
如PostMan直接发送Put、delete等方式请求无需Filter。
spring:mvc:hiddenmethod:filter:enabled: true #开启页面表单的Rest功能
123452、请求映射原理 SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet-》doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest request;HandlerExecutionChain mappedHandler null;boolean multipartRequestParsed false;WebAsyncManager asyncManager WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv null;Exception dispatchException null;try {processedRequest checkMultipart(request);multipartRequestParsed (processedRequest ! request);// 找到当前请求使用哪个HandlerController的方法处理mappedHandler getHandler(processedRequest);//HandlerMapping处理器映射。/xxx-xxxx
12345678910111213141516171819RequestMappingHandlerMapping保存了所有RequestMapping 和handler的映射规则。 所有的请求映射都在HandlerMapping中。 SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html SpringBoot自动配置了默认 的 RequestMappingHandlerMapping 请求进来挨个尝试所有的HandlerMapping看是否有请求信息。 如果有就找到这个请求对应的handler 如果没有就是下一个 HandlerMapping 我们需要一些自定义的映射处理我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings ! null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler mapping.getHandler(request);if (handler ! null) {return handler;}}}return null;}
12345678910111、普通参数与基本注解
1.1、注解
PathVariable、RequestHeader、ModelAttribute、RequestParam、MatrixVariable、CookieValue、RequestBody
RestController
public class ParameterTestController {// car/2/owner/zhangsanGetMapping(/car/{id}/owner/{username})public MapString,Object getCar(PathVariable(id) Integer id,PathVariable(username) String name,PathVariable MapString,String pv,RequestHeader(User-Agent) String userAgent,RequestHeader MapString,String header,RequestParam(age) Integer age,RequestParam(inters) ListString inters,RequestParam MapString,String params,CookieValue(_ga) String _ga,CookieValue(_ga) Cookie cookie){MapString,Object map new HashMap();// map.put(id,id);
// map.put(name,name);
// map.put(pv,pv);
// map.put(userAgent,userAgent);
// map.put(headers,header);map.put(age,age);map.put(inters,inters);map.put(params,params);map.put(_ga,_ga);System.out.println(cookie.getName()cookie.getValue());return map;}PostMapping(/save)public Map postMethod(RequestBody String content){MapString,Object map new HashMap();map.put(content,content);return map;}//1、语法 请求路径/cars/sell;low34;brandbyd,audi,yd//2、SpringBoot默认是禁用了矩阵变量的功能// 手动开启原理。对于路径的处理。UrlPathHelper进行解析。// removeSemicolonContent移除分号内容支持矩阵变量的//3、矩阵变量必须有url路径变量才能被解析GetMapping(/cars/{path})public Map carsSell(MatrixVariable(low) Integer low,MatrixVariable(brand) ListString brand,PathVariable(path) String path){MapString,Object map new HashMap();map.put(low,low);map.put(brand,brand);map.put(path,path);return map;}// /boss/1;age20/2;age10GetMapping(/boss/{bossId}/{empId})public Map boss(MatrixVariable(value age,pathVar bossId) Integer bossAge,MatrixVariable(value age,pathVar empId) Integer empAge){MapString,Object map new HashMap();map.put(bossAge,bossAge);map.put(empAge,empAge);return map;}}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172731.2、Servlet API
WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId
ServletRequestMethodArgumentResolver 以上的部分参数
Overridepublic boolean supportsParameter(MethodParameter parameter) {Class? paramType parameter.getParameterType();return (WebRequest.class.isAssignableFrom(paramType) ||ServletRequest.class.isAssignableFrom(paramType) ||MultipartRequest.class.isAssignableFrom(paramType) ||HttpSession.class.isAssignableFrom(paramType) ||(pushBuilder ! null pushBuilder.isAssignableFrom(paramType)) ||Principal.class.isAssignableFrom(paramType) ||InputStream.class.isAssignableFrom(paramType) ||Reader.class.isAssignableFrom(paramType) ||HttpMethod.class paramType ||Locale.class paramType ||TimeZone.class paramType ||ZoneId.class paramType);}
123456789101112131415161.3、复杂参数
Map、**Modelmap、model里面的数据会被放在request的请求域 request.setAttribute、**Errors/BindingResult、RedirectAttributes 重定向携带数据、ServletResponseresponse、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder
MapString,Object map, Model model, HttpServletRequest request 都是可以给request域中放数据
request.getAttribute();
12Map、Model类型的参数会返回 mavContainer.getModel— BindingAwareModelMap 是Model 也是Map
mavContainer.getModel(); 获取到值的 1.4、自定义对象参数
可以自动类型转换与格式化可以级联封装。
/*** 姓名 input nameuserName/ br/* 年龄 input nameage/ br/* 生日 input namebirth/ br/* 宠物姓名input namepet.name/br/* 宠物年龄input namepet.age/*/
Data
public class Person {private String userName;private Integer age;private Date birth;private Pet pet;}Data
public class Pet {private String name;private String age;}result
12345678910111213141516171819202122232425262、POJO封装过程
ServletModelAttributeMethodProcessor
3、参数处理原理 HandlerMapping中找到能处理请求的HandlerController.method() 为当前Handler 找一个适配器 HandlerAdapter RequestMappingHandlerAdapter 适配器执行目标方法并确定方法参数的每一个值
1、HandlerAdapter 0 - 支持方法上标注RequestMapping
1 - 支持函数式编程的
xxxxxx
2、执行目标方法
// Actually invoke the handler.
//DispatcherServlet -- doDispatch
mv ha.handle(processedRequest, response, mappedHandler.getHandler());
mav invokeHandlerMethod(request, response, handlerMethod); //执行目标方法//ServletInvocableHandlerMethod
Object returnValue invokeForRequest(webRequest, mavContainer, providedArgs);
//获取方法的参数值
Object[] args getMethodArgumentValues(request, mavContainer, providedArgs);
123456789103、参数解析器-HandlerMethodArgumentResolver
确定将要执行的目标方法的每一个参数的值是什么;
SpringMVC目标方法能写多少种参数类型。取决于参数解析器。 当前解析器是否支持解析这种参数支持就调用 resolveArgument
4、返回值处理器 5、如何确定目标方法每一个参数的值
InvocableHandlerMethod
protected Object[] getMethodArgumentValues(NativeWebRequest request, Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {MethodParameter[] parameters getMethodParameters();if (ObjectUtils.isEmpty(parameters)) {return EMPTY_ARGS;}Object[] args new Object[parameters.length];for (int i 0; i parameters.length; i) {MethodParameter parameter parameters[i];parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);args[i] findProvidedArgument(parameter, providedArgs);if (args[i] ! null) {continue;}if (!this.resolvers.supportsParameter(parameter)) {throw new IllegalStateException(formatArgumentError(parameter, No suitable resolver));}try {args[i] this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);}catch (Exception ex) {// Leave stack trace for later, exception may actually be resolved and handled...if (logger.isDebugEnabled()) {String exMsg ex.getMessage();if (exMsg ! null !exMsg.contains(parameter.getExecutable().toGenericString())) {logger.debug(formatArgumentError(parameter, exMsg));}}throw ex;}}return args;}
1234567891011121314151617181920212223242526272829303132333435365.1、挨个判断所有参数解析器那个支持解析这个参数 Nullableprivate HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {HandlerMethodArgumentResolver result this.argumentResolverCache.get(parameter);if (result null) {for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {if (resolver.supportsParameter(parameter)) {result resolver;this.argumentResolverCache.put(parameter, result);break;}}}return result;}
12345678910111213145.2、解析这个参数的值
调用各自 HandlerMethodArgumentResolver 的 resolveArgument 方法即可
15.3、自定义类型参数 封装POJO
ServletModelAttributeMethodProcessor 这个参数处理器支持
是否为简单类型。
public static boolean isSimpleValueType(Class? type) {return (Void.class ! type void.class ! type (ClassUtils.isPrimitiveOrWrapper(type) ||Enum.class.isAssignableFrom(type) ||CharSequence.class.isAssignableFrom(type) ||Number.class.isAssignableFrom(type) ||Date.class.isAssignableFrom(type) ||Temporal.class.isAssignableFrom(type) ||URI.class type ||URL.class type ||Locale.class type ||Class.class type));}
OverrideNullablepublic final Object resolveArgument(MethodParameter parameter, Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, Nullable WebDataBinderFactory binderFactory) throws Exception {Assert.state(mavContainer ! null, ModelAttributeMethodProcessor requires ModelAndViewContainer);Assert.state(binderFactory ! null, ModelAttributeMethodProcessor requires WebDataBinderFactory);String name ModelFactory.getNameForParameter(parameter);ModelAttribute ann parameter.getParameterAnnotation(ModelAttribute.class);if (ann ! null) {mavContainer.setBinding(name, ann.binding());}Object attribute null;BindingResult bindingResult null;if (mavContainer.containsAttribute(name)) {attribute mavContainer.getModel().get(name);}else {// Create attribute instancetry {attribute createAttribute(name, parameter, binderFactory, webRequest);}catch (BindException ex) {if (isBindExceptionRequired(parameter)) {// No BindingResult parameter - fail with BindExceptionthrow ex;}// Otherwise, expose null/empty value and associated BindingResultif (parameter.getParameterType() Optional.class) {attribute Optional.empty();}bindingResult ex.getBindingResult();}}if (bindingResult null) {// Bean property binding and validation;// skipped in case of binding failure on construction.WebDataBinder binder binderFactory.createBinder(webRequest, attribute, name);if (binder.getTarget() ! null) {if (!mavContainer.isBindingDisabled(name)) {bindRequestParameters(binder, webRequest);}validateIfApplicable(binder, parameter);if (binder.getBindingResult().hasErrors() isBindExceptionRequired(binder, parameter)) {throw new BindException(binder.getBindingResult());}}// Value type adaptation, also covering java.util.Optionalif (!parameter.getParameterType().isInstance(attribute)) {attribute binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);}bindingResult binder.getBindingResult();}// Add resolved attribute and BindingResult at the end of the modelMapString, Object bindingResultModel bindingResult.getModel();mavContainer.removeAttributes(bindingResultModel);mavContainer.addAllAttributes(bindingResultModel);return attribute;}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778WebDataBinder binder binderFactory.createBinder(webRequest, attribute, name);
WebDataBinder :web数据绑定器将请求参数的值绑定到指定的JavaBean里面
WebDataBinder 利用它里面的 Converters 将请求数据转成指定的数据类型。再次封装到JavaBean中
GenericConversionService在设置每一个值的时候找它里面的所有converter那个可以将这个数据类型request带来参数的字符串转换到指定的类型JavaBean – Integer
byte – file
FunctionalInterfacepublic interface ConverterS, T 未来我们可以给WebDataBinder里面放自己的Converter
private static final class StringToNumberT extends Number implements ConverterString, T
自定义 Converter //1、WebMvcConfigurer定制化SpringMVC的功能Beanpublic WebMvcConfigurer webMvcConfigurer(){return new WebMvcConfigurer() {Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper new UrlPathHelper();// 不移除后面的内容。矩阵变量功能就可以生效urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(new ConverterString, Pet() {Overridepublic Pet convert(String source) {// 啊猫,3if(!StringUtils.isEmpty(source)){Pet pet new Pet();String[] split source.split(,);pet.setName(split[0]);pet.setAge(Integer.parseInt(split[1]));return pet;}return null;}});}};}
12345678910111213141516171819202122232425262728293031326、目标方法执行完成
将所有的数据都放在 ModelAndViewContainer包含要去的页面地址View。还包含Model数据。 7、处理派发结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
InternalResourceView
Overrideprotected void renderMergedOutputModel(MapString, Object model, HttpServletRequest request, HttpServletResponse response) throws Exception {// Expose the model object as request attributes.exposeModelAsRequestAttributes(model, request);// Expose helpers as request attributes, if any.exposeHelpers(request);// Determine the path for the request dispatcher.String dispatcherPath prepareForRendering(request, response);// Obtain a RequestDispatcher for the target resource (typically a JSP).RequestDispatcher rd getRequestDispatcher(request, dispatcherPath);if (rd null) {throw new ServletException(Could not get RequestDispatcher for [ getUrl() ]: Check that the corresponding file exists within your web application archive!);}// If already included or response already committed, perform include, else forward.if (useInclude(request, response)) {response.setContentType(getContentType());if (logger.isDebugEnabled()) {logger.debug(Including [ getUrl() ]);}rd.include(request, response);}else {// Note: The forwarded resource is supposed to determine the content type itself.if (logger.isDebugEnabled()) {logger.debug(Forwarding to [ getUrl() ]);}rd.forward(request, response);}}
1234567891011121314151617181920212223242526272829303132333435363738暴露模型作为请求域属性
// Expose the model object as request attributes.exposeModelAsRequestAttributes(model, request);
123protected void exposeModelAsRequestAttributes(MapString, Object model,HttpServletRequest request) throws Exception {//model中的所有数据遍历挨个放在请求域中model.forEach((name, value) - {if (value ! null) {request.setAttribute(name, value);}else {request.removeAttribute(name);}});}
123456789101112134、数据响应与内容协商 1、响应JSON
1.1、jackson.jarResponseBody dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency
web场景自动引入了json场景dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-json/artifactIdversion2.3.4.RELEASE/versionscopecompile/scope/dependency
1234567891011给前端自动返回json数据
1、返回值解析器 try {this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);}Overridepublic void handleReturnValue(Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {HandlerMethodReturnValueHandler handler selectHandler(returnValue, returnType);if (handler null) {throw new IllegalArgumentException(Unknown return value type: returnType.getParameterType().getName());}handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);}
RequestResponseBodyMethodProcessor
Overridepublic void handleReturnValue(Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest)throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {mavContainer.setRequestHandled(true);ServletServerHttpRequest inputMessage createInputMessage(webRequest);ServletServerHttpResponse outputMessage createOutputMessage(webRequest);// Try even with null return value. ResponseBodyAdvice could get involved.// 使用消息转换器进行写出操作writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);}
123456789101112131415161718192021222324252627282、返回值解析器原理 1、返回值处理器判断是否支持这种类型返回值 supportsReturnType 2、返回值处理器调用 handleReturnValue 进行处理 3、RequestResponseBodyMethodProcessor 可以处理返回值标了ResponseBody 注解的。 \1. 利用 MessageConverters 进行处理 将数据写为json 1、内容协商浏览器默认会以请求头的方式告诉服务器他能接受什么样的内容类型 2、服务器最终根据自己自身的能力决定服务器能生产出什么样内容类型的数据 3、SpringMVC会挨个遍历所有容器底层的 HttpMessageConverter 看谁能处理 1、得到MappingJackson2HttpMessageConverter可以将对象写为json - 2、利用MappingJackson2HttpMessageConverter将对象转为json再写出去。 1.2、SpringMVC到底支持哪些返回值
ModelAndView
Model
View
ResponseEntity
ResponseBodyEmitter
StreamingResponseBody
HttpEntity
HttpHeaders
Callable
DeferredResult
ListenableFuture
CompletionStage
WebAsyncTask
有 ModelAttribute 且为对象类型的
ResponseBody 注解 --- RequestResponseBodyMethodProcessor
1234567891011121314151.3、HTTPMessageConverter原理
1、MessageConverter规范 HttpMessageConverter: 看是否支持将 此 Class类型的对象转为MediaType类型的数据。
例子Person对象转为JSON。或者 JSON转为Person
2、默认的MessageConverter 0 - 只支持Byte类型的
1 - String
2 - String
3 - Resource
4 - ResourceRegion
5 - DOMSource.*class * SAXSource.class) \ StAXSource.**class **StreamSource.**class **Source.class
6 - MultiValueMap
7 - true
8 - true
9 - 支持注解方式xml处理的。
最终 MappingJackson2HttpMessageConverter 把对象转为JSON利用底层的jackson的objectMapper转换的 2、内容协商
根据客户端接收能力不同返回不同媒体类型的数据。
1、引入xml依赖 dependencygroupIdcom.fasterxml.jackson.dataformat/groupIdartifactIdjackson-dataformat-xml/artifactId
/dependency
12342、postman分别测试返回json和xml
只需要改变请求头中Accept字段。Http协议中规定的告诉服务器本客户端可以接收的数据类型。 3、开启浏览器参数方式内容协商功能
为了方便内容协商开启基于请求参数的内容协商功能。
spring:contentnegotiation:favor-parameter: true #开启请求参数内容协商模式
123发请求 http://localhost:8080/test/person?formatjson
http://localhost:8080/test/person?formatxml 确定客户端接收什么样的内容类型
1、Parameter策略优先确定是要返回json数据获取请求头中的format的值 2、最终进行内容协商返回给客户端json即可。
4、内容协商原理 1、判断当前响应头中是否已经有确定的媒体类型。MediaType 2、获取客户端PostMan、浏览器支持接收的内容类型。获取客户端Accept请求头字段【application/xml】 contentNegotiationManager 内容协商管理器 默认使用基于请求头的策略 HeaderContentNegotiationStrategy 确定客户端可以接收的内容类型 3、遍历循环所有当前系统的 MessageConverter看谁支持操作这个对象Person 4、找到支持操作Person的converter把converter支持的媒体类型统计出来。 5、客户端需要【application/xml】。服务端能力【10种、json、xml】 6、进行内容协商的最佳匹配媒体类型 7、用 支持 将对象转为 最佳匹配媒体类型 的converter。调用它进行转化 。 导入了jackson处理xml的包xml的converter就会自动进来
WebMvcConfigurationSupport
jackson2XmlPresent ClassUtils.isPresent(com.fasterxml.jackson.dataformat.xml.XmlMapper, classLoader);if (jackson2XmlPresent) {Jackson2ObjectMapperBuilder builder Jackson2ObjectMapperBuilder.xml();if (this.applicationContext ! null) {builder.applicationContext(this.applicationContext);}messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));}
123456789105、自定义 MessageConverter
实现多协议数据兼容。json、xml、x-guigu
0、ResponseBody 响应数据出去 调用 RequestResponseBodyMethodProcessor 处理
1、Processor 处理方法返回值。通过 MessageConverter 处理
2、所有 MessageConverter 合起来可以支持各种媒体类型数据的操作读、写
3、内容协商找到最终的 messageConverter
SpringMVC的什么功能。一个入口给容器中添加一个 WebMvcConfigurer Beanpublic WebMvcConfigurer webMvcConfigurer(){return new WebMvcConfigurer() {Overridepublic void extendMessageConverters(ListHttpMessageConverter? converters) {}}}
12345678910有可能我们添加的自定义的功能会覆盖默认很多功能导致一些默认的功能失效。
大家考虑上述功能除了我们完全自定义外SpringBoot有没有为我们提供基于配置文件的快速修改媒体类型功能怎么配置呢【提示参照SpringBoot官方文档web开发内容协商章节】
5、视图解析与模板引擎
视图解析SpringBoot默认不支持 JSP需要引入第三方模板引擎技术实现页面渲染。
1、视图解析 1、视图解析原理流程
1、目标方法处理的过程中所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址
2、方法的参数是一个自定义类型对象从请求参数中确定的把他重新放在 ModelAndViewContainer
3、任何目标方法执行完成以后都会返回 ModelAndView数据和视图地址。
**4、**processDispatchResult 处理派发结果页面改如何响应 1、render(mv, request, response); 进行页面渲染逻辑 1、根据方法的String返回值得到 View 对象【定义了页面的渲染逻辑】 1、所有的视图解析器尝试是否能根据当前返回值得到View对象 2、得到了 redirect:/main.html -- Thymeleaf new RedirectView() 3、ContentNegotiationViewResolver 里面包含了下面所有的视图解析器内部还是利用下面所有视图解析器得到视图对象。 4、view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作 RedirectView 如何渲染【重定向到一个页面】 - 1、获取目标url地址 **2、**response.sendRedirect(encodedURL);
视图解析 返回值以 forward: 开始 new InternalResourceView(forwardUrl); -- 转发****request.getRequestDispatcher(path).forward(request, response); 返回值以 redirect: 开始 new RedirectView() --》 render就是重定向 返回值是普通字符串 new ThymeleafView—
自定义视图解析器自定义视图 大厂学院。 2、模板引擎-Thymeleaf
1、thymeleaf简介
Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text.
现代化、服务端Java模板引擎
2、基本语法
1、表达式
表达式名字语法用途变量取值${…}获取请求域、session域、对象等值选择变量*{…}获取上下文对象值消息#{…}获取国际化等值链接{…}生成链接片段表达式~{…}jsp:include 作用引入公共页面片段
2、字面量
文本值: ‘one text’ , ‘Another one!’ **,…**数字: 0 , 34 , 3.0 , 12.3 **,…**布尔值: true , false
空值: null
变量 onetwo… 变量不能有空格
3、文本操作
字符串拼接:
变量替换: |The name is ${name}|
4、数学运算
运算符: , - , * , / , %
5、布尔运算
运算符: and , or
一元运算: ! , not
6、比较运算
比较: , , , ( gt , lt , ge , le **)**等式: , ! ( eq , ne )
7、条件运算
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
8、特殊操作
无操作 _
3、设置属性值-th:attr
设置单个值
form actionsubscribe.html th:attraction{/subscribe}fieldsetinput typetext nameemail /input typesubmit valueSubscribe! th:attrvalue#{subscribe.submit}//fieldset
/form
123456设置多个值
img src../../images/gtvglogo.png th:attrsrc{/images/gtvglogo.png},title#{logo},alt#{logo} /
1以上两个的代替写法 th:xxxx
input typesubmit valueSubscribe! th:value#{subscribe.submit}/
form actionsubscribe.html th:action{/subscribe}
12所有h5兼容的标签写法
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes
4、迭代
tr th:eachprod : ${prods}td th:text${prod.name}Onions/tdtd th:text${prod.price}2.41/tdtd th:text${prod.inStock}? #{true} : #{false}yes/td
/tr
12345tr th:eachprod,iterStat : ${prods} th:class${iterStat.odd}? oddtd th:text${prod.name}Onions/tdtd th:text${prod.price}2.41/tdtd th:text${prod.inStock}? #{true} : #{false}yes/td
/tr
123455、条件运算
a hrefcomments.html
th:href{/product/comments(prodId${prod.id})}
th:if${not #lists.isEmpty(prod.comments)}view/a
123div th:switch${user.role}p th:caseadminUser is an administrator/pp th:case#{roles.manager}User is a manager/pp th:case*User is some other thing/p
/div
123456、属性优先级 3、thymeleaf使用
1、引入Starter dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId/dependency
12342、自动配置好了thymeleaf
Configuration(proxyBeanMethods false)
EnableConfigurationProperties(ThymeleafProperties.class)
ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration { }
12345自动配好的策略 1、所有thymeleaf的配置值都在 ThymeleafProperties 2、配置好了 SpringTemplateEngine 3、配好了 ThymeleafViewResolver 4、我们只需要直接开发页面 public static final String DEFAULT_PREFIX classpath:/templates/;public static final String DEFAULT_SUFFIX .html; //xxx.html
1233、页面开发
!DOCTYPE html
html langen xmlns:thhttp://www.thymeleaf.org
headmeta charsetUTF-8titleTitle/title
/head
body
h1 th:text${msg}哈哈/h1
h2a hrefwww.atguigu.com th:href${link}去百度/a br/a hrefwww.atguigu.com th:href{link}去百度2/a
/h2
/body
/html
12345678910111213144、构建后台管理系统
1、项目创建
thymeleaf、web-starter、devtools、lombok
2、静态资源处理
自动配置好我们只需要把所有静态资源放到 static 文件夹下
3、路径构建
th:action“{/login}”
4、模板抽取
th:insert/replace/include
5、页面跳转 PostMapping(/login)public String main(User user, HttpSession session, Model model){if(StringUtils.hasLength(user.getUserName()) 123456.equals(user.getPassword())){//把登陆成功的用户保存起来session.setAttribute(loginUser,user);//登录成功重定向到main.html; 重定向防止表单重复提交return redirect:/main.html;}else {model.addAttribute(msg,账号密码错误);//回到登录页面return login;}}
1234567891011121314156、数据渲染 GetMapping(/dynamic_table)public String dynamic_table(Model model){//表格内容的遍历ListUser users Arrays.asList(new User(zhangsan, 123456),new User(lisi, 123444),new User(haha, aaaaa),new User(hehe , aaddd));model.addAttribute(users,users);return table/dynamic_table;}table classdisplay table table-bordered idhidden-table-infotheadtrth#/thth用户名/thth密码/th/tr/theadtbodytr classgradeX th:eachuser,stats:${users}td th:text${stats.count}Trident/tdtd th:text${user.userName}Internet/tdtd [[${user.password}]]/td/tr/tbody/table
1234567891011121314151617181920212223242526276、拦截器
1、HandlerInterceptor 接口
/*** 登录检查* 1、配置好拦截器要拦截哪些请求* 2、把这些配置放在容器中*/
Slf4j
public class LoginInterceptor implements HandlerInterceptor {/*** 目标方法执行之前* param request* param response* param handler* return* throws Exception*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String requestURI request.getRequestURI();log.info(preHandle拦截的请求路径是{},requestURI);//登录检查逻辑HttpSession session request.getSession();Object loginUser session.getAttribute(loginUser);if(loginUser ! null){//放行return true;}//拦截住。未登录。跳转到登录页request.setAttribute(msg,请先登录);
// re.sendRedirect(/);request.getRequestDispatcher(/).forward(request,response);return false;}/*** 目标方法执行完成以后* param request* param response* param handler* param modelAndView* throws Exception*/Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info(postHandle执行{},modelAndView);}/*** 页面渲染以后* param request* param response* param handler* param ex* throws Exception*/Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info(afterCompletion执行异常{},ex);}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364652、配置拦截器
/*** 1、编写一个拦截器实现HandlerInterceptor接口* 2、拦截器注册到容器中实现WebMvcConfigurer的addInterceptors* 3、指定拦截规则【如果是拦截所有静态资源也会被拦截】*/
Configuration
public class AdminWebConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns(/**) //所有请求都被拦截包括静态资源.excludePathPatterns(/,/login,/css/**,/fonts/**,/images/**,/js/**); //放行的请求}
}
1234567891011121314153、拦截器原理
1、根据当前请求找到**HandlerExecutionChain【**可以处理请求的handler以及handler的所有 拦截器】
2、先来顺序执行 所有拦截器的 preHandle方法
1、如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle2、如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion
3、如果任何一个拦截器返回false。直接跳出不执行目标方法
4、所有拦截器都返回True。执行目标方法
5、倒序执行所有拦截器的postHandle方法。
6、前面的步骤有任何异常都会直接倒序触发 afterCompletion
7、页面成功渲染完成以后也会倒序触发 afterCompletion 7、文件上传
1、页面表单
form methodpost action/upload enctypemultipart/form-datainput typefile namefilebrinput typesubmit value提交
/form
12342、文件上传代码 /*** MultipartFile 自动封装上传过来的文件* param email* param username* param headerImg* param photos* return*/PostMapping(/upload)public String upload(RequestParam(email) String email,RequestParam(username) String username,RequestPart(headerImg) MultipartFile headerImg,RequestPart(photos) MultipartFile[] photos) throws IOException {log.info(上传的信息email{}username{}headerImg{}photos{},email,username,headerImg.getSize(),photos.length);if(!headerImg.isEmpty()){//保存到文件服务器OSS服务器String originalFilename headerImg.getOriginalFilename();headerImg.transferTo(new File(H:\\cache\\originalFilename));}if(photos.length 0){for (MultipartFile photo : photos) {if(!photo.isEmpty()){String originalFilename photo.getOriginalFilename();photo.transferTo(new File(H:\\cache\\originalFilename));}}}return main;}
12345678910111213141516171819202122232425262728293031323334353、自动配置原理
**文件上传自动配置类-MultipartAutoConfiguration-**MultipartProperties 自动配置好了 StandardServletMultipartResolver 【文件上传解析器】 原理步骤 1、请求进来使用文件上传解析器判断isMultipart并封装resolveMultipart返回MultipartHttpServletRequest文件上传请求 2、参数解析器来解析请求中的文件内容封装成MultipartFile **3、将request中文件信息封装为一个Map**MultiValueMapString, MultipartFile
FileCopyUtils。实现文件流的拷贝 PostMapping(/upload)public String upload(RequestParam(email) String email,RequestParam(username) String username,RequestPart(headerImg) MultipartFile headerImg,RequestPart(photos) MultipartFile[] photos)
123458、异常处理
1、错误处理
1、默认规则 默认情况下Spring Boot提供/error处理所有错误的映射 对于机器客户端它将生成JSON响应其中包含错误HTTP状态和异常消息的详细信息。对于浏览器客户端响应一个“ whitelabel”错误视图以HTML格式呈现相同的数据 要对其进行自定义添加**View**解析为**error**** ** 要完全替换默认行为可以实现 ErrorController 并注册该类型的Bean定义或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。 error/下的4xx5xx页面会被自动解析
2、定制错误处理逻辑 自定义错误页 error/404.html error/5xx.html有精确的错误状态码页面就匹配精确没有就找 4xx.html如果都没有就触发白页 ControllerAdviceExceptionHandler处理全局异常底层是 ExceptionHandlerExceptionResolver 支持的 ResponseStatus自定义异常 底层是 ResponseStatusExceptionResolver 把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason)tomcat发送的/error Spring底层的异常如 参数类型转换异常DefaultHandlerExceptionResolver 处理框架底层的异常。 response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage()); 自定义实现 HandlerExceptionResolver 处理异常可以作为默认的全局异常处理规则 ErrorViewResolver 实现自定义处理异常 response.sendError 。error请求就会转给controller 你的异常没有任何人能处理。tomcat底层 response.sendError。error请求就会转给controller basicErrorController 要去的页面地址是 ErrorViewResolver
3、异常处理自动配置原理 ErrorMvcAutoConfiguration 自动配置异常处理规则 容器中的组件类型DefaultErrorAttributes - iderrorAttributes public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver DefaultErrorAttributes定义错误页面中可以包含哪些数据。 **容器中的组件类型**BasicErrorController -- idbasicErrorControllerjson白页 适配响应 处理默认 /error 路径的请求页面响应 new ModelAndView(“error”, model) 容器中有组件 View-id是error响应默认错误页 容器中放组件 BeanNameViewResolver视图解析器按照返回的视图名作为组件的id去容器中找View对象。 **容器中的组件**类型**DefaultErrorViewResolver - id**conventionErrorViewResolver 如果发生错误会以HTTP的状态码 作为视图页地址viewName找到真正的页面 error/404、5xx.html
如果想要返回页面就会找error视图【StaticView】。(默认是一个白页)
写出去json 错误页
4、异常处理步骤流程
1、执行目标方法目标方法运行期间有任何异常都会被catch、而且标志当前请求结束并且用 dispatchException
2、进入视图解析流程页面渲染
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
3、mv processHandlerException处理handler发生的异常处理完成返回ModelAndView 1、遍历所有的 handlerExceptionResolvers看谁能处理当前异常【HandlerExceptionResolver处理器异常解析器】 2、系统默认的 异常解析器 1、DefaultErrorAttributes先来处理异常。把异常信息保存到rrequest域并且返回null 2、默认没有任何人能处理异常所以异常会被抛出 1、如果没有任何人能处理最终底层就会发送 /error 请求。会被底层的BasicErrorController处理 2、解析错误视图遍历所有的 ErrorViewResolver 看谁能解析。 3、默认的 DefaultErrorViewResolver ,作用是把响应状态码作为错误页的地址error/500.html 4、模板引擎最终响应这个页面 error/500.html
9、Web原生组件注入Servlet、Filter、Listener
1、使用Servlet API
ServletComponentScan(basePackages “com.atguigu.admin”) :指定原生Servlet组件都放在那里
WebServlet(urlPatterns “/my”)效果直接响应没有经过Spring的拦截器
WebFilter(urlPatterns{“/css/*”,“/images/*”})
WebListener
推荐可以这种方式
扩展DispatchServlet 如何注册进来 容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties对应的配置文件配置项是 spring.mvc。 通过 ServletRegistrationBean 把 DispatcherServlet 配置进来。 默认映射的是 / 路径。 Tomcat-Servlet
多个Servlet都能处理到同一层路径精确优选原则
A /my/
B /my/1
2、使用RegistrationBean
ServletRegistrationBean, FilterRegistrationBean, and ServletListenerRegistrationBean
Configuration
public class MyRegistConfig {Beanpublic ServletRegistrationBean myServlet(){MyServlet myServlet new MyServlet();return new ServletRegistrationBean(myServlet,/my,/my02);}Beanpublic FilterRegistrationBean myFilter(){MyFilter myFilter new MyFilter();
// return new FilterRegistrationBean(myFilter,myServlet());FilterRegistrationBean filterRegistrationBean new FilterRegistrationBean(myFilter);filterRegistrationBean.setUrlPatterns(Arrays.asList(/my,/css/*));return filterRegistrationBean;}Beanpublic ServletListenerRegistrationBean myListener(){MySwervletContextListener mySwervletContextListener new MySwervletContextListener();return new ServletListenerRegistrationBean(mySwervletContextListener);}
}
1234567891011121314151617181920212223242526272810、嵌入式Servlet容器
1、切换嵌入式Servlet容器 默认支持的webServer Tomcat, Jetty, or Undertow ServletWebServerApplicationContext 容器启动寻找ServletWebServerFactory 并引导创建服务器 切换服务器 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactIdexclusionsexclusiongroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-tomcat/artifactId/exclusion/exclusions
/dependency
12345678910原理 SpringBoot应用启动发现当前是Web应用。web场景包-导入tomcat web应用会创建一个web版的ioc容器 ServletWebServerApplicationContext ServletWebServerApplicationContext 启动的时候寻找 **ServletWebServerFactory**Servlet 的web服务器工厂--- Servlet 的web服务器 SpringBoot底层默认有很多的WebServer工厂TomcatServletWebServerFactory, JettyServletWebServerFactory, or UndertowServletWebServerFactory 底层直接会有一个自动配置类。ServletWebServerFactoryAutoConfiguration ServletWebServerFactoryAutoConfiguration导入了ServletWebServerFactoryConfiguration配置类 ServletWebServerFactoryConfiguration 配置类 根据动态判断系统中到底导入了那个Web服务器的包。默认是web-starter导入tomcat包容器中就有 TomcatServletWebServerFactory TomcatServletWebServerFactory 创建出Tomcat服务器并启动TomcatWebServer 的构造器拥有初始化方法initialize---this.tomcat.start(); 内嵌服务器就是手动把启动服务器的代码调用tomcat核心jar包存在
2、定制Servlet容器 实现 WebServerFactoryCustomizer 把配置文件的值和**ServletWebServerFactory 进行绑定** 修改配置文件 server.xxx 直接自定义 ConfigurableServletWebServerFactory
xxxxxCustomizer定制化器可以改变xxxx的默认规则
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;Component
public class CustomizationBean implements WebServerFactoryCustomizerConfigurableServletWebServerFactory {Overridepublic void customize(ConfigurableServletWebServerFactory server) {server.setPort(9000);}}
1234567891011121311、定制化原理
1、定制化的常见方式 修改配置文件 xxxxxCustomizer 编写自定义的配置类 xxxConfiguration Bean替换、增加容器中默认组件视图解析器 Web应用 编写一个配置类实现 WebMvcConfigurer 即可定制化web功能 Bean给容器中再扩展一些组件
Configuration
public class AdminWebConfig implements WebMvcConfigurer
12EnableWebMvc WebMvcConfigurer —— Bean 可以全面接管SpringMVC所有规则全部自己重新配置 实现定制和扩展功能 原理 1、WebMvcAutoConfiguration 默认的SpringMVC的自动配置功能类。静态资源、欢迎页… 2、一旦使用 EnableWebMvc 、。会 Import(DelegatingWebMvcConfiguration.class) 3、DelegatingWebMvcConfiguration 的 作用只保证SpringMVC最基本的使用 把所有系统中的 WebMvcConfigurer 拿过来。所有功能的定制都是这些 WebMvcConfigurer 合起来一起生效 自动配置了一些非常底层的组件。RequestMappingHandlerMapping、这些组件依赖的组件都是从容器中获取 public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport 4、WebMvcAutoConfiguration 里面的配置要能生效 必须 ConditionalOnMissingBean(WebMvcConfigurationSupport.class) 5、EnableWebMvc 导致了 WebMvcAutoConfiguration 没有生效。 … …
2、原理分析套路
场景starter - xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties – 绑定配置文件项
6 数据访问
1、SQL
1、数据源的自动配置-HikariDataSource
1、导入JDBC场景 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-jdbc/artifactId/dependency12345数据库驱动
为什么导入JDBC场景官方不导入驱动官方不知道我们接下要操作什么数据库。
数据库版本和驱动版本对应
默认版本mysql.version8.0.22/mysql.versiondependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId
!-- version5.1.49/version--/dependency
想要修改版本
1、直接依赖引入具体版本maven的就近依赖原则
2、重新声明版本maven的属性的就近优先原则propertiesjava.version1.8/java.versionmysql.version5.1.49/mysql.version/properties
12345678910111213142、分析自动配置
1、自动配置的类 DataSourceAutoConfiguration 数据源的自动配置 修改数据源相关的配置spring.datasource 数据库连接池的配置是自己容器中没有DataSource才自动配置的 底层配置好的连接池是HikariDataSource Configuration(proxyBeanMethods false)Conditional(PooledDataSourceCondition.class)ConditionalOnMissingBean({ DataSource.class, XADataSource.class })Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })protected static class PooledDataSourceConfiguration
1234567DataSourceTransactionManagerAutoConfiguration 事务管理器的自动配置 JdbcTemplateAutoConfiguration JdbcTemplate的自动配置可以来对数据库进行crud 可以修改这个配置项ConfigurationProperties(prefix “spring.jdbc”) 来修改JdbcTemplate BeanPrimary JdbcTemplate容器中有这个组件 JndiDataSourceAutoConfiguration jndi的自动配置 XADataSourceAutoConfiguration 分布式事务相关的
3、修改配置项
spring:datasource:url: jdbc:mysql://localhost:3306/db_accountusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driver
1234564、测试
Slf4j
SpringBootTest
class Boot05WebAdminApplicationTests {AutowiredJdbcTemplate jdbcTemplate;Testvoid contextLoads() {// jdbcTemplate.queryForObject(select * from account_tbl)
// jdbcTemplate.queryForList(select * from account_tbl,)Long aLong jdbcTemplate.queryForObject(select count(*) from account_tbl, Long.class);log.info(记录总数{},aLong);}}
1234567891011121314151617182、使用Druid数据源
1、druid官方github地址
https://github.com/alibaba/druid
整合第三方技术的两种方式
自定义找starter
2、自定义方式
1、创建数据源 dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.17/version/dependencybean iddataSource classcom.alibaba.druid.pool.DruidDataSourcedestroy-methodcloseproperty nameurl value${jdbc.url} /property nameusername value${jdbc.username} /property namepassword value${jdbc.password} /property namemaxActive value20 /property nameinitialSize value1 /property namemaxWait value60000 /property nameminIdle value1 /property nametimeBetweenEvictionRunsMillis value60000 /property nameminEvictableIdleTimeMillis value300000 /property nametestWhileIdle valuetrue /property nametestOnBorrow valuefalse /property nametestOnReturn valuefalse /property namepoolPreparedStatements valuetrue /property namemaxOpenPreparedStatements value20 /
123456789101112131415161718192021222、StatViewServlet
StatViewServlet的用途包括
提供监控信息展示的html页面提供监控信息的JSON API servletservlet-nameDruidStatView/servlet-nameservlet-classcom.alibaba.druid.support.http.StatViewServlet/servlet-class/servletservlet-mappingservlet-nameDruidStatView/servlet-nameurl-pattern/druid/*/url-pattern/servlet-mapping
123456783、StatFilter
用于统计监控信息如SQL监控、URI监控
需要给数据源中配置如下属性可以允许多个filter多个用分割如property namefilters valuestat,slf4j /
123系统中所有filter
别名Filter类名defaultcom.alibaba.druid.filter.stat.StatFilterstatcom.alibaba.druid.filter.stat.StatFiltermergeStatcom.alibaba.druid.filter.stat.MergeStatFilterencodingcom.alibaba.druid.filter.encoding.EncodingConvertFilterlog4jcom.alibaba.druid.filter.logging.Log4jFilterlog4j2com.alibaba.druid.filter.logging.Log4j2Filterslf4jcom.alibaba.druid.filter.logging.Slf4jLogFiltercommonloggingcom.alibaba.druid.filter.logging.CommonsLogFilter
慢SQL记录配置
bean idstat-filter classcom.alibaba.druid.filter.stat.StatFilterproperty nameslowSqlMillis value10000 /property namelogSlowSql valuetrue /
/bean使用 slowSqlMillis 定义慢SQL的时长
1234563、使用官方starter方式
1、引入druid-starter dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.1.17/version/dependency
123452、分析自动配置 扩展配置项 spring.datasource.druid DruidSpringAopConfiguration.class, 监控SpringBean的配置项spring.datasource.druid.aop-patterns DruidStatViewServletConfiguration.class, 监控页的配置spring.datasource.druid.stat-view-servlet默认开启 DruidWebStatFilterConfiguration.class, web监控配置spring.datasource.druid.web-stat-filter默认开启 DruidFilterConfiguration.class}) 所有Druid自己filter的配置 private static final String FILTER_STAT_PREFIX spring.datasource.druid.filter.stat;private static final String FILTER_CONFIG_PREFIX spring.datasource.druid.filter.config;private static final String FILTER_ENCODING_PREFIX spring.datasource.druid.filter.encoding;private static final String FILTER_SLF4J_PREFIX spring.datasource.druid.filter.slf4j;private static final String FILTER_LOG4J_PREFIX spring.datasource.druid.filter.log4j;private static final String FILTER_LOG4J2_PREFIX spring.datasource.druid.filter.log4j2;private static final String FILTER_COMMONS_LOG_PREFIX spring.datasource.druid.filter.commons-log;private static final String FILTER_WALL_PREFIX spring.datasource.druid.filter.wall;
123456783、配置示例
spring:datasource:url: jdbc:mysql://localhost:3306/db_accountusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverdruid:aop-patterns: com.atguigu.admin.* #监控SpringBeanfilters: stat,wall # 底层开启功能statsql监控wall防火墙stat-view-servlet: # 配置监控页功能enabled: truelogin-username: adminlogin-password: adminresetEnable: falseweb-stat-filter: # 监控webenabled: trueurlPattern: /*exclusions: *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*filter:stat: # 对上面filters里面的stat的详细配置slow-sql-millis: 1000logSlowSql: trueenabled: truewall:enabled: trueconfig:drop-table-allow: false
1234567891011121314151617181920212223242526272829303132SpringBoot配置示例
https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
配置项列表https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8
3、整合MyBatis操作
https://github.com/mybatis
starter
SpringBoot官方的Starterspring-boot-starter-*
第三方的 *-spring-boot-starter dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.1.4/version/dependency
123451、配置模式 全局配置文件 SqlSessionFactory: 自动配置好了 SqlSession自动配置了 SqlSessionTemplate 组合了SqlSession Import(AutoConfiguredMapperScannerRegistrar.class Mapper 只要我们写的操作MyBatis的接口标准了 Mapper 就会被自动扫描进来
EnableConfigurationProperties(MybatisProperties.class) MyBatis配置项绑定类。
AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration{}ConfigurationProperties(prefix mybatis)
public class MybatisProperties
123456可以修改配置文件中 mybatis 开始的所有
# 配置mybatis规则
mybatis:config-location: classpath:mybatis/mybatis-config.xml #全局配置文件位置mapper-locations: classpath:mybatis/mapper/*.xml #sql映射文件位置Mapper接口---绑定Xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.atguigu.admin.mapper.AccountMapper
!-- public Account getAcct(Long id); --select idgetAcct resultTypecom.atguigu.admin.bean.Accountselect * from account_tbl where id#{id}/select
/mapper
12345678910111213141516配置 private Configuration configuration; mybatis.configuration下面的所有就是相当于改mybatis全局配置文件中的值
# 配置mybatis规则
mybatis:
# config-location: classpath:mybatis/mybatis-config.xmlmapper-locations: classpath:mybatis/mapper/*.xmlconfiguration:map-underscore-to-camel-case: true可以不写全局配置文件所有全局配置文件的配置都放在configuration配置项中即可
12345678导入mybatis官方starter 编写mapper接口。标准Mapper注解 编写sql映射文件并绑定mapper接口 在application.yaml中指定Mapper配置文件的位置以及指定全局配置文件的信息 建议配置在mybatis.configuration
2、注解模式
Mapper
public interface CityMapper {Select(select * from city where id#{id})public City getById(Long id);public void insert(City city);}
1234567893、混合模式
Mapper
public interface CityMapper {Select(select * from city where id#{id})public City getById(Long id);public void insert(City city);}
123456789最佳实战 引入mybatis-starter 配置application.yaml中指定mapper-location位置即可 编写Mapper接口并标注Mapper注解 简单方法直接注解方式 复杂方法编写mapper.xml进行绑定映射 MapperScan(“com.atguigu.admin.mapper”) 简化其他的接口就可以不用标注Mapper注解
4、整合 MyBatis-Plus 完成CRUD
1、什么是MyBatis-Plus
MyBatis-Plus简称 MP是一个 MyBatis 的增强工具在 MyBatis 的基础上只做增强不做改变为简化开发、提高效率而生。
mybatis plus 官网
建议安装 MybatisX 插件
2、整合MyBatis-Plus dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.4.1/version/dependency
12345自动配置 MybatisPlusAutoConfiguration 配置类MybatisPlusProperties 配置项绑定。mybatis-plusxxx 就是对****mybatis-plus的定制 SqlSessionFactory 自动配置好。底层是容器中默认的数据源 **mapperLocations 自动配置好的。有默认值。*classpath*:/mapper/*/*.xml任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件。 建议以后sql映射文件放在 mapper下 容器中也自动配置好了 SqlSessionTemplate Mapper 标注的接口也会被自动扫描建议直接 MapperScan(“com.atguigu.admin.mapper”) 批量扫描就行
优点
只需要我们的Mapper继承 BaseMapper 就可以拥有crud能力
3、CRUD功能 GetMapping(/user/delete/{id})public String deleteUser(PathVariable(id) Long id,RequestParam(value pn,defaultValue 1)Integer pn,RedirectAttributes ra){userService.removeById(id);ra.addAttribute(pn,pn);return redirect:/dynamic_table;}GetMapping(/dynamic_table)public String dynamic_table(RequestParam(valuepn,defaultValue 1) Integer pn,Model model){//表格内容的遍历
// response.sendError
// ListUser users Arrays.asList(new User(zhangsan, 123456),
// new User(lisi, 123444),
// new User(haha, aaaaa),
// new User(hehe , aaddd));
// model.addAttribute(users,users);
//
// if(users.size()3){
// throw new UserTooManyException();
// }//从数据库中查出user表中的用户进行展示//构造分页参数PageUser page new Page(pn, 2);//调用page进行分页PageUser userPage userService.page(page, null);// userPage.getRecords()
// userPage.getCurrent()
// userPage.getPages()model.addAttribute(users,userPage);return table/dynamic_table;}
123456789101112131415161718192021222324252627282930313233343536373839404142Service
public class UserServiceImpl extends ServiceImplUserMapper,User implements UserService {}public interface UserService extends IServiceUser {}
1234567892、NoSQL
Redis 是一个开源BSD许可的内存中的数据结构存储系统它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构如 字符串strings 散列hashes 列表lists 集合sets 有序集合sorted sets 与范围查询 bitmaps hyperloglogs 和 地理空间geospatial 索引半径查询。 Redis 内置了 复制replicationLUA脚本Lua scripting LRU驱动事件LRU eviction事务transactions 和不同级别的 磁盘持久化persistence 并通过 Redis哨兵Sentinel和自动 分区Cluster提供高可用性high availability。
1、Redis自动配置 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency
1234自动配置 RedisAutoConfiguration 自动配置类。RedisProperties 属性类 -- spring.redis.xxx是对redis的配置 连接工厂是准备好的。LettuceConnectionConfiguration、JedisConnectionConfiguration 自动注入了RedisTemplateObject, Object xxxTemplate 自动注入了StringRedisTemplatekv都是String keyvalue 底层只要我们使用 **StringRedisTemplate、**RedisTemplate就可以操作redis
redis环境搭建
1、阿里云按量付费redis。经典网络
2、申请redis的公网连接地址
3、修改白名单 允许0.0.0.0/0 访问
2、RedisTemplate与Lettuce Testvoid testRedis(){ValueOperationsString, String operations redisTemplate.opsForValue();operations.set(hello,world);String hello operations.get(hello);System.out.println(hello);}
1234567893、切换至jedis dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency!-- 导入jedis--dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactId/dependency
spring:redis:host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.comport: 6379password: lfy:Lfy123456client-type: jedisjedis:pool:max-active: 10
1234567891011121314151617181907、单元测试
1、JUnit5 的变化
Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库
作为最新版本的JUnit框架JUnit5与之前版本的Junit框架有很大的不同。由三个不同子项目的几个不同模块组成。
JUnit 5 JUnit Platform JUnit Jupiter JUnit Vintage
JUnit Platform: Junit Platform是在JVM上启动测试框架的基础不仅支持Junit自制的测试引擎其他测试引擎也都可以接入。
JUnit Jupiter: JUnit Jupiter提供了JUnit5的新的编程模型是JUnit5新特性的核心。内部 包含了一个测试引擎用于在Junit Platform上运行。
JUnit Vintage: 由于JUint已经发展多年为了照顾老的项目JUnit Vintage提供了兼容JUnit4.x,Junit3.x的测试引擎。 注意
SpringBoot 2.4 以上版本移除了默认对 Vintage 的依赖。如果需要兼容junit4需要自行引入不能使用junit4的功能 Test****
JUnit 5’s Vintage Engine Removed from **spring-boot-starter-test,如果需要继续兼容junit4需要自行引入vintage**
dependencygroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.hamcrest/groupIdartifactIdhamcrest-core/artifactId/exclusion/exclusions
/dependency
1234567891011dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope
/dependency
12345现在版本
SpringBootTest
class Boot05WebAdminApplicationTests {Testvoid contextLoads() {}
}
123456789以前
SpringBootTest RunWith(SpringTest.class)
SpringBoot整合Junit以后。
编写测试方法Test标注注意需要使用junit5版本的注解Junit类具有Spring的功能Autowired、比如 Transactional 标注测试方法测试完成后自动回滚
2、JUnit5常用注解
JUnit5的注解与JUnit4的注解有所变化
https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations **Test *表示方法是测试方法。但是与JUnit4的Test不同他的职责非常单一不能声明任何属性拓展的测试将会由Jupiter提供额外测试 **ParameterizedTest *表示方法是参数化测试下方会有详细介绍 **RepeatedTest *表示方法可重复执行下方会有详细介绍 **DisplayName *为测试类或者测试方法设置展示名称 **BeforeEach *表示在每个单元测试之前执行 **AfterEach *表示在每个单元测试之后执行 **BeforeAll *表示在所有单元测试之前执行 **AfterAll *表示在所有单元测试之后执行 **Tag *表示单元测试类别类似于JUnit4中的Categories **Disabled *表示测试类或测试方法不执行类似于JUnit4中的Ignore **Timeout *表示测试方法运行如果超过了指定时间将会返回错误 **ExtendWith *为测试类或测试方法提供扩展类引用
import org.junit.jupiter.api.Test; //注意这里使用的是jupiter的Test注解public class TestDemo {TestDisplayName(第一次测试)public void firstTest() {System.out.println(hello world);}
123456789103、断言assertions
断言assertions是测试方法中的核心部分用来对测试需要满足的条件进行验证。这些断言方法都是 org.junit.jupiter.api.Assertions 的静态方法。JUnit 5 内置的断言可以分成如下几个类别
检查业务逻辑返回的数据是否合理。
所有的测试运行结束以后会有一个详细的测试报告
1、简单断言
用来对单个值进行简单的验证。如
方法说明assertEquals判断两个对象或两个原始类型是否相等assertNotEquals判断两个对象或两个原始类型是否不相等assertSame判断两个对象引用是否指向同一个对象assertNotSame判断两个对象引用是否指向不同的对象assertTrue判断给定的布尔值是否为 trueassertFalse判断给定的布尔值是否为 falseassertNull判断给定的对象引用是否为 nullassertNotNull判断给定的对象引用是否不为 null
Test
DisplayName(simple assertion)
public void simple() {assertEquals(3, 1 2, simple math);assertNotEquals(3, 1 1);assertNotSame(new Object(), new Object());Object obj new Object();assertSame(obj, obj);assertFalse(1 2);assertTrue(1 2);assertNull(null);assertNotNull(new Object());
}
123456789101112131415162、数组断言
通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等
Test
DisplayName(array assertion)
public void array() {assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}
123453、组合断言
assertAll 方法接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言可以通过 lambda 表达式很容易的提供这些断言
Test
DisplayName(assert all)
public void all() {assertAll(Math,() - assertEquals(2, 1 1),() - assertTrue(1 0));
}
123456784、异常断言
在JUnit4时期想要测试方法的异常情况时需要用**Rule注解的ExpectedException变量还是比较麻烦的。而JUnit5提供了一种新的断言方式Assertions.assertThrows()** ,配合函数式编程就可以进行使用。
Test
DisplayName(异常测试)
public void exceptionTest() {ArithmeticException exception Assertions.assertThrows(//扔出断言异常ArithmeticException.class, () - System.out.println(1 % 0));}
123456785、超时断言
Junit5还提供了Assertions.assertTimeout() 为测试方法设置了超时时间
Test
DisplayName(超时测试)
public void timeoutTest() {//如果测试方法时间超过1s将会异常Assertions.assertTimeout(Duration.ofMillis(1000), () - Thread.sleep(500));
}
1234566、快速失败
通过 fail 方法直接使得测试失败
Test
DisplayName(fail)
public void shouldFail() {fail(This should fail);
}
123454、前置条件assumptions
JUnit 5 中的前置条件assumptions【假设】类似于断言不同之处在于不满足的断言会使得测试方法失败而不满足的前置条件只会使得测试方法的执行终止。前置条件可以看成是测试方法执行的前提当该前提不满足时就没有继续执行的必要。
DisplayName(前置条件)
public class AssumptionsTest {private final String environment DEV;TestDisplayName(simple)public void simpleAssume() {assumeTrue(Objects.equals(this.environment, DEV));assumeFalse(() - Objects.equals(this.environment, PROD));}TestDisplayName(assume then do)public void assumeThenDo() {assumingThat(Objects.equals(this.environment, DEV),() - System.out.println(In DEV));}
}
1234567891011121314151617181920assumeTrue 和 assumFalse 确保给定的条件为 true 或 false不满足条件会使得测试执行终止。assumingThat 的参数是表示条件的布尔值和对应的 Executable 接口的实现对象。只有条件满足时Executable 对象才会被执行当条件不满足时测试执行并不会终止。
5、嵌套测试
JUnit 5 可以通过 Java 中的内部类和Nested 注解实现嵌套测试从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用BeforeEach 和AfterEach 注解而且嵌套的层次没有限制。
DisplayName(A stack)
class TestingAStackDemo {StackObject stack;TestDisplayName(is instantiated with new Stack())void isInstantiatedWithNew() {new Stack();}NestedDisplayName(when new)class WhenNew {BeforeEachvoid createNewStack() {stack new Stack();}TestDisplayName(is empty)void isEmpty() {assertTrue(stack.isEmpty());}TestDisplayName(throws EmptyStackException when popped)void throwsExceptionWhenPopped() {assertThrows(EmptyStackException.class, stack::pop);}TestDisplayName(throws EmptyStackException when peeked)void throwsExceptionWhenPeeked() {assertThrows(EmptyStackException.class, stack::peek);}NestedDisplayName(after pushing an element)class AfterPushing {String anElement an element;BeforeEachvoid pushAnElement() {stack.push(anElement);}TestDisplayName(it is no longer empty)void isNotEmpty() {assertFalse(stack.isEmpty());}TestDisplayName(returns the element when popped and is empty)void returnElementWhenPopped() {assertEquals(anElement, stack.pop());assertTrue(stack.isEmpty());}TestDisplayName(returns the element when peeked but remains not empty)void returnElementWhenPeeked() {assertEquals(anElement, stack.peek());assertFalse(stack.isEmpty());}}}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970716、参数化测试
参数化测试是JUnit5很重要的一个新特性它使得用不同的参数多次运行测试成为了可能也为我们的单元测试带来许多便利。
利用**ValueSource**等注解指定入参我们将可以使用不同的参数进行多次单元测试而不需要每新增一个参数就新增一个单元测试省去了很多冗余代码。
ValueSource: 为参数化测试指定入参来源支持八大基础类以及String类型,Class类型
NullSource: 表示为参数化测试提供一个null的入参
EnumSource: 表示为参数化测试提供一个枚举入参
CsvFileSource表示读取指定CSV文件内容作为参数化测试入参
MethodSource表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)
当然如果参数化测试仅仅只能做到指定普通的入参还达不到让我觉得惊艳的地步。让我真正感到他的强大之处的地方在于他可以支持外部的各类入参。如:CSV,YML,JSON 文件甚至方法的返回值也可以作为入参。只需要去实现ArgumentsProvider接口任何外部文件都可以作为它的入参。
ParameterizedTest
ValueSource(strings {one, two, three})
DisplayName(参数化测试1)
public void parameterizedTest1(String string) {System.out.println(string);Assertions.assertTrue(StringUtils.isNotBlank(string));
}ParameterizedTest
MethodSource(method) //指定方法名
DisplayName(方法来源参数)
public void testWithExplicitLocalMethodSource(String name) {System.out.println(name);Assertions.assertNotNull(name);
}static StreamString method() {return Stream.of(apple, banana);
}
12345678910111213141516171819207、迁移指南
在进行迁移的时候需要注意如下的变化 注解在 org.junit.jupiter.api 包中断言在 org.junit.jupiter.api.Assertions 类中前置条件在 org.junit.jupiter.api.Assumptions 类中。 把Before 和After 替换成BeforeEach 和AfterEach。 把BeforeClass 和AfterClass 替换成BeforeAll 和AfterAll。 把Ignore 替换成Disabled。 把Category 替换成Tag。 把RunWith、Rule 和ClassRule 替换成ExtendWith。
08、指标监控
1、SpringBoot Actuator
1、简介
未来每一个微服务在云上部署以后我们都需要对其进行监控、追踪、审计、控制等。SpringBoot就抽取了Actuator场景使得我们每个微服务快速引用即可获得生产级别的应用监控、审计等功能。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency
12342、1.x与2.x的不同 3、如何使用 引入场景 访问 http://localhost:8080/actuator/** 暴露所有监控信息为HTTP
management:endpoints:enabled-by-default: true #暴露所有端点信息web:exposure:include: * #以web方式暴露
123456测试
http://localhost:8080/actuator/beans
http://localhost:8080/actuator/configprops
http://localhost:8080/actuator/metrics
http://localhost:8080/actuator/metrics/jvm.gc.pause
http://localhost:8080/actuator/endpointName/detailPath 。。。。。。
4、可视化
https://github.com/codecentric/spring-boot-admin
2、Actuator Endpoint
1、最常使用的端点
ID描述auditevents暴露当前应用程序的审核事件信息。需要一个AuditEventRepository组件。beans显示应用程序中所有Spring Bean的完整列表。caches暴露可用的缓存。conditions显示自动配置的所有条件信息包括匹配或不匹配的原因。configprops显示所有ConfigurationProperties。env暴露Spring的属性ConfigurableEnvironmentflyway显示已应用的所有Flyway数据库迁移。 需要一个或多个Flyway组件。health显示应用程序运行状况信息。httptrace显示HTTP跟踪信息默认情况下最近100个HTTP请求-响应。需要一个HttpTraceRepository组件。info显示应用程序信息。integrationgraph显示Spring integrationgraph 。需要依赖spring-integration-core。loggers显示和修改应用程序中日志的配置。liquibase显示已应用的所有Liquibase数据库迁移。需要一个或多个Liquibase组件。metrics显示当前应用程序的“指标”信息。mappings显示所有RequestMapping路径列表。scheduledtasks显示应用程序中的计划任务。sessions允许从Spring Session支持的会话存储中检索和删除用户会话。需要使用Spring Session的基于Servlet的Web应用程序。shutdown使应用程序正常关闭。默认禁用。startup显示由ApplicationStartup收集的启动步骤数据。需要使用SpringApplication进行配置BufferingApplicationStartup。threaddump执行线程转储。
如果您的应用程序是Web应用程序Spring MVCSpring WebFlux或Jersey则可以使用以下附加端点
ID描述heapdump返回hprof堆转储文件。jolokia通过HTTP暴露JMX bean需要引入Jolokia不适用于WebFlux。需要引入依赖jolokia-core。logfile返回日志文件的内容如果已设置logging.file.name或logging.file.path属性。支持使用HTTPRange标头来检索部分日志文件的内容。prometheus以Prometheus服务器可以抓取的格式公开指标。需要依赖micrometer-registry-prometheus。
最常用的Endpoint Health监控状况 Metrics运行时指标 Loggers日志记录
2、Health Endpoint
健康检查端点我们一般用于在云平台平台会定时的检查应用的健康状况我们就需要Health Endpoint可以为平台返回当前应用的一系列组件健康状况的集合。
重要的几点 health endpoint返回的结果应该是一系列健康检查后的一个汇总报告 很多的健康检查默认已经自动配置好了比如数据库、redis等 可以很容易的添加自定义的健康检查机制 3、Metrics Endpoint
提供详细的、层级的、空间指标信息这些信息可以被pull主动推送或者push被动获取方式得到 通过Metrics对接多种监控系统 简化核心Metrics开发 添加自定义Metrics或者扩展已有Metrics 4、管理Endpoints
1、开启与禁用Endpoints
默认所有的Endpoint除过shutdown都是开启的。需要开启或者禁用某个Endpoint。配置模式为 management.endpoint…enabled true
management:endpoint:beans:enabled: true
1234或者禁用所有的Endpoint然后手动开启指定的Endpoint
management:endpoints:enabled-by-default: falseendpoint:beans:enabled: truehealth:enabled: true
123456782、暴露Endpoints
支持的暴露方式 HTTP默认只暴露health和info Endpoint JMX默认暴露所有Endpoint 除过health和info剩下的Endpoint都应该进行保护访问。如果引入SpringSecurity则会默认配置安全访问规则
IDJMXWebauditeventsYesNobeansYesNocachesYesNoconditionsYesNoconfigpropsYesNoenvYesNoflywayYesNohealthYesYesheapdumpN/ANohttptraceYesNoinfoYesYesintegrationgraphYesNojolokiaN/ANologfileN/ANologgersYesNoliquibaseYesNometricsYesNomappingsYesNoprometheusN/ANoscheduledtasksYesNosessionsYesNoshutdownYesNostartupYesNothreaddumpYesNo
3、定制 Endpoint
1、定制 Health 信息
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;Component
public class MyHealthIndicator implements HealthIndicator {Overridepublic Health health() {int errorCode check(); // perform some specific health checkif (errorCode ! 0) {return Health.down().withDetail(Error Code, errorCode).build();}return Health.up().build();}}构建Health
Health build Health.down().withDetail(msg, error service).withDetail(code, 500).withException(new RuntimeException()).build();
management:health:enabled: trueshow-details: always #总是显示详细信息。可显示每个模块的状态信息
12345678910111213141516171819202122232425262728Component
public class MyComHealthIndicator extends AbstractHealthIndicator {/*** 真实的检查方法* param builder* throws Exception*/Overrideprotected void doHealthCheck(Health.Builder builder) throws Exception {//mongodb。 获取连接进行测试MapString,Object map new HashMap();// 检查完成if(1 2){
// builder.up(); //健康builder.status(Status.UP);map.put(count,1);map.put(ms,100);}else {
// builder.down();builder.status(Status.OUT_OF_SERVICE);map.put(err,连接超时);map.put(ms,3000);}builder.withDetail(code,100).withDetails(map);}
}
123456789101112131415161718192021222324252627282930312、定制info信息
常用两种方式
1、编写配置文件
info:appName: boot-adminversion: 2.0.1mavenProjectName: project.artifactId #使用可以获取maven的pom文件值mavenProjectVersion: project.version
123452、编写InfoContributor
import java.util.Collections;import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;Component
public class ExampleInfoContributor implements InfoContributor {Overridepublic void contribute(Info.Builder builder) {builder.withDetail(example,Collections.singletonMap(key, value));}}
12345678910111213141516http://localhost:8080/actuator/info 会输出以上方式返回的所有info信息
3、定制Metrics信息
1、SpringBoot支持自动适配的Metrics JVM metrics, report utilization of: Various memory and buffer pools Statistics related to garbage collection Threads utilization Number of classes loaded/unloaded CPU metrics File descriptor metrics Kafka consumer and producer metrics Log4j2 metrics: record the number of events logged to Log4j2 at each level Logback metrics: record the number of events logged to Logback at each level Uptime metrics: report a gauge for uptime and a fixed gauge representing the application’s absolute start time Tomcat metrics (server.tomcat.mbeanregistry.enabled must be set to true for all Tomcat metrics to be registered) Spring Integration metrics
2、增加定制Metrics
class MyService{Counter counter;public MyService(MeterRegistry meterRegistry){counter meterRegistry.counter(myservice.method.running.counter);}public void hello() {counter.increment();}
}//也可以使用下面的方式
Bean
MeterBinder queueSize(Queue queue) {return (registry) - Gauge.builder(queueSize, queue::size).register(registry);
}
12345678910111213141516174、定制Endpoint
Component
Endpoint(id container)
public class DockerEndpoint {ReadOperationpublic Map getDockerInfo(){return Collections.singletonMap(info,docker started...);}WriteOperationprivate void restartDocker(){System.out.println(docker restarted....);}}
12345678910111213141516场景开发ReadinessEndpoint来管理程序是否就绪或者Liveness****Endpoint来管理程序是否存活
当然这个也可以直接使用 https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-kubernetes-probes
09、原理解析
1、Profile功能
为了方便多环境适配springboot简化了profile功能。
1、application-profile功能 默认配置文件 application.yaml任何时候都会加载 指定环境配置文件 application-{env}.yaml 激活指定环境 配置文件激活 命令行激活java -jar xxx.jar –spring.profiles.activeprod --person.namehaha 修改配置文件的任意值命令行优先 默认配置与环境配置同时生效 同名配置项profile配置优先
2、Profile条件装配功能
Configuration(proxyBeanMethods false)
Profile(production)
public class ProductionConfiguration {// ...}
12345673、profile分组
spring.profiles.group.production[0]proddb
spring.profiles.group.production[1]prodmq使用--spring.profiles.activeproduction 激活
12342、外部化配置
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config Default properties (specified by setting SpringApplication.setDefaultProperties). PropertySource annotations on your Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins. Config data (such as **application.properties** files) A RandomValuePropertySource that has properties only in random.*. OS environment variables. Java System properties (System.getProperties()). JNDI attributes from java:comp/env. ServletContext init parameters. ServletConfig init parameters. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property). Command line arguments. properties attribute on your tests. Available on SpringBootTest and the test annotations for testing a particular slice of your application. TestPropertySource annotations on your tests. Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.
1、外部配置源
常用Java属性文件、YAML文件、环境变量、命令行参数
2、配置文件查找位置
(1) classpath 根路径
(2) classpath 根路径下config目录
(3) jar包当前目录
(4) jar包当前目录的config目录
(5) /config子目录的直接子目录
3、配置文件加载顺序 当前jar包内部的application.properties和application.yml 当前jar包内部的application-{profile}.properties 和 application-{profile}.yml 引用的外部jar包的application.properties和application.yml 引用的外部jar包的application-{profile}.properties 和 application-{profile}.yml
4、指定环境优先外部优先后面的可以覆盖前面的同名配置项
3、自定义starter
1、starter启动原理
starter-pom引入 autoconfigurer 包 autoconfigure包中配置使用 META-INF/spring.factories 中 EnableAutoConfiguration 的值使得项目启动加载指定的自动配置类 编写自动配置类 xxxAutoConfiguration - xxxxProperties Configuration Conditional EnableConfigurationProperties Bean …
引入starter — xxxAutoConfiguration — 容器中放入组件 ---- 绑定xxxProperties ---- 配置项
2、自定义starter
atguigu-hello-spring-boot-starter启动器
atguigu-hello-spring-boot-starter-autoconfigure自动配置包
4、SpringBoot原理
Spring原理【Spring注解】、SpringMVC原理、自动配置原理、SpringBoot原理
1、SpringBoot启动过程 创建 SpringApplication 保存一些信息。 判定当前应用的类型。ClassUtils。Servlet bootstrappers**初始启动引导器List去spring.factories文件中找** org.springframework.boot.Bootstrapper 找 ApplicationContextInitializer去spring.factories****找 ApplicationContextInitializer ListApplicationContextInitializer? initializers 找 ApplicationListener 应用监听器。去spring.factories****找 ApplicationListener ListApplicationListener? listeners 运行 SpringApplication StopWatch 记录应用的启动时间 **创建引导上下文Context环境**createBootstrapContext() 获取到所有之前的 bootstrappers 挨个执行 intitialize() 来完成对引导启动器上下文环境设置 让当前应用进入headless模式。java.awt.headless 获取所有 RunListener**运行监听器【为了方便所有Listener进行事件感知】** getSpringFactoriesInstances 去spring.factories****找 SpringApplicationRunListener. 遍历 SpringApplicationRunListener 调用 starting 方法 相当于通知所有感兴趣系统正在启动过程的人项目正在 starting。 保存命令行参数ApplicationArguments 准备环境 prepareEnvironment; 返回或者创建基础环境信息对象。StandardServletEnvironment 配置环境信息对象。 读取所有的配置源的配置属性值。 绑定环境信息 监听器调用 listener.environmentPrepared()通知所有的监听器当前环境准备完成 创建IOC容器createApplicationContext 根据项目类型Servlet创建容器 当前会创建 AnnotationConfigServletWebServerApplicationContext 准备ApplicationContext IOC容器的基本信息 prepareContext() 保存环境信息 IOC容器的后置处理流程。 应用初始化器applyInitializers 遍历所有的 ApplicationContextInitializer 。调用 initialize.。来对ioc容器进行初始化扩展功能 - 遍历所有的 listener 调用 contextPrepared。EventPublishRunListenr通知所有的监听器****contextPrepared 所有的监听器 调用 contextLoaded。通知所有的监听器 contextLoaded **刷新IOC容器。**refreshContext 创建容器中的所有组件Spring注解 容器刷新完成后工作afterRefresh 所有监听 器 调用 listeners.started(context); 通知所有的监听器 started **调用所有runners**callRunners() 获取容器中的 ApplicationRunner 获取容器中的 CommandLineRunner 合并所有runner并且按照Order进行排序 遍历所有的runner。调用 run 方法 如果以上有异常 调用Listener 的 failed 调用所有监听器的 running 方法 listeners.running(context); 通知所有的监听器 running **running如果有问题。继续通知 failed 。**调用所有 Listener 的 **failed**通知所有的监听器 failed
public interface Bootstrapper {/*** Initialize the given {link BootstrapRegistry} with any required registrations.* param registry the registry to initialize*/void intitialize(BootstrapRegistry registry);}
123456789FunctionalInterface
public interface ApplicationRunner {/*** Callback used to run the bean.* param args incoming application arguments* throws Exception on error*/void run(ApplicationArguments args) throws Exception;}
FunctionalInterface
public interface CommandLineRunner {/*** Callback used to run the bean.* param args incoming main method arguments* throws Exception on error*/void run(String... args) throws Exception;}
123456789101112131415161718192021222、Application Events and Listeners
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-application-events-and-listeners
ApplicationContextInitializer
ApplicationListener
SpringApplicationRunListener