请求处理流程:
从jdk的HttpServlet到达DispatcherServlet类的doDIspatch()方法的过程如下:
具体的代码可以参考:https://blog.csdn.net/zknxx/article/details/75194820
现在我们从doDispatch()方法开始解析请求处理的过程:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//1.检查是否是文件上传的请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//2.取得处理当前请求的Controller,也就是Handler 【★】
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) { //如果为空,直接返回404
noHandlerFound(processedRequest, response);
return;
}
//3.获取处理请求的处理器适配器 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//处理 last-modified请求头
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (!mappedHandler.applyPreHandle(processedRequest, response)) { //4.调用执行器链中的拦截器
return;
}
//5. 实际处理器处理请求,返回结果视图对象 【★】
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//结果视图对象的处理
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
}
1.checkMultipart()
检查他是否是上传请求:
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
}
else if (hasMultipartException(request)) {
}
else {
try {
return this.multipartResolver.resolveMultipart(request); //【调用解析】
}
}
return request;
}
该代码检查请求是否上传了文件,如果没有直接返回原始请求,如果具有请求文件,那么需要调用解析器,进行解析,这里存在两个安全判断,一个是解析器是否为空,解析器必须我们手动配置一个实现类,解析类比如:CommonsMultipartResolver类的解析方法:
public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException {
Assert.notNull(request, "Request must not be null");
if (this.resolveLazily) { //是不是延迟解析文件,默认是false
//产生一个新的request请求
return new DefaultMultipartHttpServletRequest(request) {
@Override
protected void initializeMultipart() {
MultipartParsingResult parsingResult = parseRequest(request); //解析
//从解析结果中获取 结构,注入到new的request中
setMultipartFiles(parsingResult.getMultipartFiles());
setMultipartParameters(parsingResult.getMultipartParameters());
setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes());
}
};
}
else { //与方面功能相同
MultipartParsingResult parsingResult = parseRequest(request);
return new DefaultMultipartHttpServletRequest(request, parsingResult.getMultipartFiles(),
parsingResult.getMultipartParameters(), parsingResult.getMultipartParameterContentTypes());
}
}
2.getHandler(processedRequest)
获取当前请求对应的处理类,返回的是请求处理链
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) { //找到了就退出
HandlerExecutionChain handler = hm.getHandler(request);//【入】
if (handler != null) {
return handler;
}
}
}
return null;
}
紧接着,跟入getHandler()方法,位于handlerMapping的父类AbstractHandlerMapping中:
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//子类实现,一个是AbstractHandlerMethodMapping一个是 method换成url
Object handler = getHandlerInternal(request); //【★】
if (handler == null) {//为找到,使用默认的处理类
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//包装为 执行器链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) { //是不是core请求,core是跨域请求
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
具体的getHandler()稍显复杂,这里我们先不叙述,另开一节,在这个时候拿到了Handler,就调用getHandlerExecutionChain()方法,将Handler包装成执行器链
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//强制转换 or 封装
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) { //遍历
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor()); //添加到执行链中
}
}
else {
chain.addInterceptor(interceptor); //直接添加
}
}
return chain;
}
回到doDispatch()方法
3.getHandlerAdapter()
获取适配器,直接遍历,匹配成功直接返回
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter ha : this.handlerAdapters) {
if (ha.supports(handler)) {
return ha;
}
}
}
}
4.appliyPreHandler()
执行器链的拦截方法调用,位于HandlerExecutionChain类中
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
5.ha.handle()
ha是handlerAdapter类, 实际请求处理,返回视图结果,它的实现类很多,走AbstractHandlerMethodAdapter类,最后来到RequestMappingHandlerAdapter类的handleInternal()方法:
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod); //【入】
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
此方法,深入内容很多,这里先暂停
6.processDispatchResult()
处理最后结果
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
//存在异常,返回异常界面
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response); //解析页面
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
//调用拦截器的afterCompletion方法
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
到这里,整个处理流程介绍完毕,还有许多细节的地方需要补充,比如请求的url如何和我们书写的controller类的method进行对应等等。