springboot
- 笔记
- request.getRequestDispatcher()的两个方法forward()/include()
- *关于响应式开发的概念*
- Mybatis 中依赖配置文件名称和mapper接口名称是否要一致及原因
1,微服务
- 微服务: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交互
- 服务围绕业务功能拆分
- 可以由全自动部署机制独立部署
- 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术
2,分布式
- 分布式的困难
- 远程调用
- 服务发现
- 负载均衡
- 服务容错
- 配置管理
- 服务监控
- 链路追踪
- 日志管理
- 任务调度
分布式的解决
- Springboot + SpringCloud
3,云原生
原生应用如何上云。 Cloud Native
- 上云的困难
• 服务自愈
• 弹性伸缩
• 服务隔离
• 自动化部署
• 灰度发布
• 流量治理
• …
4, springboot的特点
4.1 依赖管理
1.1,依赖管理
- 父项目做依赖管理(几乎声明了所有开发中常用的依赖的版本号)
- 开发导入starter场景启动器
- 无需关注版本号,自动版本仲裁
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
4.2 自动配置
-
自动配好Tomcat
- 引入Tomcat依赖。
- 配置Tomcat• 自动配好SpringMVC
-
自动配好SpringMVC
- 引入SpringMVC全套组件
- 自动配好SpringMVC常用组件(功能)
-
自动配好Web常见功能,如:字符编码问题
- SpringBoot帮我们配置好了所有web开发的常见场景
-
默认的包结构
-
主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
-
无需以前的包扫描配置
-
要想使不在主程序的包也被扫描,则需要修改默认的scanBasePackages
-
想要改变扫描路径,@SpringBootApplication(scanBasePackages=“com.atguigu”)或者@ComponentScan 指定扫描路径
-
-
各种配置拥有默认值
- 默认配置最终都是映射到某个类上,如:MultipartProperties
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
-
按需加载所有自动配置项
- 非常多的starter
- 引入了哪些场景这个场景的自动配置才会开启
- SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
• …
5,底层注解
5.1 @Configuration
-
@Configuration,告诉Springboot这是一个配置类
-
@Bean,给容器中添加组件,以方法名作为组件的id,返回类型就是组件类型。方法返回的值就是组件在容器中的实例。
-
配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
-
配置类本身也是组件
-
proxyBeanMethods:代理bean的方法
- Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
- Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
- 组件依赖必须使用Full模式默认。其他默认是否Lite模式
-
外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例
-
如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有
-
保持组件单实例,如果为false,则拿到的对象就不是单实例
-
也可以使用别的方法创建组件;如@Bean,@Component,@Controller,@Service,@Repository
-
@ComponentScan
5.2 @Import
4、@Import({User.class, DBHelper.class})
* 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
*
*
*
*/
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}
5.3 @Conditional
- 条件装配:满足Conditional指定的条件,则进行组件注入
5.4 @ImportResource 原生配置文件引入
5.5 配置绑定
- 1, @ConfigurationProperties(prefix = " ") perfix表示在配置文件中的前缀
- 2、@EnableConfigurationProperties + @ConfigurationProperties
@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
- 3、@Component + @ConfigurationProperties 这种方法要求组件在容器中,所以需要@Component
6,自动配置原理
- 6.1、引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}
1、@SpringBootConfiguration
- @Configuration。代表当前是一个配置类
2、@ComponentScan
- 指定扫描哪些,Spring注解;
3、@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
- 1、@AutoConfigurationPackage
自动配置包?指定了默认的包规则
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
- 2,@ Import
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
- 按需开启自动配置项
- 虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration,
- 但最终按照条件装配规则(@Conditional),最终会按需配置。
6.2 修改默认配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
给容器中加入了文件上传解析器;
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
}
6.3 总结
- SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
- 生效的配置类就会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就有了
- 定制化配置
• 用户直接自己@Bean替换底层的组件
• 用户去看这个组件是获取的配置文件的什么值就去修改。 - xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties
7,最佳实践
-
查看自动配置了哪些(选做)
• 自己分析,引入场景对应的自动配置一般都生效了
• 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效) -
是否需要修改
- 参照文档修改配置项
- https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
- 自己分析。xxxxProperties绑定了配置文件的哪些。
-
自定义加入或者替换组件
- @Bean、@Component。。。
-
自定义器 XXXXXCustomizer;
- …
8.开发小技巧
- 8.1 Lombok
- 8.2 dev-tools
- 热更新
- 项目或者页面修改以后:Ctrl+F9;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
- 8.3 Spring Initailizr(项目初始化向导)
- 1、自动依赖引入
- 2, 自动创建项目结构
- 3,自动编写好主配置类
9,配置文件 -yaml的用法
-
简介
- YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。
- 非常适合用来做以数据为中心的配置文件
-
基本语法
• key: value;kv之间有空格
• 大小写敏感
• 使用缩进表示层级关系
• 缩进不允许使用tab,只允许空格
• 缩进的空格数不重要,只要相同层级的元素左对齐即可
• '#‘表示注释
• 字符串无需加引号,如果要加,’‘与""表示字符串内容 会被 转义/不转义。’'会将\n作为字符串输出 双引号会将\n作为换行输出 -
配置提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
//下面的意思是打包的时候不打包配置处理器
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
Web开发
1,简单功能分析
- 1.1、静态资源访问
- 1、静态资源目录
只要静态资源放在类路径下: called /static (or /public or /resources or /META-INF/resources)
访问 : 当前项目根路径/ + 静态资源名
原理: 静态映射/**。
请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面
- 1、静态资源目录
- 改变默认的静态资源路径
//静态资源访问前缀
spring:
mvc:
static-path-pattern: /res/**
resources:
static-locations: [classpath:/haha/]
当前项目+ static-path-pattern+静态资源名 = 静态资源文件夹下找
- 1.2 欢迎页
- 静态资源路径下 index.html
- 可以配置静态资源路径
- 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致welcome page功能失效
resources:
static-locations: [classpath:/haha/]
-
controller能处理/index
-
1.3 自定义 Favicon(网页打开后的小图标)
favicon.ico 放在静态资源目录下即可。
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致 Favicon 功能失效
2,请求参数处理
请求映射
-
1、rest使用与原理
- @xxxMapping;
- Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
- 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
- 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
- 核心Filter;HiddenHttpMethodFilter
- 用法: 表单method=post,隐藏域 _method=put
• SpringBoot中手动开启
• 扩展:如何把_method 这个名字换成我们自己喜欢的。
-
也可以使用下述的注解直接使用Rest风格
-
2,请求映射原理
####普通参数与基本注解
-
1.1、注解:
-
@PathVariable、路径变量 下图中的pv,是获取到所有的路径变量中的k,v
测试结果:
-
@RequestHeader、获取请求头中的信息
-
@RequestParam、获取请求参数
-
-
@RequestAttribute 获取request域属性
-
@MatrixVariable、矩阵变量,矩阵变量应该绑定在路径变量
矩阵变量要和路径放在一起,;之前是矩阵变量,;之后是矩阵变量
spring中默认关闭矩阵变量功能,需要自定义,有两种方法
1,
2,
如果有两个变量名一样,加上路径加以区分
-
@CookieValue、获取Cookie的值
-
@RequestBody 获取请求体中的数据
-
1.2、Servlet API:
WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId -
1.3 复杂参数:
Map、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)、ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder
2,POJO封装过程
3,参数处理原理
-
HandlerMapping中找到能处理请求的Handler(Controller.method())
-
为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
-
适配器执行目标方法并确定方法参数的每一个值
-
1、HandlerAdapter
0 - 支持方法上标注@RequestMapping
1 - 支持函数式编程的
4、数据响应与内容协商
-
4.1 响应JSON
- jackson.jar+@ResponseBody
-
开启浏览器参数方式内容协商功能
为了方便内容协商,开启基于请求参数的内容协商功能。
spring:
mvc:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式
发请求: http://localhost:8080/test/person?format=json
http://localhost:8080/test/person?format=xml
5, 自定义 MessageConverter
无论修改SpringMVC的什么功能。都是在给容器中添加一个 WebMvcConfigurer,然后在其中修改
视图解析
- 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
添加链接描述
thymeleaf中的[[${}]]
-
状态码:400:Bad Request 一般都是浏览器的参数没有传递正确
2、定制错误处理逻辑 -
自定义错误页
- error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页
-
@ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的
-
@ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error
-
Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。
-
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
-
自定义异常解析器
####Web原生组件注入(Servlet、Filter、Listener)
-
1、使用Servlet API
@ServletComponentScan(basePackages = “com.atguigu.admin”) :指定原生Servlet组件都放在那里
@WebServlet(urlPatterns = “/my”):效果:直接响应,没有经过Spring的拦截器?
@WebFilter(urlPatterns={"/css/","/images/"}) /*是原生Servlet,/***是springboot
@WebListener
推荐可以这种方式;
扩展:DispatchServlet 如何注册进来
• 容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties;对应的配置文件配置项是 spring.mvc。
• 通过 ServletRegistrationBean 把 DispatcherServlet 配置进来。
• 默认映射的是 / 路径。 -
2、使用RegistrationBean
ServletRegistrationBean, FilterRegistrationBean, and ServletListenerRegistrationBean -
return new FilterRegistrationBean(myFilter,myServlet());Servlet是什么路径,Filter就拦截什么路径
数据访问
- mybatis 配置
# 配置mybatis规则
mybatis:
# config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
configuration:
map-underscore-to-camel-case: true
可以不写全局配置文件,所有全局配置文件的配置都放在configuration配置项中即可。
全局配置文件config-location和configuration只能有一个存在
mybatisplus
@TableField(exist = false) 表示表中不存在这种属性,可以不查询
Filter和Interceptor几乎拥有相同的功能
-
1,Filter是Servlet定义的原生组件。好处,脱离Spring应用也能使用
-
2,Interceptor是Spring定义的接口,可以使用Spring的自动装配等功能。
-
redis
只有容器中的组件spring才会解析注解,自己new的不行
单元测试
- 要想在测试类中使用spring的注入等功能,就要加@SpringBootTest注解,这是一个复合注解
- 断言
- 前面的断言失败,后面的代码不会执行
- 嵌套测试情况下,外层的Test不能驱动内层的Before(After)Each/All之类的方法提前/之后运行,内层的Test可以驱动外层的Before(After)Each/All之类的方法提前/之后运行
指标监控
-
SpringBoot Actuator
-
暴露Endpoints
支持的暴露方式
• HTTP:默认只暴露health和info Endpoint
• JMX:默认暴露所有Endpoint, jconsole,java控制台
原理解析
-
1,Profile功能
-
@Profile条件装配功能
@Profile(“env”) 指定在哪个配置文件下生效
-
classpath java和resources都是类路径
###SpringBoot原理
Spring原理【Spring注解】,SpringMVC原理,自动配置原理,SpringBoot原理