SpringMVC流程及源码分析 |
您所在的位置:网站首页 › ps中怎么导入表格文字格式 › SpringMVC流程及源码分析 |
二、源码分析 以下源码来源jar包:spring-webmvc-5.25.RELEASE.jar 1、初始化 1.1、ApplicationContext ApplicationContext初始化入口类:ApplicationObjectSupport的setApplicationContext方法,setApplicationContext方法中核心部分就是初始化容器initApplicationContext(context),子类AbstractDetectingUrlHandlerMapping实现了该方法。 类图: 2021022601-06-RequestMappingHandlerMapping类层次图 UML图: 2021022601-07-RequestMappingHandlerMapping-uml RequestMappingHandlerMapping ,用于注解@Controller,@RequestMapping来定义controller. 初始化时,3个类的大致分工如下: AbstractHandlerMethodMapping定义整个算法流程; RequestMappingInfoHandlerMapping提供匹配条件RequestMappingInfo的解析处理; RequestMappingHandlerMapping根据@RequestMapping注解生成 RequestMappingInfo,同时提供isHandler实现 2、前端控制器(中央处理器)DistepcherServlet 从上面的流程图可以看到前端控制器(中央处理器)DistepcherServlet是SpringMVC核心,查看DistepcherServlet类的继承情况。 UML图: ![2021022601-08-DispatcherServlet UML图](https://gitee.com/chuchq/blogs-gallery/raw/master/images / 2021/2021022601-08-DispatcherServlet UML图.png) 从继承关系看出: DistepcherServlet ---> FrameworkServlet ---> HttpServletBean---> HttpServlet 那就说明DistepcherServlet 类也是一个Servlet类,那最终核心的方法就是service()方法,即Servlet的核心方法。 那就找service()方法,在DistepcherServlet中没有servic()方法,在父类FrameworkServlet有service()方法,源码如下: 来源: org.springframework.web.servlet.FrameworkServlet.service(HttpServletRequest request, HttpServletResponse response) /** * Override the parent class implementation in order to intercept PATCH requests. */ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { processRequest(request, response); } else { super.service(request, response); } } 可以看到: FrameworkServlet.service(HttpServletRequest request, HttpServletResponse response)拿到request请求,判断当前请求是否是PATCH请求,不是的就调用父类的servic()方法,掉用父类中的service方法就是去调用该类中doPost(),doGet()方法,根据不同的请求方式然后走doPost()或者doGet(),调用中以doGet()为例, FrameworkServlet类的doGet()源码: /** * Delegate GET requests to processRequest/doService. * Will also be invoked by HttpServlet's default implementation of {@code doHead}, * with a {@code NoBodyResponse} that just captures the content length. * @see #doService * @see #doHead */ @Override protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } doGet()又调用FrameworkServlet类中的processRequest(request, response); /** * Process this request, publishing an event regardless of the outcome. * The actual event handling is performed by the abstract * {@link #doService} template method. */ protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor()); initContextHolders(request, localeContext, requestAttributes); try { doService(request, response); } catch (ServletException | IOException ex) { failureCause = ex; throw ex; } catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); } finally { resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { requestAttributes.requestCompleted(); } logResult(request, response, failureCause, asyncManager); publishRequestHandledEvent(request, response, startTime, failureCause); } } processRequest(request, response)方法中最关键的又调用了doService(request, response);查看FrameworkServlet类中的doService(request, response),或者是调试跟踪可知,doService(request, response)由子类DispatcherServlet实现。 源码来源: org.springframework.web.servlet.FrameworkServlet.doService(HttpServletRequest request, HttpServletResponse response) /** * Subclasses must implement this method to do the work of request handling, * receiving a centralized callback for GET, POST, PUT and DELETE. * The contract is essentially the same as that for the commonly overridden * {@code doGet} or {@code doPost} methods of HttpServlet. * This class intercepts calls to ensure that exception handling and * event publication takes place. * @param request current HTTP request * @param response current HTTP response * @throws Exception in case of any kind of processing failure * @see javax.servlet.http.HttpServlet#doGet * @see javax.servlet.http.HttpServlet#doPost */ protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception; 查看DispatcherServlet中的doService(HttpServletRequest request, HttpServletResponse response)方法 /** * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch} * for the actual dispatching. */ @Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { logRequest(request); // Keep a snapshot of the request attributes in case of an include, // to be able to restore the original attributes after the include. Map attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap(); Enumeration attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } // Make framework objects available to handlers and view objects. request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); if (this.flashMapManager != null) { FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); } try { doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } } DispatcherServlet的doService()方法中最终调用doDispatch(request, response),查看源码如下: org.springframework.web.servlet.DispatcherServlet.doDispatch() /** * Process the actual dispatching to the handler. * The handler will be obtained by applying the servlet's HandlerMappings in order. * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters * to find the first that supports the handler class. * All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers * themselves to decide which methods are acceptable. * @param request current HTTP request * @param response current HTTP response * @throws Exception in case of any kind of processing failure */ 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 { // 文件上传相关,判断是不是二进制请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // 取得处理当前请求的controller,这里也称为hanlder处理器,第一个步骤的意义就在这里体现了.这里并不是直接返回controller,而是返回的HandlerExecutionChain请求处理器链对象,该对象封装了handler和拦截器interceptors. // Determine handler for the current request. mappedHandler = getHandler(processedRequest); // 如果handler为空,则返回404 if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } //3. 获取处理request的处理器适配器HandlerAdapter // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. 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; } //处理器适配器根据找到,执行handler,返回ModelAndView // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } } 可以看出doDispatch()就是SpringMVC的核心代码了,分析doDispatch(): 2.1、查找处理器映射器HandlerMapping 首先看下处理器映射器HandlerMapping类图: 2021022601-09-HandlerMapping类图 doDispatch()关键代码: HandlerExecutionChain mappedHandler = null; mappedHandler = getHandler(processedRequest); mappedHandler是一个执行链HandlerExecutionChain 对象,这里封装了handler和拦截器interceptors,getHandler(processedRequest)方法就是从处理器映射器HandlerMapping中找到url和controller的对应关系,并返回给前端控制器DispatchServlet。 查看getHandler(processedRequest);源码: /** * Return the HandlerExecutionChain for this request. * Tries all handler mappings in order. * @param request current HTTP request * @return the HandlerExecutionChain, or {@code null} if no handler could be found */ @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; } 调试代码如下: 2021022601-10-DispatchServlet-doDispatch-getHandler执行截图 从代码调试中可以看到handlerMapping中有三个对象: this.handlerMappings = {ArrayList@4662} size = 3 0 = {BeanNameUrlHandlerMapping@4791} 1 = {RequestMappingHandlerMapping@4792} 2 = {RouterFunctionMapping@4793} BeanNameUrlHandlerMapping:初始化时会将urlpath做映射存储(xml); RequestMappingHandlerMapping:初始化时会将Controller中配置@RequestMapping注解的方法做映射存储(注解); RouterFunctionMapping: (这个对象不是太理解) 这也就是为什么要去HandlerMapping找一个Handler了,因为处理器映射器HandlerMapping有不同的实现: 1、xml方式 2、注解方式 接着看getHandler(HttpServletRequest request)方法,先遍历HandlerMappers,查找控制器找到之后就返回执行链HandlerExecutionChain类型的Handler。 2021022601-11-DispatchServlet-doDispatch-getHandler-执行截图 可以看到返回的Handler中,拿到的就是我们自己编码的Controller类,以及拦截器(演示项目中未编写,所以调试汇总返回的Handler最后是0 interceptors) HandlerExecutionChain with [com.bjpowernode.controller.MyController#doSome()] and 0 interceptors 2021022601-12-02-DispatchServlet-doDispatch-getHandler-mappedHandler执行截图2 将正在调试的idea打开自己编写的Controller来对照,发现一致: 2021022601-13-DispatchServlet-doDispatch-getHandler-执行返回结果截图 2.2、根据处理器映射器HandlerMapping返回结果调用处理器适配器HandlerAdapter doDispatch()里面的关键代码: HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 源码如下: /** * Return the HandlerAdapter for this handler object. * @param handler the handler object to find an adapter for * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error. */ protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); } 为什么还要获取处理器适配器HandlerAdapter:与获取处理器映射器HandlerMapping一样,Spring提供了不通的处理器适配器。 调试如下: 2021022601-14-01-DispatchServlet-doDispatch-getHandlerAdapter-执行截图-出方法-在用 查看DEBUG调试模式中getHandlerAdapter()方法在中的: handler、adapter、this.handlerAdapters 2021022601-15-DispatchServlet-doDispatch-getHandlerAdapter-执行结果截图 以下是拷贝的结果: handler handler = {HandlerMethod@4792} "com.bjpowernode.controller.MyController#doSome()" logger = {LogAdapter$JavaUtilLog@4858} bean = {MyController@4859} beanFactory = {DefaultListableBeanFactory@4847} "org.springframework.beans.factory.support.DefaultListableBeanFactory@56b5a4c3: defining beans [myController,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,org.springframework.web.servlet.view.InternalResourceViewResolver#0]; root of factory hierarchy" beanType = {Class@3782} "class com.bjpowernode.controller.MyController" method = {Method@4860} "public org.springframework.web.servlet.ModelAndView com.bjpowernode.controller.MyController.doSome()" bridgedMethod = {Method@4860} "public org.springframework.web.servlet.ModelAndView com.bjpowernode.controller.MyController.doSome()" parameters = {MethodParameter[0]@4861} responseStatus = null responseStatusReason = null resolvedFromHandlerMethod = {HandlerMethod@4863} "com.bjpowernode.controller.MyController#doSome()" interfaceParameterAnnotations = null description = "com.bjpowernode.controller.MyController#doSome()" adapter adapter = {RequestMappingHandlerAdapter@4827} customArgumentResolvers = null argumentResolvers = {HandlerMethodArgumentResolverComposite@4833} initBinderArgumentResolvers = {HandlerMethodArgumentResolverComposite@4834} customReturnValueHandlers = null returnValueHandlers = {HandlerMethodReturnValueHandlerComposite@4835} modelAndViewResolvers = null contentNegotiationManager = {ContentNegotiationManager@4836} messageConverters = {ArrayList@4837} size = 4 requestResponseBodyAdvice = {ArrayList@4838} size = 0 webBindingInitializer = null taskExecutor = {SimpleAsyncTaskExecutor@4839} asyncRequestTimeout = null callableInterceptors = {CallableProcessingInterceptor[0]@4840} deferredResultInterceptors = {DeferredResultProcessingInterceptor[0]@4842} reactiveAdapterRegistry = {ReactiveAdapterRegistry@4844} ignoreDefaultModelOnRedirect = false cacheSecondsForSessionAttributeHandlers = 0 synchronizeOnSession = false sessionAttributeStore = {DefaultSessionAttributeStore@4845} parameterNameDiscoverer = {DefaultParameterNameDiscoverer@4846} beanFactory = {DefaultListableBeanFactory@4847} "org.springframework.beans.factory.support.DefaultListableBeanFactory@56b5a4c3: defining beans [myController,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,org.springframework.web.servlet.view.InternalResourceViewResolver#0]; root of factory hierarchy" sessionAttributesHandlerCache = {ConcurrentHashMap@4848} size = 0 initBinderCache = {ConcurrentHashMap@4849} size = 0 initBinderAdviceCache = {LinkedHashMap@4850} size = 0 modelAttributeCache = {ConcurrentHashMap@4851} size = 0 modelAttributeAdviceCache = {LinkedHashMap@4852} size = 0 order = 2147483647 supportedMethods = null allowHeader = "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS" requireSession = false cacheControl = null cacheSeconds = -1 varyByRequestHeaders = null useExpiresHeader = false useCacheControlHeader = true useCacheControlNoStore = true alwaysMustRevalidate = false servletContext = {ApplicationContextFacade@4754} logger = {LogAdapter$JavaUtilLog@4854} applicationContext = {XmlWebApplicationContext@4665} "WebApplicationContext for namespace 'myweb-servlet', started on Tue Mar 02 23:25:35 CST 2021" messageSourceAccessor = {MessageSourceAccessor@4855} this.handlerAdapters this.handlerAdapters = {ArrayList@4658} size = 4 0 = {HttpRequestHandlerAdapter@4810} 1 = {SimpleControllerHandlerAdapter@4820} //XML方式 2 = {RequestMappingHandlerAdapter@4827} //注解方式 3 = {HandlerFunctionAdapter@4832} 可以看到找到4个处理器适配器。通过DEBUG模式可以看到,此次取到的处理器适配器HandlerAdapter是:RequestMappingHandlerAdapter ha = {RequestMappingHandlerAdapter@4827} 2.3、检查拦截器Interceptor doDispatch()中的关键代码: if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } org.springframework.web.servlet.HandlerExecutionChain#applyPreHandle applyPreHandle(processedRequest, response)源码: /** * Apply preHandle methods of registered interceptors. * @return {@code true} if the execution chain should proceed with the * next interceptor or the handler itself. Else, DispatcherServlet assumes * that this interceptor has already dealt with the response itself. */ 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; } 2.3、处理器适配器HandlerAdapter执行Handler(Controller)返回ModelAndView doDispatch()中的关键代码: mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); DEBUG模式调试,是跳到了: org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle 源码如下: /** * This implementation expects the handler to be an {@link HandlerMethod}. */ @Override @Nullable public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } 再往下看handleInternal(request, response, (HandlerMethod) handler)方法, org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal @Override 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; } 注意,handleInternal(request, response, (HandlerMethod) handler)方法的返回值是ModelAndView ,这里就完成了处理器适配器HandlerAdapter执行Handler(Controller)并将结果ModelAndView返回给前端控制器DistepchServlet 2.4、视图解析器ViewResolver 接上2.3:前端控制器DistepchServlet接收到处理器适配器HandlerAdapter返回的ModelAndView以后,这里分2种情况: (1)、如果ModelAndView里面是逻辑视图 前端控制器DistepchServlet调用视图解析器ViewResolver通过逻辑视图查找真正的视图对象View,并返回给前端控制器DistepchServlet。 (2)、如果ModelAndView里面是非逻辑视图: 如:MappingJackson2JsonView(把当前数据转为为JSON数据,并不需要对视图逻辑名称进行转换) 总结一下: 视图解析器ViewResolver接口主要作用是解析前端控制器DispatcherServlet传递的逻辑视图名,并将解析结果的真正的视图对象View传回给前端控制器DispatcherServlet ViewResolverd的实现类: 2021022601-16-ViewResolver-实现类图-hierarchy ViewResolver的UML: 2021022601-17-ViewResolver-uml图 2.5、视图View 2.5.1、视图对象的作用 (1)、将控制器返回的数据处理渲染,最终返回客户端展示给用户,主要就是完成转发或者是重定向的操作.。 (2)、为了实现视图模型和具体实现技术的解耦(指的是Spring在org.springframework.web.servlet包中定义的抽象View接口),详见2.5.2View接口图。 (3)、视图对象View由视图解析器负责实例化。由于视图是无状态(每一次请求都会创建一个新的view对象)的,所以不会有线程安全的问题. 2.5.2、View接口图 2021022601-18-View-接口方法 2.5.3、View的实现类图 2021022601-19-View-实现类图-hierarchy 2.5.4、View的UML图 ![2021022601-20-01-View-uml(hierarchic group layout)](https://gitee.com/chuchq/blogs-gallery/raw/master/images / 2021/2021022601-20-01-View-uml(hierarchic group layout).png) 2.5.5、常用的View视图类 视图类型 简介 URL视图资源图 InternalResourceView 将JSP或其他资源封装成一个视图。被视图解析器InternalResourceViewResolver默认使用。 JstlView InternalResourceView的子类。如果JSP中使用了JSTL的国际化标签,就需要使用该视图类。 文档视图 AbstractExcelView Excel文档视图的抽象类。 AbstractPdfView PDF文档视图的抽象类 报表视图 ConfigurableJasperReportsView 常用的JasperReports报表视图 JasperReportsHtmlView JasperReportsPdfView JasperReportsXlsView JSON视图 MappingJackson2JsonView 将数据通过Jackson框架的ObjectMapper对象,以JSON方式输出 2.6、其他重要的点 2.6.1、DispatcherServlet.properties DispatcherServlet.properties文件是在SpringMVC架包中: 2021022601-21-jar-DispatchServlet.properties DispatcherServlet.properties内容: # Default implementation classes for DispatcherServlet's strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. org.springframework.web.servlet.LocaleResolver= org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver= org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping= org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ org.springframework.web.servlet.function.support.RouterFunctionMapping org.springframework.web.servlet.HandlerAdapter= org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ org.springframework.web.servlet.function.support.HandlerFunctionAdapter org.springframework.web.servlet.HandlerExceptionResolver= org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator= org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver= org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager= org.springframework.web.servlet.support.SessionFlashMapManager 深圳网站建设www.sz886.com |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |