SpringBoot

1、Spring与SpringBoot

  • Spring的生态

    覆盖了:web开发、数据访问、安全控制、分布式、消息服务、移动开发、批处理.....

  • Spring5重大升级

    1. 响应式编程

    2. 内部源码设计

      基于Java8的一些新特性,如:接口默认实现。重新设计源码架构。

  • 为什么要使用SpringBoot?

    Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".

    能快速创建出生产级别的Spring应用。

  • SpringBoot优点

    • 创建独立Spring应用
    • 内嵌web服务器
    • 自动starter依赖,简化构建配置
    • 自动配置Spring以及第三方功能
    • 提供生产级别的监控、健康检查及外部化配置
    • 无代码生成、无需编码XML

    SpringBoot是整合Spring技术栈的一站式框架
    SpringBoot是简化Spring技术栈的快速开发脚手架

  • SpringBoot缺点

    • 人称版本帝,迭代快,需要时刻关注变化
    • 封装太深,内部原理复杂,不容易精通

2、微服务与分布式

  • 微服务

    → 微服务是一种架构风格

    → 一个应用拆分为一组小型服务

    → 每个服务运行在自己的进程内,也就是可独立部署和升级

    → 服务之间使用轻量级HTTP交互

    → 服务围绕业务功能拆分

    → 可以由全自动部署机制独立部署

    → 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术

  • 分布式的困难

    • 远程调用
    • 服务发现
    • 负载均衡
    • 服务容错
    • 配置管理
    • 服务监控
    • 链路追踪
    • 日志管理
    • 任务调度
  • 分布式的解决

    SpringBoot + SpringCloud

3、了解自动配置

  • 自动配置
自动配好Tomcat
-》 引入Tomcat依赖
-》 配置Tomcat

自动配好SpringMVC
-》 引入SpringMVC全套组件
-》 自动配好SpringMVC常用组件(功能)
自动配好Web常见功能,如:字符编码问题
-》 SpringBoot帮我们配置好了所有Web开发的常见场景
默认的包结构
-》 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
-》 无需以前的包扫描配置
-》 想要改变扫描路径
    @SpringBootApplication(scanBasePackages="com.atguigu")
    或者@ComponentScan指定扫描路径
    
各种配置拥有默认值
-》 默认配置最终都是映射到某个类上,如:MultipartProperties
-》 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
按需加载所有自动配置项
-》 非常多的starter
-》 引入了哪些场景这个场景的自动配置才会开启
-》 SpringBoot所有的自动配置功能都在spring-boot-autoconfigure包里面

  • 容器功能
    1. @Configuration

      Full模式与Lite模式

@Configuration(proxyBeanMethods = true / false)
true → Full:保证每个@Bean方法被调用多少次返回的组件都是单实例的
false → Lite:每个@Bean方法调用多少次返回的组件都是新创建的
组件依赖必须使用Full模式默认,其他默认是否Lite模式

最佳实践
→ 配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
→ 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式

1. @Import

@Import({User.class,DBHelper.class})
给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
1. **@Conditional**

    条件装配:满足Conditional指定的条件,则进行组件注入
1. **@ImportResource**

    原生配置文件引入
@ImportResource("classpath:beans.xml")
public class MyConfig{}

1. **@ConfigurationProperties**
//只有在容器中的组件,才会拥有SpringBoot提供的强大功能
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car{}
1. **@EnableConfigurationProperties**
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
@EnableConfigurationProperties(Car.class)
public class MyConfig{}
**自动配置原理入门**

`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(AutoConfigurationImportSelector.class)
-》 利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
-》 调用List<String> configurations = 
    getCandidateConfigurations(annotationMetadata,attributes)
    获取到所有需要导入到容器中的配置类
-》 利用工厂加载 Map<String,List<String>> loadSpringFactories(@Nullable ClassLoader classLoader)
    得到所有的组件
-》 从META-INF/spring.factories位置来加载一个文件
    默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
    spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories  
**按需开启自动配置项**

**修改默认配置**
总结:
-》 SpringBoot先加载所有的自动配置类 xxxAutoConfiguration
-》 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值
    xxxProperties里面拿。xxxProperties和配置文件进行了绑定
-》 生效的配置类就会给容器中装配很多组件
-》 只要容器中有这些组件,相当于这些功能就有了
-》 定制化配置
    -> 用户直接自己@Bean替换底层的组件
    -> 用户去看这个组件是获取的配置文件什么值就去修改

**xxxAutoConfiguration ---> 组件 ---> xxxProperties里面拿值 
---> application.properties**
  • Lombok

    使用Lombok简化JavaBean开发

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

然后在ide中搜索安装lombok插件
//使用@Data注解,lombok会帮我们生成已有属性的getter和setter方法
//使用@ToString注解,lombok会帮我们生成toString方法
//使用@AllArgsConstructor注解,lombok会帮我们生成所有参数的构造方法
//使用@NoArgsConstructor注解,lombok会帮我们生成无参构造方法
//使用@EqualsAndHashCode注解,lombok会帮我们重写equals()和hashCode()
//使用@Slf4j注解,注入日志类
@Slf4j
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Data
@Component
@ConfigurationProperties(prefix="mycar")
public class Car{
    private String brand;
    private Integer price;
}
  • 一些注意事项
    1. SpringMVC自动配置概况

      • 内容协商视图解析器和BeanName视图解析器
      • 静态资源(包括webjars)
      • 自动注册Converter,GenericConverter,Formatter
      • 支持HttpMessageConverters(后来我们配合内容协商理解原理)
      • 自动注册MessageCodesResolver(国际化用)
      • 静态index.html页支持
      • 自定义Favicon
      • 自动使用ConfigurableWebBindingInitializer,(DataBinder负责将请求数据绑定到JavaBean上)
    2. 定制化SpringMVC

      • 不用@EnableWebMvc注解,使用@Configuration + WebMvcConfigurer自定义规则
      • 声明WebMvcRegistrations改变默认底层组件
      • 使用@EnableWebMvc + @Configuration + DelegatingWebMvcConfiguration 全面接管SpringMVC
    3. 静态资源访问

      静态资源目录

      只要静态资源放在类路径下:called /static(or /public or /resources or /META-INF/resources)

      访问:当前项目根路径 / + 静态资源名

      原理:静态映射/**

      请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源能找到就访问,找不到就404

    4. 欢迎页支持

      静态资源路径下index.html

      • 可以配置静态资源路径
      • 不可以配置静态资源的访问前缀,否则导致index.html不能被默认访问
spring:
#  mvc:
#    static-path-pattern: /res/**  这个会导致welcome page功能失效

  resources:
    static-locations: [classpath:/haha/]
1. **配置类只有一个有参构造器**

    有参构造器所有参数的值都会从容器中确定
1. **面试题:页面开发,cookie禁用了,session里面的内容怎么使用?**
以往:
session.set(a,b) ---> jsessionid ---> cookie --->每次发请求携带

可以使用矩阵变量的方式:
url重写:
/abc;jsessionid=xxx 把cookie的值使用矩阵变量的方式进行传递

/boss/1/2:查询1号里面的2号
/boss/1;age=20/2;age=20:查询1号里面age=20的2号里面age=20的
    SpringBoot默认是禁用了矩阵变量的功能

    手动开启:
@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer{
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer){
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        //不移除分号后面的内容。矩阵变量功能就可以生效
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}
    原理:对于路径的处理,UrlPathHelper进行解析

    removeSemicolonContent(移除分号内容)支持矩阵变量的
1. **参数处理原理**
    - HandlerMapping中找到能处理请求的Handler(Controller.method())
    - 为当前Handler找一个适配器HandlerAdapter;RequestMappingHandlerAdapter
    - 当前解析器是否支持解析这种参数
    - 支持就调用res
    1. HandlerAdapter
0 - 支持方法上标注@RequestMapping注解的适配器
RequestMappingHandlerAdapter
1 - 支持函数式编程的适配器
HandlerFunctionAdapter
    2. 目标方法
//(1)Actually invoke the handler.
//DispatcherServlet -- doDispatch
mv = ha.handle(processedRequest,response,mappedHandler.getHandler());

//(2)调用目标方法
mav = invokeHandlerMethod(request,response,handlerMethod);

//(3)真正执行目标方法
Object returnValue = invokeForRequest(webRequest,mavContainer,providedArgs); //获取方法参数值
Object[] args = getMethodArgumentValues(request,mavContainer,providedArgs);
    3. 参数解析器HandlerMethodArgumentResolver:确定将要执行的目标方法的每一个参数的值是什么,SpringMVC目标方法能写多少种参数类型。取决于参数解析器
    4. 返回值解析器
    5. 如何确定目标方法每一个参数的值
        - 挨个判断所有参数解析器哪个支持解析这个参数
        - 解析这个参数的值 
    1. 目标方法执行完成

        将所有的数据都放在ModelAndViewContainer;包含要去的页面地址View,还包含Model数据。
Map<String,Object> map,Model model,HttpServletRequest request 都是可以给request域中放数据

可以取出:
request.getAttribute();
posted @ 2022-01-01 15:47  ArosyCat  阅读(49)  评论(0编辑  收藏  举报