spring mvc请求处理完整流程详解
一、流程文字描述
当一个http请求到达服务器后,会经历以下流程:
filter链处理(入口)
- 请求首先经过filter链
- 每个filter按照定义的顺序执行dofilter方法的前置处理
- filter通过调用chain.dofilter()将请求传递给下一个filter
dispatcherservlet接收请求
- 所有filter处理完后,请求到达dispatcherservlet
- dispatcherservlet作为前端控制器,统一处理所有请求
寻找handler
- dispatcherservlet调用gethandler方法
- 遍历所有handlermapping,找到与当前url匹配的handler
- 找到handler后,把handler和对应的拦截器封装成handlerexecutionchain对象
获取handleradapter
- 根据handler的类型,遍历所有handleradapter
- 找到支持该handler类型的handleradapter
- handleradapter用于调用handler并处理参数、返回值等
拦截器前置处理
- 按顺序调用handlerexecutionchain中所有拦截器的prehandle方法
- 如果任一拦截器的prehandle返回false,则中断请求处理
- 中断时会触发已执行的拦截器的aftercompletion方法
handler处理请求
- 通过handleradapter调用handler(controller方法)
- handleradapter负责参数解析、类型转换
- handler执行业务逻辑,返回处理结果
拦截器后置处理
- handler执行完成后,按逆序调用所有拦截器的posthandle方法
- 此时视图尚未渲染
视图渲染
- 根据handler返回的结果进行视图渲染
- 如果是@restcontroller,将返回值转换为json/xml等格式
- 如果是传统@controller,解析视图名称并渲染视图
拦截器完成处理
- 视图渲染完成后,按逆序调用所有拦截器的aftercompletion方法
- 无论过程中是否有异常,都会执行aftercompletion
filter链处理(出口)
- 响应会按照与处理请求相反的顺序经过filter链
- 每个filter执行dofilter方法的后置处理
- 最终响应返回给客户端
二、关键组件详解
2.1 handlermapping
// 核心数据结构
public class requestmappinghandlermapping {
// 保存url与处理器方法的映射关系
private final map<requestmappinginfo, handlermethod> mappinglookup;
}
// 映射示例
mappinglookup = {
requestmappinginfo{
patterns=/users/{id}, // url模式
methods=get, // http方法
params=[], // 请求参数
headers=[] // 请求头
} -> handlermethod{usercontroller.getuser()}
}2.2 handlerexecutionchain
public class handlerexecutionchain {
// handler本身(如controller的方法)
private final object handler;
// 与handler关联的拦截器列表
private list<handlerinterceptor> interceptors;
}2.3 handleradapter
// 处理@requestmapping注解的方法
public class requestmappinghandleradapter implements handleradapter {
public modelandview handle(request, response, handler) {
// 1. 解析请求参数
object[] args = resolveparameters(request, handler);
// 2. 调用controller方法
object returnvalue = invokemethod(handler, args);
// 3. 处理返回值
return processreturnvalue(returnvalue);
}
}2.4 视图渲染
// 1. @restcontroller(json渲染)
@getmapping("/api/user")
public user getuser() {
return user; // 自动转换为json
}
// 2. @controller(html渲染)
@getmapping("/user")
public string user(model model) {
model.addattribute("user", user);
return "userview"; // 解析为具体视图
}三、拦截器执行流程
3.1 拦截器定义
public class loginterceptor implements handlerinterceptor {
@override
public boolean prehandle(request, response, handler) {
system.out.println("loginterceptor - prehandle");
return true;
}
@override
public void posthandle(request, response, handler, mv) {
system.out.println("loginterceptor - posthandle");
}
@override
public void aftercompletion(request, response, handler, ex) {
system.out.println("loginterceptor - aftercompletion");
}
}3.2 执行顺序示例
filter1 - 请求处理
filter2 - 请求处理
loginterceptor - prehandle
securityinterceptor - prehandle
controller方法执行
securityinterceptor - posthandle
loginterceptor - posthandle
视图渲染
securityinterceptor - aftercompletion
loginterceptor - aftercompletion
filter2 - 响应处理
filter1 - 响应处理3.3 拦截器调用过程
// 1. prehandle调用(正序)
for (handlerinterceptor interceptor : interceptors) {
if (!interceptor.prehandle(request, response, handler)) {
triggeraftercompletion(request, response, handler, null);
return false;
}
}
// 2. posthandle调用(逆序)
for (int i = interceptors.length - 1; i >= 0; i--) {
interceptors[i].posthandle(requestresponse, handler, mv);
}
// 3. aftercompletion调用(逆序)
for (int i = interceptors.length - 1; i >= 0; i--) {
interceptors[i].aftercompletion(request, response, handler, ex);
}到此这篇关于spring mvc核心组件与请求处理流程的文章就介绍到这了,更多相关spring mvc请求处理内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论