- ctrl + n,搜索DispatcherServlet
| public class DispatcherServlet extends FrameworkServlet { |
| public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"; |
| public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; |
| public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver"; |
| public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping"; |
| public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter"; |
| public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver"; |
| public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator"; |
| public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver"; |
| public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { |
| public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet"; |
| public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class; |
| public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT."; |
| private static final String INIT_PARAM_DELIMITERS = ",; \t\n"; |
| @Nullable |
| private String contextAttribute; |
| private Class<?> contextClass; |
| @Nullable |
| private String contextId; |
| @Nullable |
| private String namespace; |
| @Nullable |
| private String contextConfigLocation; |
| public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { |
| protected final Log logger = LogFactory.getLog(this.getClass()); |
| @Nullable |
| private ConfigurableEnvironment environment; |
| private final Set<String> requiredProperties = new HashSet(4); |
| |
| public HttpServletBean() { |
| } |
| |
| protected final void addRequiredProperty(String property) { |
| this.requiredProperties.add(property); |
| } |
| |
| public void setEnvironment(Environment environment) { |
| Assert.isInstanceOf(ConfigurableEnvironment.class, environment, "ConfigurableEnvironment required"); |
| this.environment = (ConfigurableEnvironment)environment; |
| } |
- 在HttpServletBean中并没有重写doget和dopost方法,但是在FrameworkServlet 重写doget等方法
| protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
| this.processRequest(request, response); |
| } |
| |
| protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
| this.processRequest(request, response); |
| } |
| |
| protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
| this.processRequest(request, response); |
| } |
| |
| protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
| this.processRequest(request, response); |
| } |
| protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
| long startTime = System.currentTimeMillis(); |
| Throwable failureCause = null; |
| LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); |
| LocaleContext localeContext = this.buildLocaleContext(request); |
| RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); |
| ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes); |
| WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); |
| asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor()); |
| this.initContextHolders(request, localeContext, requestAttributes); |
| |
| try { |
| this.doService(request, response); |
| } catch (IOException | ServletException var16) { |
| failureCause = var16; |
| throw var16; |
| } catch (Throwable var17) { |
| failureCause = var17; |
| throw new NestedServletException("Request processing failed", var17); |
| } finally { |
| this.resetContextHolders(request, previousLocaleContext, previousAttributes); |
| if (requestAttributes != null) { |
| requestAttributes.requestCompleted(); |
| } |
| |
| this.logResult(request, response, (Throwable)failureCause, asyncManager); |
| this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause); |
| } |
| |
| } |
| protected abstract void doService(HttpServletRequest var1, HttpServletResponse var2) throws Exception; |
- 最终查看DispatcherServlet的doService方法
| protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { |
| this.logRequest(request); |
| Map<String, Object> attributesSnapshot = null; |
| if (WebUtils.isIncludeRequest(request)) { |
| attributesSnapshot = new HashMap(); |
| Enumeration attrNames = request.getAttributeNames(); |
| |
| label95: |
| while(true) { |
| String attrName; |
| do { |
| if (!attrNames.hasMoreElements()) { |
| break label95; |
| } |
| |
| attrName = (String)attrNames.nextElement(); |
| } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); |
| |
| attributesSnapshot.put(attrName, request.getAttribute(attrName)); |
| } |
| } |

| protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { |
| HttpServletRequest processedRequest = request; |
| HandlerExecutionChain mappedHandler = null; |
| boolean multipartRequestParsed = false; |
| WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); |
| |
| try { |
| try { |
| ModelAndView mv = null; |
| Object dispatchException = null; |
| |
| try { |
| |
| processedRequest = this.checkMultipart(request); |
| multipartRequestParsed = processedRequest != request; |
| |
| mappedHandler = this.getHandler(processedRequest); |
| if (mappedHandler == null) { |
| this.noHandlerFound(processedRequest, response); |
| return; |
| } |
| |
| HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); |
| String method = request.getMethod(); |
| boolean isGet = "GET".equals(method); |
| if (isGet || "HEAD".equals(method)) { |
| long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); |
| if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { |
| return; |
| } |
| } |
| |
| if (!mappedHandler.applyPreHandle(processedRequest, response)) { |
| return; |
| } |
| |
| mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); |
| if (asyncManager.isConcurrentHandlingStarted()) { |
| return; |
| } |
| |
| this.applyDefaultViewName(processedRequest, mv); |
| mappedHandler.applyPostHandle(processedRequest, response, mv); |
| } catch (Exception var20) { |
| dispatchException = var20; |
| } catch (Throwable var21) { |
| dispatchException = new NestedServletException("Handler dispatch failed", var21); |
| } |
| |
| this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); |
| } catch (Exception var22) { |
| this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22); |
| } catch (Throwable var23) { |
| this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); |
| } |
| |
| } finally { |
| if (asyncManager.isConcurrentHandlingStarted()) { |
| if (mappedHandler != null) { |
| mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); |
| } |
| } else if (multipartRequestParsed) { |
| this.cleanupMultipart(processedRequest); |
| } |
| |
| } |
| } |
| @Nullable |
| protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { |
| |
| if (this.handlerMappings != null) { |
| Iterator var2 = this.handlerMappings.iterator(); |
| |
| while(var2.hasNext()) { |
| HandlerMapping mapping = (HandlerMapping)var2.next(); |
| HandlerExecutionChain handler = mapping.getHandler(request); |
| if (handler != null) { |
| return handler; |
| } |
| } |
| } |
| |
| return null; |
| } |

- RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。

| public interface HandlerMapping { |
| String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler"; |
| String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath"; |
| String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping"; |
| String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern"; |
| String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping"; |
| String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables"; |
| String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables"; |
| String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; |
| |
| @Nullable |
| HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception; |
| } |
| @Nullable |
| public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { |
| Object handler = this.getHandlerInternal(request); |
| if (handler == null) { |
| handler = this.getDefaultHandler(); |
| } |
| |
| if (handler == null) { |
| return null; |
| } else { |
| if (handler instanceof String) { |
| String handlerName = (String)handler; |
| handler = this.obtainApplicationContext().getBean(handlerName); |
| } |
| |
| HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request); |
| if (this.logger.isTraceEnabled()) { |
| this.logger.trace("Mapped to " + handler); |
| } else if (this.logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { |
| this.logger.debug("Mapped to " + executionChain.getHandler()); |
| } |
| |
| if (this.hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { |
| CorsConfiguration config = this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null; |
| CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request); |
| config = config != null ? config.combine(handlerConfig) : handlerConfig; |
| executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config); |
| } |
| |
| return executionChain; |
| } |
| } |
-
查看getHandlerInternal

-
查看lookupHandlerMethod
| @Nullable |
| protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { |
| List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList(); |
| |
| List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); |
| if (directPathMatches != null) { |
| this.addMatchingMappings(directPathMatches, matches, request); |
| } |
| |
| if (matches.isEmpty()) { |
| this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); |
| } |
| |
| |
| if (!matches.isEmpty()) { |
| AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0); |
| if (matches.size() > 1) { |
| Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request)); |
| matches.sort(comparator); |
| bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0); |
| if (this.logger.isTraceEnabled()) { |
| this.logger.trace(matches.size() + " matching mappings: " + matches); |
| } |
| |
| if (CorsUtils.isPreFlightRequest(request)) { |
| return PREFLIGHT_AMBIGUOUS_MATCH; |
| } |
| |
| AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1); |
| if (comparator.compare(bestMatch, secondBestMatch) == 0) { |
| Method m1 = bestMatch.handlerMethod.getMethod(); |
| Method m2 = secondBestMatch.handlerMethod.getMethod(); |
| String uri = request.getRequestURI(); |
| throw new IllegalStateException("Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); |
| } |
| } |
| |
| request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); |
| this.handleMatch(bestMatch.mapping, lookupPath, request); |
| return bestMatch.handlerMethod; |
| } else { |
| return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix