SpringMVC源码分析

目录

 

1.Tomcat和Servlet

1.1servlet是什么?

1.2Servlet 与 Servlet 容器(Tomcat)的关系

1.3Servlet接口设计

1.4servlet生命周期

2.SpringMVC

2.1DispatcherServlet的初始化准备工作

2.2DispatcherServlet接收用户请求

2.2.1HandlerMapping为请求匹配处理器执行链HandlerExecutionChain

2.2.2根据处理器方法handlerMethod匹配处理器适配器HandlerAdapter

2.2.3调用处理器执行链 HandlerExecutionChain

2.2.4处理返回结果


1.Tomcat和Servlet

1.1servlet是什么?

Servlet是用Java编写的Server端程序,它与协议和平台无关。Servlet运行于Java-enabled Web Server中。Java Servlet可以动态地扩展Server的能力,并采用请求-响应模式提供Web服务。最早支持Servlet技术的是JavaSoft的Java Web Server。此后,一些其它的基于Java的Web Server开始支持标准的Servlet API。Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容。

A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol.
 

1.2Servlet 与 Servlet 容器(Tomcat)的关系

 
要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力。虽然它们是彼此依存的,但是又相互独立发展,这一切都是为了适应工业化生产的结果。从技术角度来说是为了解耦,通过标准化接口来相互协作。后端服务器Tomcat(servlet容器)提供服务,本质上最终是servlet为用户请求提供服务。
 

1.3Servlet接口设计

核心服务方法service,处理客户端请求

public interface Servlet {
    public void init(ServletConfig config) throws ServletException;
    
    public ServletConfig getServletConfig();
    
    public void service(ServletRequest req, ServletResponse res)
   throws ServletException, IOException;
   
    public String getServletInfo();

    public void destroy();
}

1.4servlet生命周期

  1. The servlet is constructed, then initialized with the init method.
  2. Any calls from clients to the service method are handled.
  3. The servlet is taken out of service, then destroyed with the destroy method, then garbage collected and finalized.

2.SpringMVC

springMVC定义了  DispatcherServlet作为前端控制器,统一接收所有的客户端请求并转发。经典配置:
<servlet>
  <servlet-name>dispatcherServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <!--配置读取springmvc.xml的文件位置-->
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc.xml</param-value>
  </init-param>
  <!-- 配置初始参数,启动应用时创建Servlet对象-->
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>dispatcherServlet</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

请求执行流程图

2.1DispatcherServlet的初始化准备工作

第一次请求的时候,dispatcherservlet会进行初始化。代码入口在Tomcat中org.apache.catalina.core.StandardWrapper#initServlet,这里先不讨论Tomcat源码,从DispatcherServlet开始看

org.springframework.web.servlet.DispatcherServlet#initStrategies
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);

HandlerMapping的初始化【initHandlerMappings从applicationContext查找并加载HandlerMapping实现,存放到handlerMappings里面。其中我们最常见的@Controller注解,使用的是RequestMappingHandlerMapping 。

HandlerAdapter的初始化【initHandlerAdapters】过程几乎完全相同, 其中我们最常见的@Controller注解形式使用的是RequestMappingHandlerAdapter
private void initHandlerMappings(ApplicationContext context) {
   this.handlerMappings = null;


   if (this.detectAllHandlerMappings) {
      // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
      // 从容器中查找并实例化HandlerMapping的实现类,一部分是从DispatcherServlet.properties中加载,一部分来源于程序员指定。
      // 最常用的使用@ReuqestMapping形式使用的工具类RequestMappingHandlerMapping    
      Map<String, HandlerMapping> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
      if (!matchingBeans.isEmpty()) {
         this.handlerMappings = new ArrayList<>(matchingBeans.values());
         // handlerMapping排序
         // We keep HandlerMappings in sorted order.
         AnnotationAwareOrderComparator.sort(this.handlerMappings);
      }
   }
   else {
      try {
         HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
         this.handlerMappings = Collections.singletonList(hm);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Ignore, we'll add a default HandlerMapping later.
      }
   }


   // Ensure we have at least one HandlerMapping, by registering
   // a default HandlerMapping if no other mappings are found.
   if (this.handlerMappings == null) {
      this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
      if (logger.isTraceEnabled()) {
         logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
               "': using default strategies from DispatcherServlet.properties");
      }
   }
}

RequestMappingHandlerMapping的初始化【afterPropertiesSet

查找控制器handler的方法并注册url映射关系
protected void initHandlerMethods() {
   // 拿到所有的beanName 
   for (String beanName : getCandidateBeanNames()) {
      if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
         // 处理所有的候选bean
         processCandidateBean(beanName);
      }
   }
   // handler方法初始化,仅仅打印一下有多少个方法映射 
   handlerMethodsInitialized(getHandlerMethods());
}

处理候选bean

protected void processCandidateBean(String beanName) {
   Class<?> beanType = null;
   try {
      beanType = obtainApplicationContext().getType(beanName);
   }
   catch (Throwable ex) {
      // An unresolvable bean type, probably from a lazy bean - let's ignore it.
      if (logger.isTraceEnabled()) {
         logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
      }
   }
   // 判断是否是控制器handler【controller】 
   if (beanType != null && isHandler(beanType)) {
      detectHandlerMethods(beanName);
   }
}

是否是控制器,如果带controller注解或RequestMapping注解就认为是控制器

protected boolean isHandler(Class<?> beanType) {
   return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
         AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

解析控制器的方法

protected void detectHandlerMethods(Object handler) {
   // 根据控制器名称beanName获取class类对象 
   Class<?> handlerType = (handler instanceof String ?
         obtainApplicationContext().getType((String) handler) : handler.getClass());

    
   if (handlerType != null) {
      // 如果是CGLIB代理,拿到被代理对象  
      Class<?> userType = ClassUtils.getUserClass(handlerType);
      // 筛选所有方法  
      Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
            (MethodIntrospector.MetadataLookup<T>) method -> {
               try {
                  // 解析所有方法上的@RequestMapping属性,放到map里面  
                  return getMappingForMethod(method, userType);
               }
               catch (Throwable ex) {
                  throw new IllegalStateException("Invalid mapping on handler class [" +
                        userType.getName() + "]: " + method, ex);
               }
            });
      if (logger.isTraceEnabled()) {
         logger.trace(formatMappings(userType, methods));
      }
      methods.forEach((method, mapping) -> {
         // 检查方法的可见性
         Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
         // 注册控制器方法
         registerHandlerMethod(handler, invocableMethod, mapping);
      });
   }
}

解析方法上的RequestMapping属性 getMappingForMethod

protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
   // 解析方法上的@RequestMapping注解 
   RequestMappingInfo info = createRequestMappingInfo(method);
   if (info != null) {
      // 解析类上的@RequestMapping注解
      RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
      if (typeInfo != null) {
         // 属性合并 比如把类上的请求路径和方法上的路径结合起来
         info = typeInfo.combine(info);
      }
      String prefix = getPathPrefix(handlerType);
      if (prefix != null) {
         info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
      }
   }
   return info;
}

注册控制器方法 registerHandlerMethod

protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
   // 注册url和方法映射 
   super.registerHandlerMethod(handler, method, mapping);
   // 设置@RequestBody是否需要 
   updateConsumesCondition(mapping, method);
}

往MappingRegistry里面注册方法

public void register(T mapping, Object handler, Method method) {
   // Assert that the handler method is not a suspending one.
   if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
      Class<?>[] parameterTypes = method.getParameterTypes();
      if ((parameterTypes.length > 0) && "kotlin.coroutines.Continuation".equals(parameterTypes[parameterTypes.length - 1].getName())) {
         throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
      }
   }
   this.readWriteLock.writeLock().lock();
   try {
      // 创建handlerMethod对象,保存控制器和方法
      HandlerMethod handlerMethod = createHandlerMethod(handler, method);
      validateMethodMapping(handlerMethod, mapping);
      // 保存RequestMappingInfo和控制器方法的映射
      this.mappingLookup.put(mapping, handlerMethod);


      List<String> directUrls = getDirectUrls(mapping);
      for (String url : directUrls) {
         // 保存请求url和RequestMappingInfo的映射
         this.urlLookup.add(url, mapping);
      }


      String name = null;
      if (getNamingStrategy() != null) {
         name = getNamingStrategy().getName(handlerMethod, mapping);
         addMappingName(name, handlerMethod);
      }


      CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
      if (corsConfig != null) {
         this.corsLookup.put(handlerMethod, corsConfig);
      }

      // 注册映射关系  
      this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
   }
   finally {
      this.readWriteLock.writeLock().unlock();
   }
}

总结: RequestMappingHandlerMapping在初始化的时候扫描容器中的所有类,带@Controller注解或@RequestMapping注解的被认为是控制器,扫描控制器的所有方法,解析@RequestMapping属性,把类上的url和方法上的url结合起来作为key,具体控制器的方法作为value,存储映射关系到RequestMappingHandlerMapping的MappingRegistry里面

 

2.2DispatcherServlet接收用户请求

以Get请求为例,方法入口

@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

   processRequest(request, response);
}

跳过准备工作进入主流程org.springframework.web.servlet.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 {
         processedRequest = checkMultipart(request);
         multipartRequestParsed = (processedRequest != request);


         // Determine handler for the current request.
         // 为当前请求匹配处理器执行链,遍历handlerMappings里面的每一个handlerMapping,如果handlerMapping能匹配到当前请求的处理器执行链就返回
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null) {
            noHandlerFound(processedRequest, response);
            return;
         }


         // 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;
         }


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

2.2.1HandlerMapping为请求匹配处理器执行链HandlerExecutionChain

以最常见的RequestMappingHandlerMapping为例

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   // 拿到内部控制器handler【Controller】 
   Object handler = getHandlerInternal(request);
   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);
   }

   // 包装控制器执行链 
   HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);


   if (logger.isTraceEnabled()) {
      logger.trace("Mapped to " + handler);
   }
   else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
      logger.debug("Mapped to " + executionChain.getHandler());
   }


   if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
      CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
      CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
      config = (config != null ? config.combine(handlerConfig) : handlerConfig);
      executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
   }


   return executionChain;
}

为请求匹配内部控制方法

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
   // 从请求中拿到url路径 
   String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
   request.setAttribute(LOOKUP_PATH, lookupPath);
   // 拿到可重入的读锁 
   this.mappingRegistry.acquireReadLock();
   try {
      HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
      // 把方法对应的控制器对象从容器中获取出来,也放进handlerMethod  
      return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
   }
   finally {
      // 释放锁  
      this.mappingRegistry.releaseReadLock();
   }
}

lookupHandlerMethod

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
   List<Match> matches = new ArrayList<>();
   //  从mappingRegistry的urlLookup里面通过url拿到RequestMappingInfo
    // 直接路径匹配【url等值匹配】
   List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
   if (directPathMatches != null) {
      // 把RequestMappingInfo -> handlerMethod的映射存储在matches里面  
      addMatchingMappings(directPathMatches, matches, request);
   }
   if (matches.isEmpty()) {
      // 如果没有url等值匹配到的方法,遍历所有RequestMapping进行匹配  
      // No choice but to go through all mappings...
      addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
   }

   // 匹配到方法 
   if (!matches.isEmpty()) {
      Match bestMatch = matches.get(0);
      // 如果匹配到多个方法,排序比较优先级  
      if (matches.size() > 1) {
         Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
         matches.sort(comparator);
         bestMatch = matches.get(0);
         if (logger.isTraceEnabled()) {
            logger.trace(matches.size() + " matching mappings: " + matches);
         }
         if (CorsUtils.isPreFlightRequest(request)) {
            return PREFLIGHT_AMBIGUOUS_MATCH;
         }
         Match secondBestMatch = 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里面  
      request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
      // 处理请求参数放到request里面  
      handleMatch(bestMatch.mapping, lookupPath, request);
      // 返回匹配好的方法  
      return bestMatch.handlerMethod;
   }
   else {
      // 没有找到对应的控制器方法  
      return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
   }
}

把控制器和拦截器包装成执行链

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
   // 把handler包装成执行链对象,暂时里面只有控制器 
   HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
         (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    
   // 从request里面拿到url 
   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;
}

拦截器执行链 HandlerExecutionChain结构

2.2.2根据处理器方法handlerMethod匹配处理器适配器HandlerAdapter

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

因为我们这里使用的是最常用的@Controller注解形式,所以第一个handlerAdapter就会匹配上【匹配过程略过】,看一下RequestMappingHandlerAdapter的support实现

public final boolean supports(Object handler) {
   return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
protected boolean supportsInternal(HandlerMethod handlerMethod) {
   return true;
}

只要传进来的是handlerMethod就行

 

2.2.3调用处理器执行链 HandlerExecutionChain

调用过程示意图
 
// 调用拦截器前置方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
   return;
}

//  调用控制器方法
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());


if (asyncManager.isConcurrentHandlingStarted()) {
   return;
}


applyDefaultViewName(processedRequest, mv);
// 调用拦截器后置方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
 
 
前置方法
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;
}

后置方法

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


   HandlerInterceptor[] interceptors = getInterceptors();
   if (!ObjectUtils.isEmpty(interceptors)) {
      for (int i = interceptors.length - 1; i >= 0; i--) {
         HandlerInterceptor interceptor = interceptors[i];
         interceptor.postHandle(request, response, this.handler, mv);
      }
   }
}

调用控制器方法

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

最终反射调用控制器方法

protected Object doInvoke(Object... args) throws Exception {
    ReflectionUtils.makeAccessible(this.getBridgedMethod());


    try {
        return this.getBridgedMethod().invoke(this.getBean(), args);
    } catch (IllegalArgumentException var4) {
        this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args);
        String text = var4.getMessage() != null ? var4.getMessage() : "Illegal argument";
        throw new IllegalStateException(this.formatInvokeError(text, args), var4);
    } catch (InvocationTargetException var5) {
        Throwable targetException = var5.getTargetException();
        if (targetException instanceof RuntimeException) {
            throw (RuntimeException)targetException;
        } else if (targetException instanceof Error) {
            throw (Error)targetException;
        } else if (targetException instanceof Exception) {
            throw (Exception)targetException;
        } else {
            throw new IllegalStateException(this.formatInvokeError("Invocation failure", args), targetException);
        }
    }
}

2.2.4处理返回结果

随着微服务的发展,现在项目大多数都是前后端分离,不再需要使用视图解析器解析视图和渲染页面返回了,大多数时候只需要把执行结果以json形式返回给前端。
 
handleReturnValue
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    // 根据返回值类型,选择合适的处理器,这里是RequestResponseBodyMethodProcessor
    HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
    if (handler == null) {
        throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    } else {
        // 处理返回值
        handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }
}

最终由MessageConverter写会给客户端浏览器

protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
   HttpHeaders headers = outputMessage.getHeaders();
   if (this.writeAcceptCharset && headers.get(HttpHeaders.ACCEPT_CHARSET) == null) {
      headers.setAcceptCharset(getAcceptedCharsets());
   }
   Charset charset = getContentTypeCharset(headers.getContentType());
   StreamUtils.copy(str, charset, outputMessage.getBody());
}

Write and flush

public static void copy(String in, Charset charset, OutputStream out) throws IOException {
   Assert.notNull(in, "No input String specified");
   Assert.notNull(charset, "No Charset specified");
   Assert.notNull(out, "No OutputStream specified");


   Writer writer = new OutputStreamWriter(out, charset);
   writer.write(in);
   writer.flush();
}

 

 
 
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值