SpringMVC原理
# 执行流程
1、用户发送http请求
2、dispatchServlet解析请求头中的uri
3、通过处理器映射器(HandlerMapping)拿到对应的hanlder
4、处理器适配器(HandlerAdapter)通过拿到的hanlder处理业务逻辑,返回视图ModelAndView
5、dispatchServlet通过视图解析器(ViewResolver)将物理视图解析成逻辑视图View
6、视图渲染。
-
DispatcherServlet:
- 调用HandlerMapping拿到Handler
- 调用HandlerAdapter拿到ModelAndView
- 调用ViewResolver拿到View
// 视图渲染 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 != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; String viewName = mv.getViewName(); if (viewName != null) { // We need to resolve the view name. view = resolveViewName(viewName, 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.isTraceEnabled()) { logger.trace("Rendering view [" + view + "] "); } try { if (mv.getStatus() != null) { response.setStatus(mv.getStatus().value()); } view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "]", ex); } throw ex; } }
-
HandlerMapping:根据请求的url找到对应的handler
-
urlLookup
-
mappingLookup
public interface HandlerMapping { @Nullable HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; }
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware { // 实现类逻辑 @Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 获取handler对象 Object handler = getHandlerInternal(request); ... // Handler执行前后要执行的拦截器 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); ... return executionChain; } @Nullable protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception; }
// 映射信息封装handler public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping { String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath"; @Override @Nullable protected Object getHandlerInternal(HttpServletRequest request) throws Exception { // 从请求头中获取请求路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // org.springframework.web.servlet.HandlerMapping.lookupPath -> /test request.setAttribute(LOOKUP_PATH, lookupPath); Object handler = lookupHandler(lookupPath, request); ... return handler; } // 路径封装handler @Nullable protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { // Direct match? Object handler = this.handlerMap.get(urlPath); if (handler != null) { // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } validateHandler(handler, request); return buildPathExposingHandler(handler, urlPath, urlPath, null); } } // 方法执行前后拦截器创建 protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern, String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) { HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler); chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping)); if (!CollectionUtils.isEmpty(uriTemplateVariables)) { chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables)); } return chain; } // 相关拦截器添加 protected HandlerExecutionChain getHandlerExecutionChain(Object handler,HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH); 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; } }
-
-
HandlerAdapter:根据找到的handler执行对应的方法
public interface HandlerAdapter { // 该适配器是否能支持指定处理器 boolean supports(Object handler); // 执行处理逻辑,返回 ModelAndView @Nullable ModelAndView handle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; // 请求的目标资源最近一次的修改时间 long getLastModified(HttpServletRequest request, Object handler); }
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered { ... @Override @Nullable public final ModelAndView handle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } @Nullable protected abstract ModelAndView handleInternal( HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception; ... }
// 通过反射业务方法执行 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { @Override protected ModelAndView handleInternal( HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; // 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; } }