当前位置: 首页 > news >正文

专业网站的公司etc工程承包模式

专业网站的公司,etc工程承包模式,如何装修网店详细步骤,王野天是谁Srping MVC 执行流程真的是老生常谈的话题了#xff0c;最近同事小刚出去面试#xff0c;前面面试官相继问了几个 Spring 相关的问题#xff0c;但当面试官问他#xff0c;你知道 Srping MVC 的执行流程吗#xff1f;小刚娴熟的巴拉巴拉回答完后#xff0c;面试官就让他回…Srping MVC 执行流程真的是老生常谈的话题了最近同事小刚出去面试前面面试官相继问了几个 Spring 相关的问题但当面试官问他你知道 Srping MVC 的执行流程吗小刚娴熟的巴拉巴拉回答完后面试官就让他回去等通知了… Spring MVC 执行流程 Spring MVC 执行流程图片版 Spring MVC 执行流程文字版 用户发送请求到前端控制器 DispatcherServletDispatcherServlet 控制器接收到请求然后调用 HandlerMapping 处理器映射器。HandlerMapping 处理器映射器找到处理请求的 HandlerAdapter 处理器映射器。DispatcherServlet 调用 HandlerAdapter 处理器适配器找到具体的处理器 Controller。执行 Controller 进行业务处理。Controller 执行完返回 ModelAndView 给 HandlerAdapter。HandlerAdapter 将 Controller 执行结果 ModelAndView 返回给 DispatcherServlet。DispatcherServlet 查询一个或多个 ViewResoler 视图解析器找到 ModelAndView 指定的视图 View。ViewReslover 解析后返回具体 View。DispatcherServlet 根据View 进行渲染视图。DispatcherServlet 响应结果给用户。 整个流程这样回答下来应该没什么问题因为无论是书上还是面试题上基本都这么标注的答案但巧就巧在同事小刚做的项目是前后端分离的项目简历中写的言外之意就是从第 6 步开始下面的回答基本就不对了因为在前后端分离项目中最终返回给前端的数据是以 JSON 形式的所以不存在什么视图解析器一说。 这个时候需要变一个答法就是直接返回 JSON 数据回去可以使用 ResponseBody 注解。 到这基本也明白了为啥小刚答完这个问题面试官就让他回去等消息了… Spring MVC 工作原理 相信大家上方的执行流程都背的滚瓜烂熟了… 不知道大家是否有这种好奇就是 RequestMapping 注解的 Url 怎么就跟 Controller 关联起来了呢 不管你好不好奇接下来我们就假装带着这个好奇来看看怎么就关联上了。 从上边的流程我们知道请求的入口是 DispatcherServlet 那么我们来看一下这个类 SuppressWarnings(serial) 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 static final String FLASH_MAP_MANAGER_BEAN_NAME flashMapManager;public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE DispatcherServlet.class.getName() .CONTEXT;public static final String LOCALE_RESOLVER_ATTRIBUTE DispatcherServlet.class.getName() .LOCALE_RESOLVER;public static final String THEME_RESOLVER_ATTRIBUTE DispatcherServlet.class.getName() .THEME_RESOLVER;public static final String THEME_SOURCE_ATTRIBUTE DispatcherServlet.class.getName() .THEME_SOURCE;public static final String INPUT_FLASH_MAP_ATTRIBUTE DispatcherServlet.class.getName() .INPUT_FLASH_MAP;public static final String OUTPUT_FLASH_MAP_ATTRIBUTE DispatcherServlet.class.getName() .OUTPUT_FLASH_MAP;public static final String FLASH_MAP_MANAGER_ATTRIBUTE DispatcherServlet.class.getName() .FLASH_MAP_MANAGER;public static final String EXCEPTION_ATTRIBUTE DispatcherServlet.class.getName() .EXCEPTION;public static final String PAGE_NOT_FOUND_LOG_CATEGORY org.springframework.web.servlet.PageNotFound;private static final String DEFAULT_STRATEGIES_PATH DispatcherServlet.properties;protected static final Log pageNotFoundLogger LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY);private static final Properties defaultStrategies;static {try {ClassPathResource resource new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);defaultStrategies PropertiesLoaderUtils.loadProperties(resource);}catch (IOException ex) {throw new IllegalStateException(Could not load DispatcherServlet.properties: ex.getMessage());}}/** Detect all HandlerMappings or just expect handlerMapping bean? */private boolean detectAllHandlerMappings true;/** Detect all HandlerAdapters or just expect handlerAdapter bean? */private boolean detectAllHandlerAdapters true;/** Detect all HandlerExceptionResolvers or just expect handlerExceptionResolver bean? */private boolean detectAllHandlerExceptionResolvers true;/** Detect all ViewResolvers or just expect viewResolver bean? */private boolean detectAllViewResolvers true;/** Throw a NoHandlerFoundException if no Handler was found to process this request? **/private boolean throwExceptionIfNoHandlerFound false;/** Perform cleanup of request attributes after include request? */private boolean cleanupAfterInclude true;/** MultipartResolver used by this servlet */private MultipartResolver multipartResolver;/** LocaleResolver used by this servlet */private LocaleResolver localeResolver;/** ThemeResolver used by this servlet */private ThemeResolver themeResolver;/** List of HandlerMappings used by this servlet */private ListHandlerMapping handlerMappings;/** List of HandlerAdapters used by this servlet */private ListHandlerAdapter handlerAdapters;/** List of HandlerExceptionResolvers used by this servlet */private ListHandlerExceptionResolver handlerExceptionResolvers;/** RequestToViewNameTranslator used by this servlet */private RequestToViewNameTranslator viewNameTranslator;private FlashMapManager flashMapManager;/** List of ViewResolvers used by this servlet */private ListViewResolver viewResolvers;public DispatcherServlet() {super();}public DispatcherServlet(WebApplicationContext webApplicationContext) {super(webApplicationContext);}Overrideprotected void onRefresh(ApplicationContext context) {initStrategies(context);}protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);} }这个类真的是太长了实在是没耐心看下来以至于不得不精简了一部分上方为精简后的在这里面我们可以看到一些熟悉的面孔 HandlerMapping用于handlers映射请求和一系列的对于拦截器的前处理和后处理大部分用Controller注解。HandlerAdapter帮助DispatcherServlet处理映射请求处理程序的适配器而不用考虑实际调用的是 哪个处理程序ViewResolver根据实际配置解析实际的View类型。ThemeResolver解决Web应用程序可以使用的主题例如提供个性化布局。MultipartResolver解析多部分请求以支持从HTML表单上传文件。 既然 HandlerMapping 是用来映射请求的然后我们就继续朝着这个方向走在上方 DispatcherServlet 中找到 HandlerMapping 相关的代码然后我们就找到了这个集合 private ListHandlerMapping handlerMappings; 接着看看在哪给这个 handlerMappings 集合赋值的然后就找到了如下方法 private void initHandlerMappings(ApplicationContext context) {this.handlerMappings null;if (this.detectAllHandlerMappings) {MapString, HandlerMapping matchingBeans BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerMappings new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerMappings);}} else {try {HandlerMapping hm (HandlerMapping)context.getBean(handlerMapping, HandlerMapping.class);this.handlerMappings Collections.singletonList(hm);} catch (NoSuchBeanDefinitionException var3) {}}if (this.handlerMappings null) {this.handlerMappings this.getDefaultStrategies(context, HandlerMapping.class);if (this.logger.isTraceEnabled()) {this.logger.trace(No HandlerMappings declared for servlet this.getServletName() : using default strategies from DispatcherServlet.properties);}}}简单分析一下 initHandlerMappings() 这段方法首先我们需要先了解 HandlerMapping 其实是一个接口类然后这个接口类就定义了一个方法 getHandler() 这个方法也很简单就是根据请求的 request获取 HandlerExecutionChain 对象 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;NullableHandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception; }Spring MVC 提供了许多 HandlerMapping 的实现我们可以点进去看看这个 HandlerMapping 有多少实现 大约有19个子类实现了 HandlerMapping 接口默认使用的是 BeanNameUrlHandlerMapping可以根据 Bean 的 name 属性映射到 URL 中。我们再回到 initHandlerMappings() 方法我们可以看到在赋值的时候有个 if (this.detectAllHandlerMappings) 属性的判断这个属性是用来标记是否只期望 Srping MVC 只加载指定的 HandlerMappring 的如果修改为 fasle Spring MVC 就只会查找名为 “handlerMapping” 的 bean并作为当前系统的唯一的 HandlerMapping。 而正常情况为 true 时就会加载所有 HandlerMapping 的实现类加载之后还有个使用优先级的排序过程 AnnotationAwareOrderComparator.sort(this.handlerMappings);优先使用高优先级的 HandlerMapping。 看到这可能就会觉得既然 HandlerMapping 有这么多的实现类但是具体的某个实现类又是怎么初始化的呢毕竟 HandlerMapping 的作用可是用来映射请求的还没看到具体实现过程呢… 所以到这个时候很显然得进行下去嘛所以不得不找一个实现类来看看是如何具体初始化的但是具体找哪个分析呢在决定分析哪个之前我们先了解一下 HadlerMapping 接口的继承体系。 HandlerMapping接口继承体系 这个体系比较庞大我们着重看我标注的红框跟蓝筐内的内容通过1、2我们可以将 HadlerMapping 分为两个体系一是继承自 AbstractUrlHandlerMapping二是继承 AbstractHandlerMethodMapping因为随着版本的问题本文以Spring4.3.13为例其中 AbstractUrlHandlerMapping 在目前大部分的项目已经很少使用到了所以接下来我们就重点分析AbstractHandlerMethodMapping他就是我们经常使用的RequestMapping注解会使用到的方式。 在分析 AbstractHandlerMethodMapping 之前我们先分析下这个类的父类 AbstractHandlerMapping不然有些方法就很懵逼。 1、AbstractHandlerMapping概述 已经不想贴这个类的完整代码了感兴趣的小伙伴自己点进去看看吧简单说一下定义AbstractHandlerMapping 是 HandlerMapping 的抽象实现采用模板模式设计了 HandlerMapping 的整体架构。其定义了getHandlerInternal() 方法该方法就是一个模版方法根据 request 来获取相应的 Handler由它的两个子类来具体实现该方法。然后再根据 request 来获取相应的 interceptors整合从子类获取的 Handler组成 HandlerExecutionChain 对象返回。 Nullable protected abstract Object getHandlerInternal(HttpServletRequest var1) throws Exception;2、AbstractHandlerMapping初始化 AbstractHandlerMapping 继承了 WebApplicationObjectSupport获取Spring的ApplicationContext方式之一可以看做java类获取Spring容器的Bean初始化时会自动调用模板方法 initApplicationContext具体如下 Override protected void initApplicationContext() throws BeansException {// 模板方法暂无子类实现extendInterceptors(this.interceptors);// 从容器中获取实现了MappedInterceptor接口的对象添加到adaptedInterceptors列表中detectMappedInterceptors(this.adaptedInterceptors);// 将interceptors由子类添加中的对象封装后添加到adaptedInterceptors列表中initInterceptors(); }3、AbstractHandlerMapping的使用 AbstractHandlerMapping 继承自 HandlerMapping 实现了其 getHandler() 方法我们上边也提到该方法就是根据请求的 request获取 HandlerExecutionChain 对象我们来看一下 AbstractHandlerMapping 中的实现 Override public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {// 模板模式方法具体由子类实现Object handler getHandlerInternal(request);if (handler null) {handler getDefaultHandler();}if (handler null) {return null;}if (handler instanceof String) {String handlerName (String) handler;handler getApplicationContext().getBean(handlerName);}// 根据request从adaptedInterceptors中选择匹配的interceptors与handler一起封装成HandlerExecutionChain对象HandlerExecutionChain executionChain getHandlerExecutionChain(handler, request);return executionChain; }到这就是交给子类去完成了分别是 AbstractUrlHandlerMapping 和 AbstractHandlerMethodMapping接下来我们只着重分析 AbstractHandlerMethodMapping 类。 AbstractHandlerMethodMapping 首先实现了父类 getHandlerInternal() 方法 protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 获得请求的路径String lookupPath this.getUrlPathHelper().getLookupPathForRequest(request);request.setAttribute(LOOKUP_PATH, lookupPath);// 获得读锁this.mappingRegistry.acquireReadLock();HandlerMethod var4;try {// 获得 HandlerMethod 对象HandlerMethod handlerMethod this.lookupHandlerMethod(lookupPath, request);var4 handlerMethod ! null ? handlerMethod.createWithResolvedBean() : null;} finally {// 释放锁this.mappingRegistry.releaseReadLock();}return var4; }重点在于 lookupHandlerMethod() 方法如下为详细代码 Nullable protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {// Match数组用于存储匹配上当前请求的结果ListAbstractHandlerMethodMappingT.Match matches new ArrayList();// 优先级基于直接 URL 的 Mapprings 进行匹配ListT directPathMatches this.mappingRegistry.getMappingsByUrl(lookupPath);if (directPathMatches ! null) {this.addMatchingMappings(directPathMatches, matches, request);}// 扫描注册表的 Mappings 进行匹配if (matches.isEmpty()) {this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);}// 如果匹配到则获取最佳匹配的 Match 对象的 handlerMethod 属性if (!matches.isEmpty()) {// 创建 MathComparator 对象ComparatorAbstractHandlerMethodMappingT.Match comparator new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));// 排序 matches 结果matches.sort(comparator);// 获取首个 Match 对象AbstractHandlerMethodMappingT.Match bestMatch (AbstractHandlerMethodMapping.Match)matches.get(0);// 处理存在多个 Match 对象的情况if (matches.size() 1) {if (this.logger.isTraceEnabled()) {this.logger.trace(matches.size() matching mappings: matches);}if (CorsUtils.isPreFlightRequest(request)) {return PREFLIGHT_AMBIGUOUS_MATCH;}// 比较 bestMatch 和 secondBestMatch如果相等则抛出 IllegalStateException 异常AbstractHandlerMethodMappingT.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);// 处理首个 Match 对象this.handleMatch(bestMatch.mapping, lookupPath, request);return bestMatch.handlerMethod;} else {// 如果匹配不到则处理不匹配的情况return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);} }在分析 lookupHandlerMethod() 方法的整体思路之前我们还得知晓 AbstractHandlerMethodMapping 的内部类 MappingRegistry。MappingRegistry 类中定义了两个比较重要的变量MapT, HandlerMethod mappingLookup new LinkedHashMapT, HandlerMethod() 和 MultiValueMapString, T urlLookup new LinkedMultiValueMapString, T()。其中 mappingLookup 变量保存了 RequestMappingInfo 与 HandlerMethod 的一一对应关系而 urlLookup 变量则保存了 url 与 RequestMappingInfo 的对应关系需要注意的是 MultiValueMap 类型的变量是可以一个 key 对应多个 value 的也就是说 urlLookup 变量中一个 url 可能对应多个 RequestMappingInfo。 有了这个概念后我们再来看 lookupHandlerMethod() 方法整个过程结果就是根据入参 lookupPath可以看成是 url从 request 中获取到一个最符合的 RequestMappingInfo 对象然后根据该对象再去获取到 HandlerMethod 对象返回给父类 AbstractHandlerMapping。 其实在 lookupHandlerMethod() 方法之前还有一个 mappingLookup、urlLookup 等参数初始化的过程AbstractHandlerMethodMapping 实现了 InitializingBean 接口当 Spring 容器启动时会自动调用其 afterPropertiesSet() 方法来完成 handlerMethod 的注册操作但是该方法最终又交给 initHandlerMethods() 方法完成具体的初始化 protected void initHandlerMethods() {if (logger.isDebugEnabled()) {logger.debug(Looking for request mappings in application context: getApplicationContext());}// 从springMVC容器中获取所有的beanNamString[] beanNames (this.detectHandlerMethodsInAncestorContexts ?BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :getApplicationContext().getBeanNamesForType(Object.class));// 注册从容器中获取的beanNamefor (String beanName : beanNames) {if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {Class? beanType null;try {beanType getApplicationContext().getType(beanName);}catch (Throwable ex) {// An unresolvable bean type, probably from a lazy bean - lets ignore it.if (logger.isDebugEnabled()) {logger.debug(Could not resolve target class for bean with name beanName , ex);}}if (beanType ! null isHandler(beanType)) {detectHandlerMethods(beanName);}}}// 模板方法暂无子类实现handlerMethodsInitialized(getHandlerMethods()); }简单来说这个方法就是进行 HandlerMethod 的注册操作首先从 Spring MVC 的容器中获取所有的 beanName 然后进行过滤处理注册 URL 和实现方法 HandlerMethod 的对应关系。 在 initHandlerMethods() 方法中我们主要关注两个方法 isHandler(beanType) 与 detectHandlerMethods(beanName) 其中 isHandler(beanType) 方法由子类 RequestMappingHandlerMapping 实现用于对 bean 进行过滤判断是否包含 Controller 或者 RequestMapping 注解。 Override protected boolean isHandler(Class? beanType) {return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class)); }而 detectHandlerMethods(beanName) 方法则根据筛选出的 bean进行一系列的注册最终实现是在 registerHandlerMethod() 方法 protected void detectHandlerMethods(final Object handler) {Class? handlerType (handler instanceof String ?getApplicationContext().getType((String) handler) : handler.getClass());// CGLib动态代理的特殊处理final Class? userType ClassUtils.getUserClass(handlerType);// methods包含了bean中所有符合条件的method与相关的RequestMappingInfo键值对MapMethod, T methods MethodIntrospector.selectMethods(userType,new MethodIntrospector.MetadataLookupT() {Overridepublic T inspect(Method method) {try {// 如果method有RequestMapping注解则返回由注解得到的封装好的RequestMappingInfo对象否则返回nullreturn getMappingForMethod(method, userType);}catch (Throwable ex) {throw new IllegalStateException(Invalid mapping on handler class [ userType.getName() ]: method, ex);}}});if (logger.isDebugEnabled()) {logger.debug(methods.size() request handler methods found on userType : methods);}for (Map.EntryMethod, T entry : methods.entrySet()) {Method invocableMethod AopUtils.selectInvocableMethod(entry.getKey(), userType);T mapping entry.getValue();// 注册 beanNameMethod及创建的RequestMappingInfo之间的关系registerHandlerMethod(handler, invocableMethod, mapping);} }detectHandlerMethods() 方法中的 getMappingForMethod() 方法是在子类 RequestMappingHandlerMapping 中实现的具体实现就是创建一个 RequestMappingInfo /*** Uses method and type-level {link RequestMapping} annotations to create* the RequestMappingInfo.* return the created RequestMappingInfo, or {code null} if the method* does not have a {code RequestMapping} annotation.* see #getCustomMethodCondition(Method)* see #getCustomTypeCondition(Class)*/ Override protected RequestMappingInfo getMappingForMethod(Method method, Class? handlerType) {RequestMappingInfo info createRequestMappingInfo(method);if (info ! null) {RequestMappingInfo typeInfo createRequestMappingInfo(handlerType);if (typeInfo ! null) {info typeInfo.combine(info);}}return info; }/*** Delegates to {link #createRequestMappingInfo(RequestMapping, RequestCondition)},* supplying the appropriate custom {link RequestCondition} depending on whether* the supplied {code annotatedElement} is a class or method.* see #getCustomTypeCondition(Class)* see #getCustomMethodCondition(Method)*/ private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {RequestMapping requestMapping AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);RequestCondition? condition (element instanceof Class ?getCustomTypeCondition((Class?) element) : getCustomMethodCondition((Method) element));return (requestMapping ! null ? createRequestMappingInfo(requestMapping, condition) : null); }detectHandlerMethods() 方法中的 registerHandlerMethod() 方法的操作是注册 beanNameMethod 及创建的 RequestMappingInfo 之间的关系 protected void registerHandlerMethod(Object handler, Method method, T mapping) {this.mappingRegistry.register(mapping, handler, method); }到这就简单实现了将 url 和 HandlerMethod 的对应关系注册到 mappingRegistry 中了。 private final AbstractHandlerMethodMappingT.MappingRegistry mappingRegistry new AbstractHandlerMethodMapping.MappingRegistry();最后总结 Spring MVC 执行流程 在描述 Spring MVC 执行流程的时候需要注意只有在以前使用 jsp、themlef 等模板引擎的时候我们会把前端界面放在后端的工程里然后在 controller 执行完业务逻辑之后会返回一个界面模版名称也就是ModelAndView然后 DispatherServlet 将 ModelAndView 传递给 ViewReslover 视图解析器视图解析器解析后返回具体的 View然后对 html 界面做一个渲染。 如果返回的是一个json串的话也就是前后端分离的项目那么只需要返回json数据即可。 Spring MVC 工作原理 Spring MVC 使用 HandlerMappring 来找到并保存 URL 请求和处理函数间的 mapping 关系。 以 AbstractHandlerMethodMapping 为例来具体看 HandlerMapping 的作用首先拿到容器里所有的 bean然后根据一定的规则筛选出 Handler然后保存在 map 中具体的筛选工作在子类中进行筛选的逻辑就是检查类前是否存在 Controller 或者 RequestMapping 注解 然后在 detectHandlerMethods() 方法中负责将 Handler 保存在 map 中。 1、用户发送请求时会先从 DispathcherServler 的 doService 方法开始在该方法中会将 ApplicationContext、localeResolver、themeResolver 等对象添加到 request 中紧接着就是调用 doDispatch 方法。 2、进入 doDispatch 方法后首先会检查该请求是否是文件上传的请求校验的规则是是否是post并且contenttType是否为multipart/为前缀即调用的是 checkMultipart 方法如果是的话将 request 包装成 MultipartHttpServletRequest。 3、然后调用 getHandler 方法来匹配每个 HandlerMapping 对象如果匹配成功会返回这个 Handle 的处理链 HandlerExecutionChain 对象在获取该对象的内部其实也获取我们自定定义的拦截器并执行了其中的方法。 4、执行拦截器的 preHandle 方法如果返回 false 执行 afterCompletion 方法并理解返回 5、通过上述获取到了 HandlerExecutionChain 对象通过该对象的 getHandler() 方法获得一个 object 通过 HandlerAdapter 进行封装得到 HandlerAdapter 对象。 6、该对象调用 handle 方法来执行 Controller 中的方法然后根据类型返回不同的结果如JSON、ModelAndView该对象如果返回一个 ModelAndView 给 DispatcherServlet。 7、DispatcherServlet 借助 ViewResolver 完成逻辑试图名到真实视图对象的解析得到 View 后 DispatcherServlet 使用这个 View 对 ModelAndView 中的模型数据进行视图渲染。 工作原理写着写着发现挺乱的整体描述的不是特别清楚也很枯燥之后通过阅读 Spring MVC 整体源码后再补充。 本文首发于博客园https://niceyoo.cnblogs.com/
http://wiki.neutronadmin.com/news/160144/

相关文章:

  • 公众号江苏建设信息网站so域名的网站有哪些
  • 图案设计网站有哪些响亮大气的公司名字
  • 网站的优化是什么意思河南郑州百姓网
  • 网站ui设计怎么做wordpress去除自豪的采用
  • 专门做特医食品的网站wordpress去掉tag
  • 做网站平台建企业网站行业网
  • 网站做cpa模板王网页模板
  • 阳原网站建设麦田 网站建设
  • 怎样注册一个网站做电商开题报告旅游网站建设
  • 昆明seo网站建设费用seo课程排行榜
  • 国外酷炫网站有哪些wordpress 公众号采集
  • 做空调的网站东平建设局网站
  • 微信优惠群怎么做网站长沙网站seo价格
  • 网站推广有什么方法网站项目管理系统
  • 外贸网站建设 杭州制作网站需要哪些素材
  • 小破站下载深圳住建设局网站公租房
  • 人才市场招聘网站做网站注册公司
  • 简单分析网站的外链 以及优化的策略.淘宝客网站怎么建设
  • 关于做网站的搞笑段子微网站模板建设
  • 青浦门户网站个人建设网站需要什么证件吗
  • 做视频教学网站服务器配置网站开发询价表模板下载
  • 2015微信网站设计小吃加盟网站大全
  • 视频直播点播网站建设泛华建设集团有限公司网站
  • 建立网站的步骤有哪些免费秒玩小游戏
  • 网站建设 成都工业设计和产品设计的区别
  • 公司做网站图片旅游网站建设的目标
  • 对网站进行优化网页设计100个
  • 天津 企业网站建设wordpress 主题改多频道
  • 一流的网站建设流程图电子商务网站建设干货
  • 各种网站制作百度合作推广