zoukankan      html  css  js  c++  java
  • Spring MVC之适配器的获取及执行(RequestMappingHandlerAdapter)

    首先看下doDispatch()方法如何找到适合的适配器来执行方法的:

     1     protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
     2         Iterator i$ = this.handlerAdapters.iterator();
     3 
     4         HandlerAdapter ha;
     5         do {
     6             if (!i$.hasNext()) {
     7                 throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
     8             }
     9 
    10             ha = (HandlerAdapter)i$.next();
    11             if (this.logger.isTraceEnabled()) {
    12                 this.logger.trace("Testing handler adapter [" + ha + "]");
    13             }
    14         } while(!ha.supports(handler)); //遍历初始化时候保存好的适配器,通过执行每个适配器的supports方法,如果支持就是他了。
    15 
    16         return ha;
    17     }

    注: 这块也有点责任链模式的意思...

    下面看下RequestMappingHandlerAdapter是怎么实现support方法的,看之前先上类图。

    实际上support方法是在AbstractHandlerMethodAdapter这个父类实现的,然后给自己留个钩子方法,让子类实现

    1     public final boolean supports(Object handler) { 
    2         return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler);
    3     }
    4 
    5     protected abstract boolean supportsInternal(HandlerMethod var1); //钩子方法

    这里RequestMappingHandlerAdapter的supportInternal直接是返回的true,估计后续扩展其他子类可能会复杂些,这就是设计模式的好处。

    这样就找到了合适的适配器,下面来看执行:

     1     protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     2         HttpServletRequest processedRequest = request;
     3         HandlerExecutionChain mappedHandler = null;
     4         boolean multipartRequestParsed = false;
     5         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
     6 
     7         try {
     8             try {
     9                 ModelAndView mv = null;
    10                 Exception dispatchException = null;
    11 
    12                 try {
    13                     processedRequest = this.checkMultipart(request);
    14                     multipartRequestParsed = processedRequest != request;
    15                     mappedHandler = this.getHandler(processedRequest, false); //获取处理器
    16                     if (mappedHandler == null || mappedHandler.getHandler() == null) {
    17                         this.noHandlerFound(processedRequest, response);
    18                         return;
    19                     }
    20 
    21                     HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); //获取适配器
    22                     String method = request.getMethod();
    23                     boolean isGet = "GET".equals(method);
    24                     if (isGet || "HEAD".equals(method)) {
    25                         long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
    26                         if (this.logger.isDebugEnabled()) {
    27                             String requestUri = urlPathHelper.getRequestUri(request);
    28                             this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
    29                         }
    30 
    31                         if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
    32                             return;
    33                         }
    34                     } //这一块是处理重复请求??? 有大神知道请留言....
    35 
    36                     if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    37                         return;
    38                     } //执行拦截器的preHandle方法
    39 
    40                     try {
    41                         mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //执行真正的Controller方法,就是我们的方法
    42                     } finally {
    43                         if (asyncManager.isConcurrentHandlingStarted()) {
    44                             return;
    45                         }
    46 
    47                     }
    48 
    49                     this.applyDefaultViewName(request, mv); //设置视图名称
    50                     mappedHandler.applyPostHandle(processedRequest, response, mv); //执行拦截器的postHandle方法
    51                 } catch (Exception var28) {
    52                     dispatchException = var28;
    53                 }
    54 
    55                 this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);//渲染视图
    56             } catch (Exception var29) {
    57                 this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29);
    58             } catch (Error var30) {
    59                 this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30);
    60             }
    61 
    62         } finally {
    63             if (asyncManager.isConcurrentHandlingStarted()) {
    64                 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); //执行拦截器的afterConcurrentHandlingStarted
    65                 return;
    66             } else {
    67                 if (multipartRequestParsed) {
    68                     this.cleanupMultipart(processedRequest);
    69                 }
    70 
    71             }
    72         }
    73     }

    拦截器这里就不在多说,这块就是返回false就不在往下执行。下面我们重点满ha.handle()方法,是如果映射参数,找到我们的方法,封装结果的。

    类图前面已经展示了,实际上handle是在父类AbstractHandlerMethodAdapter实现的

    1     public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    2         return this.handleInternal(request, response, (HandlerMethod)handler); //子类实现这个方法
    3     }
    4 
    5     protected abstract ModelAndView handleInternal(HttpServletRequest var1, HttpServletResponse var2, HandlerMethod var3) throws Exception;
     1     protected final ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
     2         if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
     3             this.checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
     4         } else {
     5             this.checkAndPrepare(request, response, true);
     6         } //看代码应该是从session中获取一些信息,然后初始化header等信息,不知道准确不?请大家指正!
     7         //这块就是根据需要是否进行同步操作
     8         if (this.synchronizeOnSession) {
     9             HttpSession session = request.getSession(false);
    10             if (session != null) {
    11                 Object mutex = WebUtils.getSessionMutex(session);
    12                 synchronized(mutex) {
    13                     return this.invokeHandleMethod(request, response, handlerMethod);
    14                 }
    15             }
    16         }
    17         //正式进入执行环节
    18         return this.invokeHandleMethod(request, response, handlerMethod);
    19     }

    下面这个方法非常重要,将重点讲解:

     1     private ModelAndView invokeHandleMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
     2         ServletWebRequest webRequest = new ServletWebRequest(request, response);
     3         WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod); //创建@InitBinder注解的方法的工厂类,进行缓存
     4         ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);//创建@ModelAttribute@ControllerAdvice注解方法工厂并缓存
     5         ServletInvocableHandlerMethod requestMappingMethod = this.createRequestMappingMethod(handlerMethod, binderFactory);
     6         ModelAndViewContainer mavContainer = new ModelAndViewContainer(); //创建结果容器并初始化一些参数,
     7         mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
     8         modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);//执行@ModelAttribute注解的方法,将结果放到结果容器中
     9         mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
    10         AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); //下面异步这一块不太明白,等后续在慢慢分析
    11         asyncWebRequest.setTimeout(this.asyncRequestTimeout);
    12         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    13         asyncManager.setTaskExecutor(this.taskExecutor);
    14         asyncManager.setAsyncWebRequest(asyncWebRequest);
    15         asyncManager.registerCallableInterceptors(this.callableInterceptors);
    16         asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
    17         if (asyncManager.hasConcurrentResult()) {
    18             Object result = asyncManager.getConcurrentResult();
    19             mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
    20             asyncManager.clearConcurrentResult();
    21             if (this.logger.isDebugEnabled()) {
    22                 this.logger.debug("Found concurrent result value [" + result + "]");
    23             }
    24 
    25             requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);
    26         }
    27 
    28         requestMappingMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]); //继续执行方法
    29         return asyncManager.isConcurrentHandlingStarted() ? null : this.getModelAndView(mavContainer, modelFactory, webRequest); //返回值了,两种情况
    30     }
     1     public final void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
     2         Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs); //执行方法,获取返回值
     3         this.setResponseStatus(webRequest);
     4         if (returnValue == null) {
     5             if (this.isRequestNotModified(webRequest) || this.hasResponseStatus() || mavContainer.isRequestHandled()) {
     6                 mavContainer.setRequestHandled(true);
     7                 return;
     8             }
     9         } else if (StringUtils.hasText(this.responseReason)) {
    10             mavContainer.setRequestHandled(true);
    11             return;
    12         }
    13 
    14         mavContainer.setRequestHandled(false);
    15 
    16         try { //处理返回值 ,封装结果集
    17             this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
    18         } catch (Exception var6) {
    19             if (this.logger.isTraceEnabled()) {
    20                 this.logger.trace(this.getReturnValueHandlingErrorMessage("Error handling return value", returnValue), var6);
    21             }
    22 
    23             throw var6;
    24         }
    25     }
     1     public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
     2         Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs); //处理 参数
     3         if (this.logger.isTraceEnabled()) {
     4             StringBuilder builder = new StringBuilder("Invoking [");
     5             builder.append(this.getMethod().getName()).append("] method with arguments ");
     6             builder.append(Arrays.asList(args));
     7             this.logger.trace(builder.toString());
     8         }
     9 
    10         Object returnValue = this.invoke(args); //反射执行方法
    11         if (this.logger.isTraceEnabled()) {
    12             this.logger.trace("Method [" + this.getMethod().getName() + "] returned [" + returnValue + "]");
    13         }
    14 
    15         return returnValue;
    16     }
     1     private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
     2         MethodParameter[] parameters = this.getMethodParameters();
     3         Object[] args = new Object[parameters.length];
     4 
     5         for(int i = 0; i < parameters.length; ++i) { //遍历方法的所有参数
     6             MethodParameter parameter = parameters[i];
     7             parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
     8             GenericTypeResolver.resolveParameterType(parameter, this.getBean().getClass()); //获取设置参数类型
     9             args[i] = this.resolveProvidedArgument(parameter, providedArgs);
    10             if (args[i] == null) {
    11                 if (this.argumentResolvers.supportsParameter(parameter)) { //这块是遍历预置的参数解析器,就是前面说的责任链模式,**composite负责查找和执行
    12                     try { //由找到的参数解析器,来解析参数
    13                         args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
    14                     } catch (Exception var9) {
    15                         if (this.logger.isTraceEnabled()) {
    16                             this.logger.trace(this.getArgumentResolutionErrorMessage("Error resolving argument", i), var9);
    17                         }
    18 
    19                         throw var9;
    20                     }
    21                 } else if (args[i] == null) {
    22                     String msg = this.getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
    23                     throw new IllegalStateException(msg);
    24                 }
    25             }
    26         }
    27 
    28         return args;
    29     }

    这块以,没有任何注解,参数为javaBean的解析器为例:ModelAttributeMethodProcessor

     1     public boolean supportsParameter(MethodParameter parameter) {
     2         if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
     3             return true;
     4         } else if (this.annotationNotRequired) {
     5             return !BeanUtils.isSimpleProperty(parameter.getParameterType());
     6         } else {
     7             return false;
     8         }
     9     }
    10 
    11     public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception {
    12         String name = ModelFactory.getNameForParameter(parameter); //如果当前参数用@ModelAttribute修饰了,返回value值或者参数类型第一个字母小写
    13         // 获取需要绑定的表单对象,看参数容器包含name为key的对象不,有的话就用它,没有创建个新的。 
          Object attribute = mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) : this.createAttribute(name, parameter, binderFactory, request); 14 WebDataBinder binder = binderFactory.createBinder(request, attribute, name); 15 if (binder.getTarget() != null) { 16 this.bindRequestParameters(binder, request); 17 this.validateIfApplicable(binder, parameter); 18 if (binder.getBindingResult().hasErrors() && this.isBindExceptionRequired(binder, parameter)) { 19 throw new BindException(binder.getBindingResult()); 20 } 21 } 22      //以上就是参数绑定, 这块领开一篇文章详细说 23 Map<String, Object> bindingResultModel = binder.getBindingResult().getModel(); 24 mavContainer.removeAttributes(bindingResultModel); 25 mavContainer.addAllAttributes(bindingResultModel); 26 return binder.getTarget(); 27 }

    参数就这样遍历处理,然后就开始通过反射 invoke执行了。接下来我们看是怎么封装换回结果的

    1         try {
    2             this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
    3         } catch (Exception var6) {
    4             if (this.logger.isTraceEnabled()) {
    5                 this.logger.trace(this.getReturnValueHandlingErrorMessage("Error handling return value", returnValue), var6);
    6             }
    7 
    8             throw var6;
    9         }

    this.returnValuehandlers. 就是那个返回结果的包装类,初始化的结果解析器就保存这里,处理思路和参数解析器一样的,

     1     public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
     2         HandlerMethodReturnValueHandler handler = this.getReturnValueHandler(returnType);
     3         Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");
     4         handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
     5     }
     6 
     7     private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {
     8         Iterator i$ = this.returnValueHandlers.iterator();
     9 
    10         HandlerMethodReturnValueHandler returnValueHandler;
    11         do {
    12             if (!i$.hasNext()) {
    13                 return null;
    14             }
    15 
    16             returnValueHandler = (HandlerMethodReturnValueHandler)i$.next();
    17             if (this.logger.isTraceEnabled()) {
    18                 this.logger.trace("Testing if return value handler [" + returnValueHandler + "] supports [" + returnType.getGenericParameterType() + "]");
    19             }
    20         } while(!returnValueHandler.supportsReturnType(returnType));
    21 
    22         return returnValueHandler;
    23     }

    遍历预置的所有结果解析器,结果解析器统一实现HandlerMethodReturnValueHandler 接口,实现supportReturnType方法:

    这里我们距离用@ResponseBody注解的结果解析器RequestResponseBodyMethodProcessor 前面说了,参数和结果集他都实现了

     1     public boolean supportsReturnType(MethodParameter returnType) {
     2         return returnType.getMethodAnnotation(ResponseBody.class) != null; //判断是否有@ResponseBody注解
     3     }
     4     public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException {
     5         mavContainer.setRequestHandled(true);
     6         if (returnValue != null) {
     7             this.writeWithMessageConverters(returnValue, returnType, webRequest); //用内置的消息转换器来转换结果集
     8         }
     9 
    10     }

    这里可能有人会问,消息转换器什么时候加载的?是在RequestMappingHandlerAdapter这个bean实例化的时候加载的,同时加载参数和结果解析器时候注入到解析器当中的

     1     public RequestMappingHandlerAdapter() { //无参构造函数中初始化
     2         StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
     3         stringHttpMessageConverter.setWriteAcceptCharset(false);
     4         this.messageConverters = new ArrayList();
     5         this.messageConverters.add(new ByteArrayHttpMessageConverter());
     6         this.messageConverters.add(stringHttpMessageConverter);
     7         this.messageConverters.add(new SourceHttpMessageConverter());
     8         this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
     9     }
    10     private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() { //构造参数解析器时候,注入进去
    11         List<HandlerMethodReturnValueHandler> handlers = new ArrayList();
    12         handlers.add(new ModelAndViewMethodReturnValueHandler());
    13         handlers.add(new ModelMethodProcessor());
    14         handlers.add(new ViewMethodReturnValueHandler());
    15         handlers.add(new HttpEntityMethodProcessor(this.getMessageConverters(), this.contentNegotiationManager));
    16         handlers.add(new CallableMethodReturnValueHandler());
    17         handlers.add(new DeferredResultMethodReturnValueHandler());
    18         handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
    19         handlers.add(new ModelAttributeMethodProcessor(false));
    20         handlers.add(new RequestResponseBodyMethodProcessor(this.getMessageConverters(), this.contentNegotiationManager));
    21         handlers.add(new ViewNameMethodReturnValueHandler());
    22         handlers.add(new MapMethodProcessor());
    23         if (this.getCustomReturnValueHandlers() != null) {
    24             handlers.addAll(this.getCustomReturnValueHandlers());
    25         }
    26 
    27         if (!CollectionUtils.isEmpty(this.getModelAndViewResolvers())) {
    28             handlers.add(new ModelAndViewResolverMethodReturnValueHandler(this.getModelAndViewResolvers()));
    29         } else {
    30             handlers.add(new ModelAttributeMethodProcessor(true));
    31         }
    32 
    33         return handlers;
    34     }

    下面来看是怎么寻找可以合适的消息转换器的

     1     protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException {
     2         ServletServerHttpRequest inputMessage = this.createInputMessage(webRequest);
     3         ServletServerHttpResponse outputMessage = this.createOutputMessage(webRequest);
     4         this.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
     5     }
     6 
     7     protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) throws IOException, HttpMediaTypeNotAcceptableException {
     8         Class<?> returnValueClass = returnValue.getClass();
     9         HttpServletRequest servletRequest = inputMessage.getServletRequest();
    10         List<MediaType> requestedMediaTypes = this.getAcceptableMediaTypes(servletRequest); //获取请求的MediaType,eg:"application/json"
    11         List<MediaType> producibleMediaTypes = this.getProducibleMediaTypes(servletRequest, returnValueClass); //寻找支持这个返回类型的转换器支持的MediaTyoe
    12         Set<MediaType> compatibleMediaTypes = new LinkedHashSet();
    13         Iterator i$ = requestedMediaTypes.iterator();
    14      //双循环两个list,进行匹配,把复核条件的MediaType放到compatibleMediaTypes中 //TODO有些不懂得是为啥这块要过滤一遍,  后面实现了 父类也做了判断每个字类是否支持MediaType了??
    15         MediaType selectedMediaType;
    16         Iterator i$;
    17         MediaType mediaType;
    18         while(i$.hasNext()) {
    19             selectedMediaType = (MediaType)i$.next();
    20             i$ = producibleMediaTypes.iterator();
    21 
    22             while(i$.hasNext()) {
    23                 mediaType = (MediaType)i$.next();
    24                 if (selectedMediaType.isCompatibleWith(mediaType)) {
    25                     compatibleMediaTypes.add(this.getMostSpecificMediaType(selectedMediaType, mediaType));
    26                 }
    27             }
    28         }
    29 
    30         if (compatibleMediaTypes.isEmpty()) {
    31             throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
    32         } else {
    33             List<MediaType> mediaTypes = new ArrayList(compatibleMediaTypes);
    34             MediaType.sortBySpecificityAndQuality(mediaTypes);
    35             selectedMediaType = null;
    36             i$ = mediaTypes.iterator();
    37             //排序之后,选择适合的MediaType
    38             while(i$.hasNext()) {
    39                 mediaType = (MediaType)i$.next();
    40                 if (mediaType.isConcrete()) {
    41                     selectedMediaType = mediaType;
    42                     break;
    43                 }
    44 
    45                 if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) {
    46                     selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
    47                     break;
    48                 }
    49             }
    50 
    51             if (selectedMediaType != null) {
    52                 selectedMediaType = selectedMediaType.removeQualityValue();
    53                 i$ = this.messageConverters.iterator();
    54                 //遍历所有消息转换器,canWrite是接口方法,相当于前面的support等,模式都是一个。然后满足的进行write。输出结果。
    55                 while(i$.hasNext()) {
    56                     HttpMessageConverter<?> messageConverter = (HttpMessageConverter)i$.next();
    57                     if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
    58                         messageConverter.write(returnValue, selectedMediaType, outputMessage);
    59                         if (this.logger.isDebugEnabled()) {
    60                             this.logger.debug("Written [" + returnValue + "] as "" + selectedMediaType + "" using [" + messageConverter + "]");
    61                         }
    62 
    63                         return;
    64                     }
    65                 }
    66             }
    67 
    68             throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
    69         }
    70     }

    下面介绍下,@ResponseBode标签用的消息转换器是MappingJacksonHttpMessageConverter;先看下类图吧

    MappingJacksonHttpMessageConverter重写了父类的write方法:

    1     public boolean canWrite(Class<?> clazz, MediaType mediaType) {
    2         return this.objectMapper.canSerialize(clazz) && this.canWrite(mediaType); //canWrite(mediaType)是父类实现的
    3     }
     1     protected boolean canWrite(MediaType mediaType) {
     2         if (mediaType != null && !MediaType.ALL.equals(mediaType)) {
     3             Iterator i$ = this.getSupportedMediaTypes().iterator(); //获取子类解析器支持的MediaType,看下是否支持
     4 
     5             MediaType supportedMediaType;
     6             do {
     7                 if (!i$.hasNext()) {
     8                     return false;
     9                 }
    10 
    11                 supportedMediaType = (MediaType)i$.next();
    12             } while(!supportedMediaType.isCompatibleWith(mediaType));
    13 
    14             return true;
    15         } else {
    16             return true;
    17         }
    18     }

    write方法 父类也帮着实现了,父类具体做了如输出,拼凑输出流头等信息

     1     public final void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
     2         HttpHeaders headers = outputMessage.getHeaders();
     3         if (headers.getContentType() == null) {
     4             if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
     5                 contentType = this.getDefaultContentType(t);
     6             }
     7 
     8             if (contentType != null) {
     9                 headers.setContentType(contentType);
    10             }
    11         }
    12 
    13         if (headers.getContentLength() == -1L) {
    14             Long contentLength = this.getContentLength(t, headers.getContentType());
    15             if (contentLength != null) {
    16                 headers.setContentLength(contentLength);
    17             }
    18         }
    19 
    20         this.writeInternal(t, outputMessage); //钩子方法,让子类去实现
    21         outputMessage.getBody().flush();
    22     }
     1     protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
     2         JsonEncoding encoding = this.getJsonEncoding(outputMessage.getHeaders().getContentType());
     3         JsonGenerator jsonGenerator = this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
     4         if (this.objectMapper.getSerializationConfig().isEnabled(Feature.INDENT_OUTPUT)) {
     5             jsonGenerator.useDefaultPrettyPrinter();
     6         }
     7         //这块就是默认用Jackson进行翻译结果集了
     8         try {
     9             if (this.prefixJson) {
    10                 jsonGenerator.writeRaw("{} && ");
    11             }
    12 
    13             this.objectMapper.writeValue(jsonGenerator, object);
    14         } catch (JsonProcessingException var6) {
    15             throw new HttpMessageNotWritableException("Could not write JSON: " + var6.getMessage(), var6);
    16         }
    17     }

    因为用@ResponseBody不需要返回视图,所以视图那块就返回Null,不需要渲染视图了

  • 相关阅读:
    Java中Collections的min和max方法
    Java中Collections的frequency方法
    Java中Collections的binarySearch方法
    uniapp 样式记录
    uniapp记录
    uniapp 弹窗输入
    uniapp 扫描
    uniapp for显示数据改变时,绑定的list值同时改变
    dev随笔记录
    easyui 使用技巧
  • 原文地址:https://www.cnblogs.com/haoerlv/p/8692988.html
Copyright © 2011-2022 走看看