SpringMVC源码剖析-SpringMVC执行流程

SpringMVC源码剖析-SpringMVC执行流程,第1张

}

}

return null;

}

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

//找到Handler

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 = getApplicationContext().getBean(handlerName);

}

//把handler封装成HandlerExecutionChain ,其中还包括了拦截器的封装

return getHandlerExecutionChain(handler, request);

}

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {

//创建一个Handler执行链对象

HandlerExecutionChain chain =

(handler instanceof HandlerExecutionChain) ?

(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);

//添加拦截器到HandlerExecutionChain

chain.addInterceptors(getAdaptedInterceptors());

String lookupPath = urlPathHelper.getLookupPathForRequest(request);

for (MappedInterceptor mappedInterceptor : mappedInterceptors) {

if (mappedInterceptor.matches(lookupPath, pathMatcher)) {

chain.addInterceptor(mappedInterceptor.getInterceptor());

}

}

return chain;

}

getHandler方法最终会走到org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal ,该方法就是根据request查找一个HandlerMethod

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {

//拿到请求的路径

String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);

if (logger.isDebugEnabled()) {

logger.debug("Looking up handler method for path " + lookupPath);

}

//根据请求路径,找到匹配的HandlerMethod

HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);

if (logger.isDebugEnabled()) {

if (handlerMethod != null) {

logger.debug(“Returning handler method [” + handlerMethod + “]”);

}

else {

logger.debug(“Did not find handler method for [” + lookupPath + “]”);

}

}

return (handlerMethod != null) ? handlerMethod.createWithResolvedBean() : null;

}

这里在拿到请求的路径,根据请求路径,找到匹配的HandlerMethod,再往里面走

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {

//matches是requestMppingInfo和HandlerMethod的匹配器集合

List matches = new ArrayList();

//根据请求的路径,从 this.urlMap中拿到RequestMappingInfo,

//urlMap 是一个LinkedHashMap,存储了Url路径和RequestMappingInfo的映射关系

List directPathMatches = this.urlMap.get(lookupPath);

if (directPathMatches != null) {

addMatchingMappings(directPathMatches, matches, request);

}

if (matches.isEmpty()) {

// No choice but to go through all mappings

//如果从urlMap中没有找到RequestMappingInfo,那么matches就是空的

//根据Request对象封装一个requestMppingInfo,然后handlerMethods的keySet中拿到对应的HandlerMethod,(会根据Request中的URL,请求方式,参数params,请求头headers,consumes,produces去匹配handlerMethods.keySet中的requestMppingInfo)

//然后从handlerMethods根据requestMppingInfo拿到HandlerMethod

//把requestMppingInfo和HandlerMethod封装成Match添加到matches中

addMatchingMappings(this.handlerMethods.keySet(), matches, request);

}

if (!matches.isEmpty()) {

Comparator comparator = new MatchComparator(getMappingComparator(request));

Collections.sort(matches, comparator);

if (logger.isTraceEnabled()) {

logger.trace(“Found " + matches.size() + " matching mapping(s) for [” + lookupPath + "] : " + matches);

}

Match bestMatch = matches.get(0);

if (matches.size() > 1) {

Match secondBestMatch = matches.get(1);

if (comparator.compare(bestMatch, secondBestMatch) == 0) {

Method m1 = bestMatch.handlerMethod.getMethod();

Method m2 = secondBestMatch.handlerMethod.getMethod();

throw new IllegalStateException(

“Ambiguous handler methods mapped for HTTP path '” + request.getRequestURL() + “': {” +

m1 + ", " + m2 + “}”);

}

}

handleMatch(bestMatch.mapping, lookupPath, request);

//从bestMatch拿到Handler

return bestMatch.handlerMethod;

}

else {

return handleNoMatch(handlerMethods.keySet(), lookupPath, request);

}

}

这里出现了两个集合,urlMap 和 handlerMethods ,urlMap 存储的是url和RequestMappingInfo的映射关系,handlerMethods 存储的是RequestMappingInfo和HandlerMethod的关系。

这里的代码比较复杂,先是从 urlMap中根据url拿到RequestMappingInfo集合然后,如果没获取到即:matches.isEmpty()就会调用addMatchingMappings去处理,有兴趣自己去断点一下,该方法的大致流程如下

  1. 根据request中的url,method,参数params,请求头headers,consumes,produces去创建一个requestMppingInfo

  2. 然后根据requestMppingInfo为key从handlerMethods拿到HandlerMethod封装成Match 对象添加到matches集合中

  3. 从Match 中拿到当前请求对应的HandlerMethod

那么这里的handlerMethods和urlMap 是哪儿来的?

以:RequestMappingHandlerMapping为例在其父类AbstractHandlerMethodMapping中维护了一个 Map handlerMethods = new LinkedHashMap()该集合中装的就是RequestMappingInfo和HandlerMethod的映射关系,RequestMappingInfo是的RequstMapping的封装,HandlerMethod是对Conroller中方法的封装。初始化流程如下

  1. AbstractHandlerMethodMapping它实现了InitializingBean接口,在RequestMappingHandlerMapping初始化的使用会触发AbstractHandlerMethodMapping#afterPropertiesSet方法

  2. 该方法中会调用AbstractHandlerMethodMapping#initHandlerMethods 初始化HandlerMethod,

其实就是从容器中拿到所有标识了@Controller或者@RequestMapping注解的Bean,也就是controller,然后拿到其中的所有method封装成HandlerMethod对象,然后再拿到method上RequestMapping信息封装成RquestMappingInfo对象,再把RquestMappingInfo和HandlerMethod以前者为key,后置为value注册到handlerMethods集合中。

  1. 把Url路径和RequestMappingInfo的映射关系存储到AbstractHandlerMethodMapping类中的 MultiValueMap urlMap = new LinkedMultiValueMap()集合中

这个是在MappingHandlerMapping初始化的时候就把HandlerMethod封装好存储在了handlerMethods 集合中,当请求过来就根据Request去匹配一个RequestMappingInfo,然后再找到对应的HandlerMethod返回。

[](()查找HandlerAdapter

查找HandlerAdapter在org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter中,

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {

for (HandlerAdapter ha : this.handlerAdapters) {

if (logger.isTraceEnabled()) {

logger.trace(“Testing handler adapter [” + ha + “]”);

}

if (ha.supports(handler)) {

return ha;

}

}

throw new ServletException(“No adapter for handler [” + handler +

“]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler”);

}

// org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports

public final boolean supports(Object handler) {

return handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler);

}

从handlerAdapters循环所有的HandlerAdapter,调用supports方法判断是否支持该Handler,如果支持就返回HandlerAdapter

[](()调用拦截器的preHandle

代码在org.springframework.web.servlet.HandlerExecutionChain#applyPreHandle方法中,在HandlerExecutionChain维护了一个HandlerInterceptor[] interceptors,存储了所有的拦截器。源码如下

public class HandlerExecutionChain {

private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);

private final Object handler;

//拦截器数组

private HandlerInterceptor[] interceptors;

…省略…

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {

if (getInterceptors() != null) {

for (int i = 0; i < getInterceptors().length; i++) {

//拿到所有的拦截器,调用preHandle方法

HandlerInterceptor interceptor = getInterceptors()[i];

if (!interceptor.preHandle(request, response, this.handler)) {

//如果拦截器返回false,即不放行就执行拦截器的afterCompletion方法

triggerAfterCompletion(request, response, null);

return false;

}

this.interceptorIndex = i;

}

}

return true;

}

[](()调用HandlerAdatapter

找到HanlderMethod之后执行拦截器的preHandler方法,然后执行HandlerAdapter#handle,最终会调用RequestMappingHandlerAdapter#invokeHandleMethod

private ModelAndView invokeHandleMethod(HttpServletRequest request,

HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

//把request和response包装到ServletWebRequest对象

ServletWebRequest webRequest = new ServletWebRequest(request, response);

WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);

//ModelAndvView的容器对象,方法调用之后的view和model就会在该容器中

ModelAndViewContainer mavContainer = new ModelAndViewContainer();

mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));

modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);

mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);

asyncWebRequest.setTimeout(this.asyncRequestTimeout);

final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

asyncManager.setTaskExecutor(this.taskExecutor);

async 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 Manager.setAsyncWebRequest(asyncWebRequest);

asyncManager.registerCallableInterceptors(this.callableInterceptors);

asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

if (asyncManager.hasConcurrentResult()) {

Object result = asyncManager.getConcurrentResult();

mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];

asyncManager.clearConcurrentResult();

if (logger.isDebugEnabled()) {

logger.debug(“Found concurrent result value [” + result + “]”);

}

requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);

}

//调用HandlerMethod方法,底层回从HandlerMethod拿到Method,然后使用反射进行调用

//把方法返回的viewName和model添加到mavContainer

requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

if (asyncManager.isConcurrentHandlingStarted()) {

return null;

}

//获取ModelAndView,从mavContainer拿到viewName和model生成ModelAndView

return getModelAndView(mavContainer, modelFactory, webRequest);

}

invokeAndHandle底层调用该方法nvocableHandlerMethod#invokeForRequest

public final Object invokeForRequest(NativeWebRequest request,

ModelAndViewContainer mavContainer,

Object… providedArgs) throws Exception {

//获取方法的参数

Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);

if (logger.isTraceEnabled()) {

StringBuilder builder = new StringBuilder(“Invoking [”);

builder.append(this.getMethod().getName()).append("] method with arguments ");

builder.append(Arrays.asList(args));

logger.trace(builder.toString());

}

//传入参数,调用方法

Object returnValue = invoke(args);

if (logger.isTraceEnabled()) {

logger.trace(“Method [” + this.getMethod().getName() + “] returned [” + returnValue + “]”);

}

return returnValue;

}

private Object invoke(Object… args) throws Exception {

ReflectionUtils.makeAccessible(this.getBridgedMethod());

try {

//反射调用方法

return getBridgedMethod().invoke(getBean(), args);

}

catch (IllegalArgumentException e) {

String msg = getInvocationErrorMessage(e.getMessage(), args);

throw new IllegalArgumentException(msg, e);

}

catch (InvocationTargetException e) {

// Unwrap for HandlerExceptionResolvers …

Throwable targetException = e.getTargetException();

if (targetException instanceof RuntimeException) {

throw (RuntimeException) targetException;

}

else if (targetException instanceof Error) {

throw (Error) targetException;

}

else if (targetException instanceof Exception) {

throw (Exception) targetException;

}

else {

String msg = getInvocationErrorMessage(“Failed to invoke controller method”, args);

throw new IllegalStateException(msg, targetException);

}

}

}

[](()viewResolver渲染视图

handler调用完成之后,代码来到DispatcherServlet#processDispatchResult负责处理结果

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,

HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

boolean errorView = false;

if (exception != null) {

if (exception instanceof ModelAndViewDefiningException) {

logger.debug(“ModelAndViewDefiningException encountered”, exception);

mv = ((ModelAndViewDefiningException) exception).getModelAndView();

}

else {

//这里在调用handlerExceptionResolvers处理异常,会循环所有的handlerExceptionResolvers

//然后根据exception生成一个ModelAndView

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);

}

}

else {

if (logger.isDebugEnabled()) {

logger.debug(“Null ModelAndView returned to DispatcherServlet with name '” + getServletName() +

“': assuming HandlerAdapter completed request handling”);

}

}

if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

// Concurrent handling started during a forward

return;

}

if (mappedHandler != null) {

//[重要]执行拦截器的interceptor.afterCompletion

mappedHandler.triggerAfterCompletion(request, response, null);

}

}

代码来到org.springframework.web.servlet.DispatcherServlet#render,该方法负责渲染视图

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {

// Determine locale for request and apply it to the response.

Locale locale = this.localeResolver.resolveLocale(request);

response.setLocale(locale);

View view;

if (mv.isReference()) {

// We need to resolve the view name.

//调用视图解析器,解析viewName,得到View对象

view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);

if (view == null) {

throw new ServletException(

“Could not resolve view with name '” + mv.getViewName() + “’ in servlet with name '” +

getServletName() + “'”);

}

}

else {

// No need to lookup: the ModelAndView object contains the actual View object.

view = mv.getView();

if (view == null) {

throw new ServletException(“ModelAndView [” + mv + "] neither contains a view name nor a " +

“View object in servlet with name '” + getServletName() + “'”);

}

}

// Delegate to the View object for rendering.

if (logger.isDebugEnabled()) {

logger.debug(“Rendering view [” + view + “] in DispatcherServlet with name '” + getServletName() + “'”);

}

//【重要】调用view.render渲染视图

view.render(mv.getModelInternal(), request, response);

}

protected View resolveViewName(String viewName, Map model, Locale locale,

HttpServletRequest request) throws Exception {

//调用视图解析器,根据viewName生产一个View

for (ViewResolver viewResolver : this.viewResolvers) {

View view = viewResolver.resolveViewName(viewName, locale);

if (view != null) {

return view;

}

}

return null;

}

resolveViewName方法循环所有的viewResolvers ,调用viewResolver.resolveViewName根据viewName解析一个View对象,底层调用AbstractCachingViewResolver#resolveViewName创建View,如下

protected AbstractUrlBasedView buildView(String viewName) throws Exception {

AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());

//前缀+viewName+后缀

view.setUrl(getPrefix() + viewName + getSuffix());

String contentType = getContentType();

if (contentType != null) {

view.setContentType(contentType);

}

view.setRequestContextAttribute(getRequestContextAttribute());

view.setAttributesMap(getAttributesMap());

if (this.exposePathVariables != null) {

view.setExposePathVariables(exposePathVariables);

}

return view;

}

找到View之后,会调用View的render方法渲染视图,见:org.springframework.web.servlet.view.AbstractView#render

public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {

if (logger.isTraceEnabled()) {

logger.trace(“Rendering view with name '” + this.beanName + "’ with model " + model +

" and static attributes " + this.staticAttributes);

}

//拿到model数据模型

Map mergedModel = createMergedOutputModel(model, request, response);

prepareResponse(request, response);

//渲染

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/793994.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存