⽹络
快⼿ Java ⾯试
有同学拿到腾讯和快⼿的 offer ,本以为腾讯会⽐快⼿开的⾼,结果最 后快⼿开的总包接近 50w ,
超过了腾讯给他开的薪资,真是没想到快⼿也开这么⾼啊。
不过,这个同学开奖的情况,是属于快⼿的 ssp offer 档了,属于最⾼档位的薪资了,这种⼀般是
学历优秀+有⼤⼚实习的同学才能拿到的offer ,并不是每个拿到快⼿的同学都能开到这个级别的
offer 。
我这⾥也给⼤家整理了,25 届快⼿开发岗位的开奖情况:

30k x 16 + 2k x 12 ,同学 bg 985 本科,base 北京
27k x 16 + 2k x 12 ,同学 bg 本科 211 ,base 北京
26.5k x 16 + 2k x 12 ,同学 bg 硕⼠双⼀流,base 北京
25k x 16 + 2k x 12 ,同学 bg 硕⼠ 211 ,base 北京
23k x 16 + 2k x 12 ,同学 bg 本科,base 北京
其中 2k x 12 是房补,整体看下来,快⼿的薪资确实还是⽐较⾼的,校招拿到快⼿offer 同学的年
薪平均有 40w+ 了。
我翻了快⼿去年 24 届的校招薪资,去年⽩菜档是 21k ,今年是 23k ,跟今年的美团⼀样,相⽐去
年都多了 2k 。

⽐较有意思的,之前有流传过⼀个图⽚,快⼿内部校招宣讲的PPT 被拍照流出了,上⾯讲述了24 届
快⼿校招的情况,收到了 16 万简历,录取了 1400 位应届⽣,录取率 0.875% ,从这个哔哩来看,
进⼤⼚的难度不⽐考 985 低
回归正传,这次我们来看看 快⼿校招后端开发的⾯经。主要是针对项⽬涉及的技术栈去问了,同
学项⽬⽤到了组件⽐较多,⽐如微服务组件、mysql 、redis 、es 、kafaka 。
所以针对每个组件都稍微问⼀点,所以⼤家简历所涉及的技术栈⼀定得掌握 ,不是说会使 ⽤就
⾏。

⾯试考察的内容:
⽹络:DNS 、HTTP 、UDP 、Cookie
数据结构与算法:数组、链表、栈、队列
后端:mysql ⽇志、es 倒排索引、kafaka 消息可靠+消息不重复消息
微服务:微服务组件、负载均衡算法、服务熔断、服务降级
spring :ioc 、aop 、循环依赖、事务、spring mvc 流程。
⽹络
Dns 基于什么 协议实现?udp 还是 tcp ?

域名解析的⼯作流程
DNS 基于UDP 协议实现,DNS 使⽤UDP 协议进⾏域名解析和数据传输。
为什么 是udp ?
因为基于UDP 实现DNS 能够提供低 延迟、简单快速、轻量级的特性,更适合DNS 这种需要快速响应
的域名解析服 务。
低延迟: UDP 是⼀种⽆连接的协议,不需要在数据传输前建⽴连接,因此可以减少传输时延,
适合DNS 这种需要快速响应的应⽤场景。
简单快速: UDP 相⽐于TCP 更简单,没有TCP 的连接管理和流量控制机制,传输效率更⾼,适合
DNS 这种需要快速传输数据的场景。
轻量级:UDP 头部较⼩,占⽤较少的⽹络资源,对于⼩型请求和响 应来说更加轻量级,适合
DNS 这种频繁且短⼩的数据交换。
尽管 UDP 存在丢包和数据包损坏的⻛险,但在 DNS 的设计 中,这些⻛险是可以被容忍的。DNS
使⽤了⼀些机制来提⾼可靠性,例如查询超时重传、请求重试、缓存等,以确保数据传输的可靠
性和正确性。
http 的特点是什么 ?
HTTP 具有简单、灵活、易⽤、通⽤等特点,是⼀种⼴泛应⽤于Web 通信的协议。
基于⽂本: HTTP 的消息是以⽂本形式 传输,易于阅读和调试,但相⽐⼆进制协议效率较低。
可扩展性:HTTP 协议本⾝不限制数据的内容和格式,可以通过扩展头部、⽅法等来⽀持新的功
能。
灵活性: HTTP ⽀持不同的数据格式(如HTML 、JSON 、XML 等),适⽤于多种应⽤场景。
⽆状态: 每个请求之间相互独⽴,服务器不会保 留之前请求的状态信息,需要通过其他⼿段
(如Cookies 、Session )来维护状态。
http ⽆状态体现在哪?
HTTP 的⽆状态体现在每个请求之间相互独⽴,服务器不会保 留之前请求的状态信息。每次 客⼾端
向服务器发送请求时,服务器都会独⽴处理该请求,不会记住之前的请求信息或状态。
这意味着服务器⽆法知道两次请求是否来⾃同⼀个客⼾端,也⽆法知道客⼾端的历史状态,需要
通过其他机制(如Cookies 、Session )来维护和管理状态信息。
Cookie 通过在请求和响 应报⽂中写⼊ Cookie 信息来控制客⼾端的状态。
相当于,在客⼾端第 ⼀次请求后,服务器会下发⼀个装有客⼾信息的「⼩贴纸」,后续客⼾端请求
服务器的时候,带上「⼩贴纸」,服务器就能认得了了 ,

Cookie 技术
Cookie 和session 的区别是什么 ?
存储位置:Cookie 存储在客⼾端(浏览器) 中,⽽Session 存储在服务器端。
安全性:由于Cookie 存储在客⼾端,因此容易受到安全攻击,如跨站脚本攻击(XSS )和跨站请
求伪造(CSRF )。⽽Session 存储在服务器端,对客⼾端不可⻅,相对来说更安全。
存储容量:Cookie 的存储容量有限,通常为4KB 左右,⽽Session 的存储容量较⼤,受限于服务
器的配置。
数据结构与算法
链表和数组有什么 区别?
访问效率:数组可以通过索引直接访问任何位 置的元素,访问效率⾼,时间复杂度为O(1) ,⽽
链表需要从头节点开始遍历到⽬标位置,访问效率较低,时间复杂度为O(n) 。
插⼊和删除操作效率:数组插⼊和删除操作可能需要移动其他元素,时间复杂度为O(n) ,⽽链
表只需要修改指针指向,时间复杂度为O(1) 。** 缓存命中率:** 由于数组元素在内存中连续存储,可以提⾼CPU 缓存的命中率,⽽链表节点不
连续存储,可能导致CPU 缓存的命中率较低,频繁的缓存失效会影响性能。
应⽤场景:数组适合静态⼤⼩、频繁访问元素的场景,⽽链表适合动态⼤⼩、频繁插⼊、删除
操作的场景
如何使 ⽤两个 栈实现队列?
使⽤两个 栈实现队列的⽅法如下:
准备两个 栈,分别 称为 stackPush 和 stackPop 。
当需要⼊队时,将元素压⼊ stackPush 栈。
当需要出队时,先判断 stackPop 是否为空,如果不为 空,则直接弹出栈顶元素;如果为空,则
将 stackPush 中的所有元素依次弹出并压⼊ stackPop 中,然后再从 stackPop 中弹出栈顶元素
作为出队元素。
- 当需要查询队⾸元素时,同样需要先将 stackPush 中的元素转移到 stackPop 中,然后取出
stackPop 的栈顶元素但不弹出。
- 通过上述⽅法,可以实现⽤两个 栈来模拟队列的先进先出(FIFO )特性。
这种⽅法的时间复杂度为O(1) 的⼊队操作,均摊时间复杂度为O(1) 的出队和查询队⾸元素操作。以下是使⽤两个 栈实现队列的Java 代码⽰例:
import java.util.Stack;
class MyQueue {
private Stack<Integer> stackPush;
private Stack<Integer> stackPop;
public MyQueue() {
stackPush = new Stack<>();
stackPop = new Stack<>();
}
}
public int pop() {
if (stackPop.isEmpty()) {
while (!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}
public int peek() {
if (stackPop.isEmpty()) {
while (!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.peek();
}
public boolean empty() {
return stackPush.isEmpty() && stackPop.isEmpty();
}
}
// 测试代码
public class Main {
public static void main(String[] args) {
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
System.out.println(queue.peek()); // 输出 1
System.out.println(queue.pop()); // 输出 1
System.out.println(queue.empty()); // 输出 false
}
}后端组件
MySQL 的三⼤⽇志说⼀下,分别 应⽤场景是 什么 ?
MySQL 的三⼤⽇志包括:redolog 、binlog 和undolog 。
redolog :主要⽤于保证事务的持久性(ACID 特性中的D:持久性)。当数据库发⽣故障时,通
过重做⽇志可以将未提交的事务重新执⾏,确保数据的⼀致性。
binlog :⽤于主从 复制、数据恢复和数据备份。⼆进制⽇志记录了所有对数据库的更改操作,
包括数据更新、插⼊、删除等,以便 在主从 复制时同步数据或进⾏数据恢复和备份。
undolog :主要⽤于事 务的回滚操作。当事务执⾏过程中发⽣异常或需要回滚时,回滚⽇志记
录了事 务的操作信 息,可以⽤于撤销事务对数据库的修改,实现事务的原⼦性。
ElasticSearch 如何进⾏全⽂检索的?
主要是利⽤了倒排索引的查询结构,倒排索引是⼀种⽤于快速搜索的数据结构,它将⽂档中的每
个单词与包含该单词的⽂档进⾏关联。通常,倒排索引由单词(terms )和包含这些单词的⽂档
(document )列表组成。
如何理解倒排索引呢?假如现有三份数据⽂档,⽂档的内容如下分别 是:

通过分词器将每个⽂档的内容域拆分成单独的「词词 汇」:

然后再构建从词汇到⽂档ID 的映射,就形成了倒排索引。

当进⾏搜索时,系统只需查找倒排索引中包含搜索关键词的⽂档列表,⽐如⽤⼾输⼊"秋⽔",通过
倒排索引,可以快速的找到含有"秋⽔"的⽂档是id 为 1,2 的⽂档,从⽽达到快速的全⽂检索的⽬
的。
了解过 es 分词器有哪些?
常⻅的分词器如下:
standard 默认分词器, 对单个字符进⾏切分 ,查全率⾼,准确度较低
IK 分词器 ik_max_word :查全率与准确度较⾼,性能也⾼,是业务中普遍采⽤的中⽂分词器
IK 分词器 ik_smart :切分 ⼒度较⼤,准确度与查全率不⾼,但是查询性能较⾼
Smart Chinese 分词器:查全率与准确率性能较⾼
hanlp 中⽂分词器:切分 ⼒度较⼤,准确度与查全率不⾼,但是查询性能较⾼
Pinyin 分词器:针对汉字拼⾳进⾏的分词器, 与上 ⾯介绍的分词器稍有不同,在⽤拼⾳进⾏查
询时查全率准确度较⾼

分词器⽐较
Kafka 如何保 证消息不丢 失?
使⽤⼀个消息队列,其实就分为三 ⼤块:⽣产者、中间件、消费者,所以要保证消息就是保证三个环节都不能丢失数据。

图⽚
消息⽣产阶段:⽣产者会不会丢消息,取决于⽣产者对于异常情况的处理是否合 理。从消息被
⽣产出来,然后提交给 MQ 的过程中,只要能正常收到 ( MQ 中间件) 的 ack 确认响应,就
表⽰发送成功,所以只要处理好返回值和异常,如果返回异常则进⾏消息重发,那么这个阶段
是不会出现消息丢失的。
消息存储阶段:Kafka 在使⽤时是 部署⼀个集群,⽣产者在发布消息时,队列中间件通常会写
「多个节点」,也就是有多个副本,这样⼀来,即便其中⼀个节点挂了,也能保证集群的数据不丢失。
消息消费阶段:消费者接收消息+消息处理之后,才回复 ack 的话,那么消息阶段的消息不会丢
失。不能收到消息就回 ack ,否则可能消息处理中途挂掉 了,消息就丢失了。
Kafka 如何保 证消息不重复消费?
导致重复消费的原因可能出现在⽣产者,也可能出现在 MQ 或 消费者。
这⾥说的重复消费问题是指同⼀个数据被执⾏了两 次,不单单 指 MQ 中⼀条消息被消费了两 次,
也可能是 MQ 中存在两条⼀模⼀样的消费。
⽣产者:⽣产者可能会重复推送⼀条数据到 MQ 中,为什么 会出现这种情况呢?也许是⼀个
Controller 接⼝被重复调⽤了 2 次,没有做接⼝幂等性导致的;也可能是推送消息到 MQ 时响
应⽐较慢,⽣产者的重试机制导致再次推送了⼀次消息。
MQ :在消费者消费完⼀条数据响应 ack 信号消费成功时,MQ 突然挂了,导致 MQ 以为消费
者还未消费该条数据,MQ 恢复后再次推送了该条消息,导致了重复消费。
消费者:消费者已经消费完了⼀条消息,正准备但是还未给 MQ 发送 ack 信号时,此时消费者
挂了,服务重启后 MQ 以为消费者还没有消费该消息,再次推送了该条消息。
消费者怎么解决重复消费问题呢?这⾥提供两种⽅法:
状态判断法:消费者消费数据后把消费数据记录在 redis 中,下次消费时先到 redis 中查看是否
存在该消息,存在则表⽰消息已经消费过,直接丢弃消息。
业务判 断法:通常数据消费后都需要插⼊到数据库中,使⽤数据库的唯⼀性约束防⽌重复消
费。每次 消费直接尝试插⼊数据,如果提⽰唯⼀性字段重复,则直接丢失消息。⼀般都是通过这个业 务判 断的⽅法就可以简单⾼效地避免消息的重复处 理了。
微服务
你的项⽬⽤到了哪些微服务组件?
Eureka :服务注册与发现组件,⽤于实现微服务架构 中的服务注册和发现。
Ribbon :负载均衡组件,⽤于在客⼾端实现负载均衡,提⾼系统的可⽤性和性能。
Feign :声明式的 HTTP 客⼾端组件,简化了服务之间的调⽤和通信。
Hystrix :熔断器组件,⽤于防⽌微服务间的故障蔓延,提⾼系统的容错能⼒。
Zuul :API ⽹关组件,⽤于统⼀访问⼊⼝、路由请求和过滤请求,提⾼系统的安全性和可 维护
性。
Config :配置中⼼组件,⽤于集中管理微服务的配置信息,实现配置的动态刷新。
负载均衡有哪些算法?
简单轮询:将请求按顺序分发给后端服务器上,不关⼼服务器当前的状态,⽐如后端服务器的
性能、当前的负载。
加权轮询:根据服务器⾃⾝的性能给服务器设置不同的权重,将请求按顺序和权重分发给后端
服务器, 可以让性能⾼的机器处理更多的请求
简单随机:将请求随机分发给后端服务器上,请求越多,各个服务器接收到的请求越平均
加权随机:根据服务器⾃⾝的性能给服务器设置不同的权重,将请求按各个服务器的权重随机
分发给后端服务器
⼀致性哈希:根据请求的客⼾端 ip 、或请求参数通过哈希算法得到⼀个数值,利⽤该数值取模
映射出对应的后端服务器, 这样能保证同⼀个客⼾端或相同参数的请求每次 都使⽤同⼀台服务
器
最⼩活跃数:统计每台服务器上当前正在处理的请求数,也就是请求活跃数,将请求分发给活
跃数最少的后台 服务器
如何实现⼀直均衡给⼀个⽤⼾?
可以通过「⼀致性哈希算法」来实现,根据请求的客⼾端 ip 、或请求参数通过哈希算法得到⼀个
数值,利⽤该数值取模映射出对应的后端服务器, 这样能保证同⼀个客⼾端或相同参数的请求每次都使⽤同⼀台服务器。
介绍⼀下服务熔断
服务熔断是应对微服务雪崩效应的⼀种链路保护机制,类似股市、保险丝。
⽐如说,微服务之间的数据交互 是通过远 程调⽤来完成的。服务A调⽤服务,服务B调⽤服务c,某
⼀时间链路上对服务C的调⽤响应时间过⻓或者服务C不可⽤,随着时间的增⻓,对服务C的调⽤也
越来越多,然后服务C崩溃了,但是链路调⽤还在,对服务B的调⽤也在持续增多,然后服务B崩
溃,随之A也崩溃,导致雪崩效应。
服务熔断是应对雪崩效应的⼀种微服务链路保护机制。例如在⾼压电路中,如果某 个地⽅的电压
过⾼,熔断器就会熔断,对电路进⾏保护。同样,在微服务架构 中,熔断机制也是起着类似的作
⽤。当调⽤链路的某个微服务不可⽤或者响应时间太⻓时,会进⾏服务熔断,不再有该节点微服
务的调⽤,快速返回错误的响应信息。当检测到该节点微服务调⽤响应正常后,恢复调⽤链路。
所以,服务熔断的作⽤类似于我们家⽤的保险丝,当某服 务出 现不可⽤或响应超时的情况时,为了防⽌整个系统出现雪崩,暂时 停⽌对该服务的调⽤。
在Spring Cloud 框架⾥,熔断机制通过Hystrix 实现。Hystrix 会监控微服务间调⽤的状况,当失败的
调⽤到⼀定阈值,缺省是5秒内20 次调⽤失败,就会启动熔断机制。
介绍⼀下服务降级
服务降级⼀般是指在服务器压⼒剧增的时候,根据实际业务使⽤情况以及流量,对⼀些服务和⻚
⾯有策略的不处理或者⽤⼀种简单的⽅式进⾏处理,从⽽释放服务器资源的资源以保 证核⼼业务
的正常⾼效运⾏。
服务器的资源是有限的,⽽请求是⽆限的。在⽤⼾使⽤即并发⾼峰期,会影响整体服务的性能,
严重的话会导致宕机,以⾄于某些重要服务不可⽤。故⾼峰期为了 保证核⼼功能服务的可⽤性,
就需要对某些服务降级处理。可以理解为舍⼩保⼤
服务降级是从整个系统的负荷情况出发和考虑的,对某些负荷会⽐较⾼的情况,为了 预防某些功
能(业务场景)出现负荷过载 或者响应慢的情况,在其内 部暂时 舍弃对⼀些⾮核⼼的接⼝和数据
的请求,⽽直接返回⼀个提前准备好 的fallback (退路)错误处理信息。这样,虽然提供的是⼀个
有损的服务,但却保证了整个系统的稳定性和可 ⽤性。
Spring
Spring 的IOC 介绍⼀下
IOC :Inversion Of Control ,即控制反转,是⼀种设计 思想。在传统的 Java SE 程序设计 中,我们直接在对象内部通 过 new 的⽅式来创建对象,是程序主动创 建依赖对象;

⽽在Spring 程序设计 中,IOC 是有专⻔的容器去控制对象。

所谓控制就是对象的创建、初始化、销毁。
创建对象:原来是 new ⼀个,现在是由 Spring 容器创建。
初始化对象:原来是对象⾃⼰通过构造器或者 setter ⽅法给依赖的对象赋值,现在是由 Spring
容器⾃动注⼊。
销毁对象:原来是直接给对象赋值 null 或做⼀些销毁操作,现在是 Spring 容器管理⽣命周 期负责销毁对象。
总结:IOC 解决了繁琐的对象⽣命周 期的操作,解耦了我们的代码。
所谓反转:其实是反转的控制权,前⾯提到是由 Spring 来控制对象的⽣命周 期,那么对象的控制
就完全脱离了我们的控制,控制权交给了 Spring 。这个反转是指:我们由对象的控制者变成了
IOC 的被动控制者。
为什么 依赖注⼊不适合使⽤字段注⼊?
字段注⼊可能引起的三个 问题:
对象的外部可⻅性
可能导致循环依赖
⽆法设置注⼊的对象为final ,也⽆法注 ⼊静态变量
⾸先来看字段注⼊
@RestController
public class TestHandleController {
@Autowired
TestHandleService testHandleService;
public void helloTestService(){
testHandleService.hello();
}
}字段注⼊的⾮常的简便,通过以上代码我们就可以轻松的使⽤TestHandleService 类,但是如果变
成下⾯这样呢:
TestHandleController testHandle = new TestHandleController();
testHandle.helloTestService();这样执⾏结果为空指针异常,这就是字段注⼊的第⼀个问题:** 对象的外部可⻅性,** ⽆法在容器外部实例化TestHandleService (例如在测试类中⽆法注 ⼊该组件),类和容器的耦合度过⾼,⽆法脱离容器访问⽬标对象。
接下来看第⼆段代码:
public class TestA(){
@Autowired
private TestB testB;
}
public class TestB(){
@Autowired
private TestA testA;
}这段代码在idea 中不 会报任何 错误,但是当你启动项⽬时会发现报错,⼤致意思是:创建Bean 失
败,原因是当前Bean 已经作为循环引⽤的⼀部分注⼊到了其他Bean 中。
这就是字段注⼊的第⼆个问题:可能导致循环依赖
字段注⼊还有第三个 问题:** ⽆法设置注⼊的对象为final ,也⽆法注 ⼊静态变量,** 原因是变量必
须在类实例化进⾏初始化。
Spring 的aop 介绍⼀下
Spring AOP 是Spring 框架中的⼀个重要模块,⽤于实现⾯向切⾯编程。
我们知道,Java 就是⼀⻔⾯向对象编程的语⾔,在 OOP 中最⼩的单元就是“Class 对象”,但是在
AOP 中最⼩的单元是“切⾯”。⼀个“切⾯”可以包含很多种类型和对象,对它们进⾏模块化管理,例
如事务管理。
在⾯向切⾯编程的思想⾥⾯,把功能分为两 种
核⼼业务:登陆、注册、增、删、改、查、都叫核⼼业务
周边功能:⽇志、事务管理这些次要的为周边业务
在⾯向切⾯编程中,核⼼业务功 能和周 边功能是分别 独⽴进⾏开发,两者不是耦合的,然后把切
⾯功能和核⼼业务功 能 "编织" 在⼀起,这就叫AOP 。
AOP 能够将那些与业 务⽆关,却为业 务模块所共同调⽤的逻辑或责任(例如事务处理、⽇志管
理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来 的
可拓展性和可 维护性。
在 AOP 中有以下⼏个概念:
AspectJ :切⾯,只是⼀个概念,没有具体的接⼝或类与之 对应,是 Join point ,Advice 和
Pointcut 的⼀个统称。
Join point :连接点,指程序执⾏过程中的⼀个点,例如⽅法调⽤、异常处理等。在 Spring AOP 中,仅⽀持⽅法级别的连接点。
Advice :通知,即我们定义的⼀个切⾯中的横切逻辑,有“around” ,“before” 和“after” 三种类
型。在很多的 AOP 实现框架中,Advice 通常作为⼀个拦截 器, 也可以包含许多个拦截 器作为⼀
条链路围绕着 Join point 进⾏处理。
Pointcut :切点,⽤于匹配连接点,⼀个 AspectJ 中包含哪些 Join point 需要由 Pointcut 进⾏筛
选。
Introduction :引介,让⼀个切⾯可以声明被通知的对象实现任何 他们没有真正实现的额外的接
⼝。例如可以让⼀个代理对象代理两个 ⽬标类。
Weaving :织⼊,在有了连接点、切点、通知以及切⾯,如何将它们应⽤到程序中呢?没错,
就是织⼊,在切点的引导下,将通知逻辑插⼊到⽬标⽅法上,使得我们的通知逻辑在⽅法调⽤
时得以执⾏。
AOP proxy :AOP 代理,指在 AOP 实现框架中实现切⾯协议的对象。在 Spring AOP 中有两种
代理,分别 是 JDK 动态代理和 CGLIB 动态代理。
Target object :⽬标对象,就是被代理的对象。
Spring AOP 是基于 JDK 动态代理和 Cglib 提升实现的,两种代理⽅式都属于运⾏时的⼀个⽅式,
所以它没有编译时的⼀个处理,那么因此 Spring 是通过 Java 代码实现的。
Spring 的事务,使⽤this 调⽤是否⽣效?
不能⽣效。
因为Spring 事务是通过代理对象来控制的,只有通过代理对象的⽅法调⽤才会应⽤事务管理的相关
规则。当使⽤ this 直接调⽤时,是绕过了Spring 的代理机制,因此不会应⽤事务设置。
Spring MVC 的⼯作流程描述⼀下

Spring MVC 的⼯作流程如下:
⽤⼾发送请求⾄前端控制器DispatcherServlet
DispatcherServlet 收到请求调⽤处理器映射器HandlerMapping 。
3. 处理器映射器根据请求url 找到具体的处理器, ⽣成处理器执⾏链HandlerExecutionChain( 包括处
理器对象和处理器拦截 器)⼀并返回给DispatcherServlet 。- DispatcherServlet 根据处理器Handler 获取处理器适配器HandlerAdapter 执⾏HandlerAdapter 处
理⼀系列的操作,如:参数封装,数据格式转换,数据验证等操作
5. 执⾏处理器Handler(Controller ,也叫⻚⾯控制器)。Handler 执⾏完成返回ModelAndView
HandlerAdapter 将Handler 执⾏结果ModelAndView 返回到DispatcherServlet
DispatcherServlet 将ModelAndView 传给ViewReslover 视图解析器
ViewReslover 解析后返回具体View
DispatcherServlet 对View 进⾏渲染视图(即将模型数据model 填充⾄视图中)。
DispatcherServlet 响应⽤⼾。
