Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 手写Spring

  • SSM

  • SpringBoot

    • 入门
    • 注解
    • 源码分析
      • @SpringBootApplication
      • @RestController
      • 请求参数处理
      • 视图解析
      • 拦截器
    • 核心功能
    • 问题记录
  • JavaWeb

  • Spring
  • SpringBoot
phan
2023-05-15
目录

源码分析

# 源码分析

# @SpringBootApplication

  • @SpringBootConfiguration:底层实际上是一个@Configuration

  • @ComponentScan:包扫描

  • @EnableAutoConfiguration:根据每个包下面的metaInfo自动导入自动配置类=>个别配置类注解了条件生效条件,满足IOC中存在某个Bean才生效=>给容器中装配组件。

    使用@condition注解实现给bean对象修改id

    用户若要使用自己的配置,则直接@Bean重新配置一个方法替换底层组件=>然后查看这个组件的配置类xxxProperties(EnableConfigurationProperties可以看到),根据配置类的prefix+类属性名修改

# @RestController

  • SpringMVC 默认实现了HiddenHttpMethodFilter来支持RestFul风格,SpringBoot使用时首先需要在yaml中开启filter功能(默认不开启),然后在前端form表单input添加一个隐藏变量name="_method",然后填写真正的请求方式value="delete"

    spring:
      mvc:
        hiddenmethod:
          filter:
            enabled: true
    ------------------
    <form method="post">
    <input type="hidden" name="_method" value="delete">
    
    1
    2
    3
    4
    5
    6
    7
    8

    表单发送请求(只有表单请求才会转换)流程:被过滤器拦截—>检查是否是post方式—>获取_method值,然后重新包装一个RequestWrapper对象(实现了HttpServletRequest接口),传入_method重写了getMethod方法,包装模式—>过滤器放行这个新的HttpServletRequest(wrapper)。

  • 请求映射原理

    handleMapping(RequestMapping,WelcomeMapping...),遍历每个handleMapping看哪个能处理(根据里面的一个配置中心,里面保存我们写过的映射规则)。

    DispatcherServlet.doDistpatch:初始化各种参数—>从handleMappings中getHandler找能处理的映射—>然后找对应的处理方法,先根据request方法的url路径找,再根据method找,最终找到一个对应的处理方法(handler)。

# 请求参数处理

找到handle后,找到对应的handleAdapter适配器——>执行目标方法(使用参数解析器确定要执行的目标方法每一个参数是什么—>反射doinvoke调用处理方法)

  • 参数解析器:遍历所有参数解析器,找到支持解析该参数的参数解析器(实际上就是看是不是标了对应的注解),把对应参数和解析器丢到缓存中,然后开始解析。
  • 参数解析过程:根据参数名,调用servlet一些原生的方法,比如request.getAttribute
  • 具体参数类型分析:
    • model:model的addAttribute最终相当于底层request.setAttribute往请求域中放数据。
    • VIew:视图名

# 视图解析

render(mv)页面渲染:

  • 首先根据View的名字,遍历所有view解析器,看哪一个解析器能根据当前返回值得到View对象

    • forward开头,则底层调用response.getRequestDispatcher转发

    • redirect开头,render底层就是重定向,new RedirectView()

    • 普通字符串开头,则返回new ThymeleafView()

  • 然后调用这个视图对象View自己定义的render进行页面渲染(底层原生servlet方法)。

# 拦截器

  1. 根据当前请求找到handlerExecutionChain处理器执行链,其中这个处理器请求链对象包含①handler对象,里面指明了由哪个方法处理当前请求②InterceptorList拦截器链包含所有拦截器

    mappedHandler = getHandler(processedRequest);
    
    1

    image-20221214100231957

  2. 根据handler获取目标方法的适配器

    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    1
  3. 在通过handler适配器调用执行handler方法(controller方法)之前,会执行拦截器调用applyPreHandle方法,如果返回false,则直接跳出doDIspatcher方法,后面的handler不执行。

    • applyPreHandle:先遍历所有拦截器,顺序执行prehandler,返回true放行,则继续执行下一个拦截器的prehandler方法;如果prehandler返回false,则直接触发执行triggerAfterCompletion的方法,执行完后返回false。
    • afterCompletion:从当前没有放行的拦截器开始,倒序(i--)执行所有已经执行prehandler拦截器的afterComletion方法
    if (!mappedHandler.applyPreHandle(processedRequest, response)) 
    return;
    
    1
    2
  4. 所有拦截器的prehandler方法都正常放行,ha.handler处理器方法执行完之后,调用applyPostHandle**倒序执行所有拦截器postHandler**方法(遍历拦截器列表i--),若有某个拦截器不放行,则处理规则同上。

    mappedHandler.applyPostHandle(processedRequest, response, mv);
    
    1
  5. 执行render渲染完页面后,触发执行triggerAfterCompletion。

整个流程如下:

image-20221214103921153

编辑 (opens new window)
#Spring
上次更新: 2023/12/15, 15:49:57
注解
核心功能

← 注解 核心功能→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式