SpringMVC详解(springmvc consumes)

  本篇文章为你整理了SpringMVC详解(springmvc consumes)的详细内容,包含有springmvc简单介绍 springmvc consumes springmvcioc spring springmvc SpringMVC详解,希望能帮助你了解 SpringMVC详解。

  SpringMVC的介绍

  【1】Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就已包含在Spring框架中。正式名称“ Spring Web MVC”来自其源模块的名称(spring-webmvc),但它通常被称为“ Spring MVC”。

  

  SpringMVC的具体执行流程:

  【1】说明:

   1)Spring MVC 是围绕前端控制器模式设计的,其中:中央 Servlet DispatcherServlet 为请求处理流程提供统一调度,实际工作则交给可配置组件执行。这个模型是灵活的且开放的,我们可以通过自己去定制这些组件从而进行定制自己的工作流。

   2)说白了就是用一个DispatcherServlet 封装了一个Servlet的调度中心, 由调度中心帮我们调用我们的处理方法:在这个过程中调度中心委托给各个组件执行具体工作 ,比如帮我们映射方法请求、帮我解析参数、调用处理方法、响应数据和页面 等

  【2】图示:

  

  

  

  【3】组件说明:

  

DispatcherServlet: 前端调度器 , 负责将请求拦截下来分发到各控制器方法中

 

  HandlerMapping: 负责根据请求的URL和配置@RequestMapping映射去匹配, 匹配到会返回Handler(具体控制器的方法)

  HandlerAdaper: 负责调用Handler-具体的方法- 返回视图的名字 Handler将它封装到ModelAndView(封装视图名,request域的数据)

  ViewReslover: 根据ModelAndView里面的视图名地址去找到具体的jsp封装在View对象中

  View:进行视图渲染(将jsp转换成html内容 --这是Servlet容器的事情了) 最终response到的客户端

 

  

  【4】流程说明:

  

1)用户发送请求至前端控制器DispatcherServlet

 

  2)DispatcherServlet收到请求调用处理器映射器HandlerMapping。

   2.1)处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。

  3)DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter,执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作

  4)执行处理器Handler(Controller,也叫页面控制器)。

   4.1)Handler执行完成返回ModelAndView

   4.2)HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet

  5)DispatcherServlet将ModelAndView传给ViewReslover视图解析器

   5.1)ViewReslover解析后返回具体View

  6)DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。

  7)DispatcherServlet响应用户。

 

  

  SpringMVC请求流程图解:

  

  

  

  执行流程源码解析(我是直接开启SpringBoot里面分析的)

  【1】分析主线流程,DispatcherServlet类#doDispatch方法

  

//DispatcherServlet类#doDispatch方法

 

  //主流程1,执行DispatcherServlet类#doDispatch方法

  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 {

   //检查请求是否是multipart(即文件上传),若是进行相关处理

   processedRequest = checkMultipart(request);

   multipartRequestParsed = (processedRequest != request);

   //通过handermapping映射获取HandlerExecutionChain(处理链中包括了interceptor的前置和后置方法)

   //主流程2,获取HandlerExecutionChain

   mappedHandler = getHandler(processedRequest);

   if (mappedHandler == null) {

   noHandlerFound(processedRequest, response);

   return;

   // 根据处理器(handler及HandlerExecutionChain)获取处理器适配器(处理器适配器是为了提供统一接口进行后续处理,从而支持多种类型的处理器)
// 主流程3的具体地方

   HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

   // Process last-modified header, if supported by the handler.

   String method = request.getMethod();

   boolean isGet = HttpMethod.GET.matches(method);

   if (isGet HttpMethod.HEAD.matches(method)) {

   long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

   if (new ServletWebRequest(request, response).checkNotModified(lastModified) isGet) {

   return;

   //执行chain中拦截器附加的预处理方法,即preHandle方法

   if (!mappedHandler.applyPreHandle(processedRequest, response)) {

   // 返回false就不进行后续处理了

   return;

   // 执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作 ,主流程4的具体地方

   // 执行处理器Handler(Controller,也叫页面控制器)。

   // Handler执行完成返回ModelAndView

   // HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet

   mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

   if (asyncManager.isConcurrentHandlingStarted()) {

   return;

   // 如果没有视图,给你设置默认视图 json忽略

   applyDefaultViewName(processedRequest, mv);

   // 后置拦截器

   mappedHandler.applyPostHandle(processedRequest, response, mv);

   catch (Exception ex) {

   dispatchException = ex;

   catch (Throwable err) {

   // As of 4.3, were processing Errors thrown from handler methods as well,

   // making them available for @ExceptionHandler methods and other scenarios.

   dispatchException = new NestedServletException("Handler dispatch failed", err);

   // DispatcherServlet将ModelAndView传给ViewReslover视图解析器

   // ViewReslover解析后返回具体View

   // DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。

   // DispatcherServlet响应用户。

   // 如果有异常,还会处理异常 ,主流程5,6的具体地方

   processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

   catch (Exception ex) {

   //拦截器afterCompletion处理器

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

  }

 

  

  【2】分析getHandler方法如何返回 处理器执行链HandlerExecutionChain:

  

//分析getHandler

 

  //this.handlerMappings的内容

  //0.RequestMappingHandlerMapping

  //1.BeanNameUrlHandlerMapping

  //2.RouterFunctionMapping

  //3.SimpleUrlHandlerMapping

  //4.WelcomePageHandlerMapping

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

  //调用到了AbstractHandlerMapping类#getHandler方法

  @Override

  @Nullable

  public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

   //getHandlerInternal(request)方法为抽象方法,供子类实现

   //获取到的handler对象一般为bean/HandlerMethod

   Object handler = getHandlerInternal(request);

   //上述找不到则使用默认的处理类,没有设定则返回null,则会返回前台404错误

   if (handler == null) {

   handler = getDefaultHandler();

   if (handler == null) {

   return null;

   // Bean name or resolved handler?

   if (handler instanceof String) {

   String handlerName = (String) handler;

   handler = obtainApplicationContext().getBean(handlerName);

   // Ensure presence of cached lookupPath for interceptors and others

   if (!ServletRequestPathUtils.hasCachedPath(request)) {

   initLookupPath(request);

   //创建处理链对象

   HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

   //针对cros跨域请求的处理

   if (hasCorsConfigurationSource(handler) CorsUtils.isPreFlightRequest(request)) {

   CorsConfiguration config = getCorsConfiguration(handler, request);

   if (getCorsConfigurationSource() != null) {

   CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);

   config = (globalConfig != null ? globalConfig.combine(config) : config);

   if (config != null) {

   config.validateAllowCredentials();

   executionChain = getCorsHandlerExecutionChain(request, executionChain, config);

   return executionChain;

  }

 

  【2.1】分析AbstractHandlerMapping类#getHandler方法

  【2.1.1】如何获取handler对象【一般为bean/HandlerMethod】

  

//RequestMappingInfoHandlerMapping类#getHandlerInternal方法

 

  //因为它是RequestMappingHandlerMapping的父类

  @Override

  @Nullable

  protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {

   request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);

   try {

   //调用父类AbstractHandlerMethodMapping类

   return super.getHandlerInternal(request);

   finally {

   ProducesRequestCondition.clearMediaTypesAttribute(request);

  //调用到AbstractHandlerMethodMapping类getHandlerInternal方法

  //针对HandlerMethod的获取

  protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {

   //获取访问的路径,一般类似于request.getServletPath()返回不含contextPath的访问路径

   String lookupPath = initLookupPath(request);

   //获取读锁

   this.mappingRegistry.acquireReadLock();

   try {

   //获取HandlerMethod作为handler对象,这里涉及到路径匹配的优先级

   //优先级:精确匹配 最长路径匹配 扩展名匹配

   HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);

   //HandlerMethod内部含有bean对象,其实指的是对应的Controller

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

   finally {

   //释放读锁

   this.mappingRegistry.releaseReadLock();

  }

 

  【2.1.2】如何创建处理链

  

//创建处理器链的方法

 

  protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {

   /创建HandlerExecutionChain

   HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

   //与请求url进行匹配,满足的才加入

   for (HandlerInterceptor interceptor : this.adaptedInterceptors) {

   if (interceptor instanceof MappedInterceptor) {

   MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;

   if (mappedInterceptor.matches(request)) {

   chain.addInterceptor(mappedInterceptor.getInterceptor());

   else {

   chain.addInterceptor(interceptor);

   return chain;

  }

 

  

  【3】分析getHandlerAdapter寻找的处理器适配器

  

//分析getHandlerAdapter

 

  //this.handlerAdapters的内容

  //0.RequestMappingHandlerAdapter

  //1.HandlerFunctionAdapter

  //2.HttpRequestHandlerAdapter

  //3.SimpleControllerHandlerAdapter

  protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {

   if (this.handlerAdapters != null) {

   for (HandlerAdapter adapter : this.handlerAdapters) {

   if (adapter.supports(handler)) {

   //所以一般返回的也就是RequestMappingHandlerAdapter

   return adapter;

   throw new ServletException(...);

  //因为RequestMappingHandlerAdapter没有重写故调用父类的

  //调用AbstractHandlerMethodAdapter类#supports方法

  @Override

  public final boolean supports(Object handler) {

   //如果是类的方法的话默认是true

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

  }

 

  

  【4】分析mappedHandler.applyPreHandle前置处理器与mappedHandler.applyPostHandle后置处理器

  

//分析mappedHandler.applyPreHandle前置处理器与mappedHandler.applyPostHandle后置处理器

 

  //前置处理器是从0到size

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

   for (int i = 0; i this.interceptorList.size(); i++) {

   HandlerInterceptor interceptor = this.interceptorList.get(i);

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

   triggerAfterCompletion(request, response, null);

   return false;

   this.interceptorIndex = i;

   return true;

  //前置处理器是从size到0

  void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {

   for (int i = this.interceptorList.size() - 1; i i--) {

   HandlerInterceptor interceptor = this.interceptorList.get(i);

   interceptor.postHandle(request, response, this.handler, mv);

  }

 

  

  【5】分析ha.handle(processedRequest, response, mappedHandler.getHandler());,如何进行调用控制器里面的方法

  

//AbstractHandlerMethodAdapter类#handle方法

 

  //因为适配器RequestMappingHandlerAdapter类没有所以定位到了父类

  public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

   return handleInternal(request, response, (HandlerMethod) handler);

  //RequestMappingHandlerAdapter类#handleInternal方法

  @Override

  protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

   ModelAndView mav;

   // 检查当前请求的method是否为支持的method(默认Null,可通过继承AbstractController设置supportedMethods)

   // 检查当前请求是否必须session (默认false,可通过继承AbstractController设置requireSession)

   checkRequest(request);

   * 判断当前是否需要支持在同一个session中只能线性地处理请求

   * 因为锁是通过 synchronized 是 JVM 进程级,所以在分布式环境下,

   * 无法达到同步相同 Session 的功能。默认情况下,synchronizeOnSession 为 false

   if (this.synchronizeOnSession) {

   // 获取当前请求的session对象

   HttpSession session = request.getSession(false);

   if (session != null) {

   // 为当前session生成一个唯一的可以用于锁定的key

   Object mutex = WebUtils.getSessionMutex(session);

   synchronized (mutex) {

   // 对HandlerMethod进行参数等的适配处理,并调用目标handler

   mav = invokeHandlerMethod(request, response, handlerMethod);

   else {

   // 如果当前不存在session,则直接对HandlerMethod进行适配

   mav = invokeHandlerMethod(request, response, handlerMethod);

   else {

   // 这般都会走这里,重点反射调用

   // 如果当前不需要对session进行同步处理,则直接对HandlerMethod进行适配

   mav = invokeHandlerMethod(request, response, handlerMethod);

   //判断当前请求头中是否包含Cache-Control请求头,如果不包含,则对当前response进行处理

   if (!response.containsHeader(HEADER_CACHE_CONTROL)) {

   // 如果当前SessionAttribute中存在配置的attributes,则为其设置过期时间。

   // 这里SessionAttribute主要是通过@SessionAttribute注解生成的

   if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {

   applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);

   else {

   // 如果当前不存在SessionAttributes,则判断当前是否存在Cache-Control设置,

   // 如果存在,则按照该设置进行response处理,如果不存在,则设置response中的

   // Cache的过期时间为-1,即立即失效

   prepareResponse(response);

   return mav;

  }

 

  【5.1】分析invokeHandlerMethod方法怎么做【先是参数处理器,再是生成容器,然后去反射调用,最后将结果放入容器】

  

@Nullable

 

  protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

   // 把我们的请求req resp包装成 ServletWebRequest

   ServletWebRequest webRequest = new ServletWebRequest(request, response);

   try {

   // 获取容器中全局配置的InitBinder和当前HandlerMethod所对应的Controller中

   // 配置的InitBinder,用于进行参数的绑定

   WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

   // 获取容器中全局配置的ModelAttribute和当前HandlerMethod所对应的Controller 中配置的ModelAttribute,

   // 这些配置的方法将会在目标方法调用之前进行调用

   ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

   // 封装handlerMethod,会在调用前解析参数、调用后对返回值进行处理

   ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);

   if (this.argumentResolvers != null) {

   // 让invocableMethod拥有参数解析能力

   invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);

   if (this.returnValueHandlers != null) {

   // 让invocableMethod拥有返回值处理能力

   invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);

   // 让invocableMethod拥有InitBinder解析能力

   invocableMethod.setDataBinderFactory(binderFactory);

   // 设置ParameterNameDiscoverer,该对象将按照一定的规则获取当前参数的名称

   invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

   // 创建ModelAndView处理容器

   ModelAndViewContainer mavContainer = new ModelAndViewContainer();

   // 将request的Attribute复制一份到ModelMap

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

   // 调用我们标注了@ModelAttribute的方法,主要是为我们的目标方法预加载

   modelFactory.initModel(webRequest, mavContainer, invocableMethod);

   // 重定向的时候,忽略model中的数据 默认false

   mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

   // 获取当前的AsyncWebRequest,这里AsyncWebRequest的主要作用是用于判断目标

   // handler的返回值是否为WebAsyncTask或DeferredResult,如果是这两种中的一种,

   // 则说明当前请求的处理应该是异步的。所谓的异步,指的是当前请求会将Controller中

   // 封装的业务逻辑放到一个线程池中进行调用,待该调用有返回结果之后再返回到response中。

   // 这种处理的优点在于用于请求分发的线程能够解放出来,从而处理更多的请求,提高吞吐。

   // 只有待目标任务完成之后才会回来将该异步任务的结果返回。

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

   asyncWebRequest.setTimeout(this.asyncRequestTimeout);

   // 封装异步任务的线程池、request、interceptors到WebAsyncManager中

   WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

   asyncManager.setTaskExecutor(this.taskExecutor);

   asyncManager.setAsyncWebRequest(asyncWebRequest);

   asyncManager.registerCallableInterceptors(this.callableInterceptors);

   asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

   // 这里就是用于判断当前请求是否有异步任务结果的,如果存在,则对异步任务结果进行封装

   if (asyncManager.hasConcurrentResult()) {

   Object result = asyncManager.getConcurrentResult();

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

   asyncManager.clearConcurrentResult();

   LogFormatUtils.traceDebug(logger, traceOn - {

   String formatted = LogFormatUtils.formatValue(result, !traceOn);

   return "Resume with async result [" + formatted + "]";

   invocableMethod = invocableMethod.wrapConcurrentResult(result);

   // 对请求参数进行处理,调用目标HandlerMethod,并且将返回值封装为一个ModelAndView对象

   invocableMethod.invokeAndHandle(webRequest, mavContainer);

   if (asyncManager.isConcurrentHandlingStarted()) {

   return null;

   // 对封装的ModelAndView进行处理,主要是判断当前请求是否进行了重定向,如果进行了重定向,还会判断是否需要将FlashAttributes封装到新的请求中

   return getModelAndView(mavContainer, modelFactory, webRequest);

   finally {

   webRequest.requestCompleted();

  }

 

  

  【5.1.1】分析invocableMethod.invokeAndHandle怎么反射调用

  

//ServletInvocableHandlerMethod类#invokeAndHandle方法

 

  public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {

   // 真正的调用我们的目标对象

   Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

   // 设置相关的返回状态

   setResponseStatus(webRequest);

   // 如果请求处理完成,则设置requestHandled属性

   if (returnValue == null) {

   if (isRequestNotModified(webRequest) getResponseStatus() != null mavContainer.isRequestHandled()) {

   disableContentCachingIfNecessary(webRequest);

   mavContainer.setRequestHandled(true);

   return;

   // 如果请求失败,但是有错误原因,那么也会设置requestHandled属性

   else if (StringUtils.hasText(getResponseStatusReason())) {

   mavContainer.setRequestHandled(true);

   return;

   mavContainer.setRequestHandled(false);

   Assert.state(this.returnValueHandlers != null, "No return value handlers");

   try {

   // 遍历当前容器中所有ReturnValueHandler,判断哪种handler支持当前返回值的处理,

   // 如果支持,则使用该handler处理该返回值

   this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);

   catch (Exception ex) {

   throw ex;

  //InvocableHandlerMethod类#invokeForRequest方法

  public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {

   // 获取我们目标方法入参的值

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

   // 反射调用 ,里面主要就是 method.invoke(getBean(), args) 来进行反射调用

   return doInvoke(args);

  }

 

  

  【5.1.2】分析 对封装的ModelAndView进行处理

  

//RequestMappingHandlerAdapter类#getModelAndView方法

 

  private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,

   ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

   modelFactory.updateModel(webRequest, mavContainer);

   if (mavContainer.isRequestHandled()) {

   return null;

   ModelMap model = mavContainer.getModel();

   ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());

   if (!mavContainer.isViewReference()) {

   mav.setView((View) mavContainer.getView());

   if (model instanceof RedirectAttributes) {

   Map String, ? flashAttributes = ((RedirectAttributes) model).getFlashAttributes();

   HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

   if (request != null) {

   RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);

   return mav;

  }

 

  

  【6】分析processDispatchResult方法对返回结果的处理

  

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {

 

   boolean errorView = false;

   // 异常处理

   if (exception != null) {

   if (exception instanceof ModelAndViewDefiningException) {

   logger.debug("ModelAndViewDefiningException encountered", exception);

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

   else {

   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 (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

   // Concurrent handling started during a forward

   return;

   if (mappedHandler != null) {

   // Exception (if any) is already handled..
// 拦截器的后置处理

   mappedHandler.triggerAfterCompletion(request, response, null);

  }

 

  

  【6.1】分析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 != null ? this.localeResolver.resolveLocale(request) : request.getLocale());

   response.setLocale(locale);

   View view;

   String viewName = mv.getViewName();

   if (viewName != null) {

   // 解析视图名

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

   if (view == null) {

   throw new ServletException(...);

   else {

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

   view = mv.getView();

   if (view == null) { throw new ServletException(...); }

   // Delegate to the View object for rendering.

   try {

   if (mv.getStatus() != null) {

   request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, mv.getStatus());

   response.setStatus(mv.getStatus().value());

   // 进行视图渲染 ,调用的是 AbstractView类的方法

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

   catch (Exception ex) { throw ex; }

  }

 

  

  源码解析注解@RequestMapping

  【1】@RequestMapping解析

  【1.1】说明:

   1)明确一点:@RequestMapping是通过RequestMappingHandlerMapping负责解析。

   2)HandlerMapping便是负责根据请求URI 映射 到对应的handler方法。而RequestMappingHandlerMapping是HandlerMapping的其中一个实现类, 负责根据@RequestMapping注解进行映射。

   3)所以HandlerMapping有很多其他实现类,RequestMappingHandlerMapping是最常用的。HandlerMapping可分为2个过程:1解析、2映射

  【1.2】分析RequestMappingHandlerMapping类

   1)基于继承关系可以发现它实现了InitializingBean接口

   2)分析afterPropertiesSet方法做了什么

  

@Override

 

  @SuppressWarnings("deprecation")

  public void afterPropertiesSet() {

   //这里都是一些设置配置

   this.config = new RequestMappingInfo.BuilderConfiguration();

   this.config.setTrailingSlashMatch(useTrailingSlashMatch());

   this.config.setContentNegotiationManager(getContentNegotiationManager());

   if (getPatternParser() != null) {

   this.config.setPatternParser(getPatternParser());

   else {

   this.config.setSuffixPatternMatch(useSuffixPatternMatch());

   this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());

   this.config.setPathMatcher(getPathMatcher());

   //调用父类AbstractHandlerMethodMapping类的afterPropertiesSet方法

   super.afterPropertiesSet();

  //父类AbstractHandlerMethodMapping类的afterPropertiesSet方法

  public void afterPropertiesSet() {

   initHandlerMethods();

  //AbstractHandlerMethodMapping类#initHandlerMethods方法

  protected void initHandlerMethods() {

   // 获得所有候选beanName—— 当前容器所有的beanName

   for (String beanName : getCandidateBeanNames()) {

   if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {

   // 处理候选bean——即解析@RequestMapping和映射路径

   processCandidateBean(beanName);

   // 解析完所有@RequestMapping的时候调用,输出日志

   handlerMethodsInitialized(getHandlerMethods());

  }

 

  

  【1.2.1】分析processCandidateBean方法怎么处理的

  

protected void processCandidateBean(String beanName) {

 

   Class ? beanType = null;

   try {

   beanType = obtainApplicationContext().getType(beanName);

   catch (Throwable ex) {..省略日志..}

   // 这一步判断是关键 是否有Controller 或 RequestMapping注解

   if (beanType != null isHandler(beanType)) {

   // 解析HandlerMethods

   detectHandlerMethods(beanName);

  protected void detectHandlerMethods(Object handler) {

   Class ? handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());

   if (handlerType != null) {

   Class ? userType = ClassUtils.getUserClass(handlerType);

   // 循环所有方法

   Map Method, T methods = MethodIntrospector.selectMethods(userType,

   (MethodIntrospector.MetadataLookup T ) method - {

   try {

   return getMappingForMethod(method, userType);

   catch (Throwable ex) {..省略异常..}

   ..省略日志..

   //循环注册

   methods.forEach((method, mapping) - {

   Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);

   registerHandlerMethod(handler, invocableMethod, mapping);

  }

 

  【1.2.1.1】解析流程

  

//调用回子类RequestMappingHandlerMapping类#getMappingForMethod方法

 

  protected RequestMappingInfo getMappingForMethod(Method method, Class ? handlerType) {

   // 如果方法上面有@RequestMapping:解析出RequestMappingInfo

   // RequestMappingInfo 是用来在请求的时候做匹对的

   RequestMappingInfo info = createRequestMappingInfo(method);

   if (info != null) {

   // 如果方法上面有@RequestMapping,看看类上面是不是有@RequestMapping

   RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);

   // 类上面也有@RequestMapping 那就合并

   // 比如 类:/user 方法:/info 合并为 /user/info

   if (typeInfo != null) {

   info = typeInfo.combine(info);

   // 合并前缀 5.1新增 默认null

   // 可通过 WebMvcConfigurer#configurePathMatch 进行定制

   String prefix = getPathPrefix(handlerType);

   if (prefix != null) {

   info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);

   return info;

  }

 

  

  【1.2.1.2】注册流程

  

//调用回子类RequestMappingHandlerMapping类#registerHandlerMethod方法

 

  protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {

   super.registerHandlerMethod(handler, method, mapping);

   updateConsumesCondition(mapping, method);

  //父类AbstractHandlerMethodMapping类#registerHandlerMethod方法

  //其中private final MappingRegistry mappingRegistry = new MappingRegistry();

  protected void registerHandlerMethod(Object handler, Method method, T mapping) {

   this.mappingRegistry.register(mapping, handler, method);

  //两大存储容器

  //private final Map T, MappingRegistration T registry = new HashMap ();

  //private final MultiValueMap String, T pathLookup = new LinkedMultiValueMap ();

  //pathLookup存储【path, mapping】

  //registry存储【mappin。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: