Spring 源码解析七(异常处理与视图解析)

Spring 源码解析七:异常处理与视图解析 接着上一篇,讲一下剩下的几个策略

  • 把 ExceptionHandlerExceptionResolver
    、ResponseStatusExceptionResolver
    、DefaultHandlerExceptionResolver
    作为默认的处理器异常解析器
  • 把 DefaultRequestToViewNameTranslator
    作为默认的视图查找处理器
  • 把 InternalResourceViewResolver
    作为默认的视图解析器
另外,View.render 视图渲染也在这里讲一下
1. ExceptionHandlerExceptionResolver ExceptionHandlerExceptionResolver
的主要功能是解析处理器调用产生的异常
继承关系如下
- AbstractHandlerExceptionResolver - AbstractHandlerMethodExceptionResolver - ExceptionHandlerExceptionResolver

1.1. AbstractHandlerExceptionResolver
AbstractHandlerExceptionResolver
的主要功能是可以设置异常处理器
public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered { // 设置自定义处理器 public void setMappedHandlers(Set mappedHandlers) { this.mappedHandlers = mappedHandlers; } // 设置自定义处理器类 public void setMappedHandlerClasses(Class... mappedHandlerClasses) { this.mappedHandlerClasses = mappedHandlerClasses; }// 解析异常 public ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { // 检查是否可应用处理器 if (shouldApplyTo(request, handler)) { // 解析异常,调用处理器处理 ModelAndView result = doResolveException(request, response, handler, ex); // ... 代码省略return result; } else { return null; } } }

public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered { // 检查是否可应用处理器 protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { if (handler != null) { // 如果包含在mappedHandlers中,可以处理 if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) { return true; } // 如果包含在mappedHandlerClasses中,可以处理 if (this.mappedHandlerClasses != null) { for (Class handlerClass : this.mappedHandlerClasses) { if (handlerClass.isInstance(handler)) { return true; } } } } // 如果没有mappedHandlers与mappedHandlerClasses,默认可以使用 return !hasHandlerMappings(); }// 解析异常,调用处理器处理,子类实现 protected abstract ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex); }

1.2. AbstractHandlerMethodExceptionResolver
AbstractHandlerMethodExceptionResolver
的主要功能是可以通过异常类型来处理
public abstract class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExceptionResolver { // 检查是否可应用处理器 @Override protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { if (handler == null) { return super.shouldApplyTo(request, null); } // 如果是,获取HandlerMethod内部的handler,继续判断 else if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; handler = handlerMethod.getBean(); return super.shouldApplyTo(request, handler); } // 如果有全局的异常处理器或自定义异常处理器,继续判断 else if (hasGlobalExceptionHandlers() && hasHandlerMappings()) { return super.shouldApplyTo(request, handler); } // 否则就不能处理了 else { return false; } }// 解析异常,调用处理器处理 @Override protected final ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { // 只能是HandlerMethod才能用于处理异常 HandlerMethod handlerMethod = (handler instanceof HandlerMethod ? (HandlerMethod) handler : null); // 实际处理 return doResolveHandlerMethodException(request, response, handlerMethod, ex); }// 实际处理,由子类实现 protected abstract ModelAndView doResolveHandlerMethodException( HttpServletRequest request, HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception ex); }

1.3. ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver
的主要功能是可以通过注解@ExceptionHandler来处理异常
1.3.1. ExceptionHandlerExceptionResolver.afterPropertiesSet
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver implements ApplicationContextAware, InitializingBean { // 当属性都注入后,由上下文环境调用此方法初始化 @Override public void afterPropertiesSet() { // 初始化`@ControllerAdvice`注解标注的组件 initExceptionHandlerAdviceCache(); if (this.argumentResolvers == null) { // 获取默认的参数解析器 List resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this.returnValueHandlers == null) { // 获取默认的响应值处理器 List handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }// 初始化`@ControllerAdvice`注解标注的组件 private void initExceptionHandlerAdviceCache() { // ... 代码省略// 获取有`@ControllerAdvice`注解的bean List adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); // 进行遍历 for (ControllerAdviceBean adviceBean : adviceBeans) { Class beanType = adviceBean.getBeanType(); if (beanType == null) { // 没有类型,报错 } // @ExceptionHandler注解解析器 ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType); // 有异常处理方法 if (resolver.hasExceptionMappings()) { // 加入全局异常处理器缓存容器 this.exceptionHandlerAdviceCache.put(adviceBean, resolver); } // 是ResponseBodyAdvice的子类 if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) { // 加入容器 this.responseBodyAdvice.add(adviceBean); } }// ... 代码省略 } }

public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver implements ApplicationContextAware, InitializingBean { // 获取默认的参数解析器 protected List getDefaultArgumentResolvers() { List resolvers = new ArrayList<>(); // @SessionAttribute 解析 resolvers.add(new SessionAttributeMethodArgumentResolver()); // @RequestAttribute 解析 resolvers.add(new RequestAttributeMethodArgumentResolver()); // 从原生 ServletRequest 对象的输入流中解析请求头、请求体等 resolvers.add(new ServletRequestMethodArgumentResolver()); // 把处理器最终的数据写入到原生 ServletResponse 对象的输出流中,包括响应头、响应体等 resolvers.add(new ServletResponseMethodArgumentResolver()); // 重定向处理 resolvers.add(new RedirectAttributesMethodArgumentResolver()); // Model 处理 resolvers.add(new ModelMethodProcessor()); // ... 代码省略 }// 获取默认的响应值处理器 protected List getDefaultReturnValueHandlers() { List handlers = new ArrayList<>(); // ModelAndView 处理 handlers.add(new ModelAndViewMethodReturnValueHandler()); // Model 处理 handlers.add(new ModelMethodProcessor()); // View 处理 handlers.add(new ViewMethodReturnValueHandler()); // HttpEntity 处理 handlers.add(new HttpEntityMethodProcessor( getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice)); // 数据绑定解析 handlers.add(new ServletModelAttributeMethodProcessor(false)); // @RequestBody @ResponseBody 解析 handlers.add(new RequestResponseBodyMethodProcessor( getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice)); // 视图名字处理 handlers.add(new ViewNameMethodReturnValueHandler()); // Map 处理 handlers.add(new MapMethodProcessor()); // ... 代码省略return handlers; } }

1.3.2. ExceptionHandlerExceptionResolver.doResolveHandlerMethodException
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver implements ApplicationContextAware, InitializingBean { // 实际处理异常 @Override protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) { // 获取异常处理的方法对象 ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception); // 如果没有,返回null if (exceptionHandlerMethod == null) { return null; }if (this.argumentResolvers != null) { // 注入参数解析器argumentResolvers exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) { // 注入响应处理returnValueHandlers exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); }ServletWebRequest webRequest = new ServletWebRequest(request, response); // 响应容器 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); ArrayList exceptions = new ArrayList<>(); try { // 遍历内部的异常 Throwable exToExpose = exception; while (exToExpose != null) { exceptions.add(exToExpose); Throwable cause = exToExpose.getCause(); exToExpose = (cause != exToExpose ? cause : null); } Object[] arguments = new Object[exceptions.size() + 1]; exceptions.toArray(arguments); arguments[arguments.length - 1] = handlerMethod; // 调用处理器,获取处理结果,应用响应处理returnValueHandlers exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, arguments); } catch (Throwable invocationEx) { // ... 代码省略 }// 如果是已经处理过了,返回空ModelAndView if (mavContainer.isRequestHandled()) { return new ModelAndView(); } else { // 获取模型对象 ModelMap model = mavContainer.getModel(); // 生成ModelAndView ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); // ... 代码省略// 处理重定向 if (model instanceof RedirectAttributes) { // ... 代码省略 } return mav; } }// 获取异常处理的方法对象 protected ServletInvocableHandlerMethod getExceptionHandlerMethod( @Nullable HandlerMethod handlerMethod, Exception exception) {Class handlerType = null; if (handlerMethod != null) { // 获取bean类型 handlerType = handlerMethod.getBeanType(); // 获取缓存的处理器 ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType); // 如果没有,就生成,并缓存 if (resolver == null) { resolver = new ExceptionHandlerMethodResolver(handlerType); this.exceptionHandlerCache.put(handlerType, resolver); } // 解析处理exception的方法 Method method = resolver.resolveMethod(exception); // 有了就返回一个封装对象 if (method != null) { return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method); }// ... 代码省略 }// 没有自定义的,就使用全局的异常处理器 for (Map.Entry entry : this.exceptionHandlerAdviceCache.entrySet()) { ControllerAdviceBean advice = entry.getKey(); if (advice.isApplicableToBeanType(handlerType)) { ExceptionHandlerMethodResolver resolver = entry.getValue(); // 解析处理exception的方法 Method method = resolver.resolveMethod(exception); // 有了就返回一个封装对象 if (method != null) { return new ServletInvocableHandlerMethod(advice.resolveBean(), method); } } }return null; } }

2. ResponseStatusExceptionResolver ResponseStatusExceptionResolver
的主要功能是支持@ResponseStatus注解映射状态码
public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver implements MessageSourceAware { // 解析异常,调用处理器处理 @Override protected ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {try { // 如果ResponseStatusException,把ResponseStatusException内部的responseHeaders设置到响应中 // 并设置响应码和响应原因 if (ex instanceof ResponseStatusException) { return resolveResponseStatusException((ResponseStatusException) ex, request, response, handler); }// 不然,查看异常类的`@ResponseStatus`注解,如果有,设置响应码和响应原因 ResponseStatus status = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class); if (status != null) { return resolveResponseStatus(status, request, response, handler, ex); }// 如果有内部异常,循环遍历处理 if (ex.getCause() instanceof Exception) { return doResolveException(request, response, handler, (Exception) ex.getCause()); } } catch (Exception resolveEx) { // ... 代码省略 } return null; } }

3. DefaultHandlerExceptionResolver DefaultHandlerExceptionResolver
的主要功能是把标准 SpringMVC 异常映射状态码
public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionResolver { // 解析异常,调用处理器处理 @Override protected ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { try { // 405 if (ex instanceof HttpRequestMethodNotSupportedException) { return handleHttpRequestMethodNotSupported( (HttpRequestMethodNotSupportedException) ex, request, response, handler); } // 415 else if (ex instanceof HttpMediaTypeNotSupportedException) { return handleHttpMediaTypeNotSupported( (HttpMediaTypeNotSupportedException) ex, request, response, handler); } // 406 else if (ex instanceof HttpMediaTypeNotAcceptableException) { return handleHttpMediaTypeNotAcceptable( (HttpMediaTypeNotAcceptableException) ex, request, response, handler); } // 500 else if (ex instanceof MissingPathVariableException) { return handleMissingPathVariable( (MissingPathVariableException) ex, request, response, handler); } // 400 else if (ex instanceof MissingServletRequestParameterException) { return handleMissingServletRequestParameter( (MissingServletRequestParameterException) ex, request, response, handler); } // 400 else if (ex instanceof ServletRequestBindingException) { return handleServletRequestBindingException( (ServletRequestBindingException) ex, request, response, handler); } // 500 else if (ex instanceof ConversionNotSupportedException) { return handleConversionNotSupported( (ConversionNotSupportedException) ex, request, response, handler); } // 400 else if (ex instanceof TypeMismatchException) { return handleTypeMismatch( (TypeMismatchException) ex, request, response, handler); } // 400 else if (ex instanceof HttpMessageNotReadableException) { return handleHttpMessageNotReadable( (HttpMessageNotReadableException) ex, request, response, handler); } // 500 else if (ex instanceof HttpMessageNotWritableException) { return handleHttpMessageNotWritable( (HttpMessageNotWritableException) ex, request, response, handler); } // 400 else if (ex instanceof MethodArgumentNotValidException) { return handleMethodArgumentNotValidException( (MethodArgumentNotValidException) ex, request, response, handler); } // 400 else if (ex instanceof MissingServletRequestPartException) { return handleMissingServletRequestPartException( (MissingServletRequestPartException) ex, request, response, handler); } // 400 else if (ex instanceof BindException) { return handleBindException((BindException) ex, request, response, handler); } // 404 else if (ex instanceof NoHandlerFoundException) { return handleNoHandlerFoundException( (NoHandlerFoundException) ex, request, response, handler); } // 503 else if (ex instanceof AsyncRequestTimeoutException) { return handleAsyncRequestTimeoutException( (AsyncRequestTimeoutException) ex, request, response, handler); } } catch (Exception handlerEx) { // ... 代码省略 } return null; } }

4. DefaultRequestToViewNameTranslator DefaultRequestToViewNameTranslator
的主要功能是把 URI 映射视图名字
public class DefaultRequestToViewNameTranslator implements RequestToViewNameTranslator { // 根据请求获取视图名字 @Override public String getViewName(HttpServletRequest request) { // 获取URI的path部分 String path = ServletRequestPathUtils.getCachedPathValue(request); // 加上前缀与后缀 return (this.prefix + transformPath(path) + this.suffix); }// 转换path protected String transformPath(String lookupPath) { String path = lookupPath; // 去掉开头的/ if (this.stripLeadingSlash && path.startsWith(SLASH)) { path = path.substring(1); } // 去掉结尾的/ if (this.stripTrailingSlash && path.endsWith(SLASH)) { path = path.substring(0, path.length() - 1); } // 去掉扩展名 if (this.stripExtension) { path = StringUtils.stripFilenameExtension(path); } // 确保分隔符为/ if (!SLASH.equals(this.separator)) { path = StringUtils.replace(path, SLASH, this.separator); } return path; } }

5. InternalResourceViewResolver InternalResourceViewResolver
的主要功能是把视图名字解析成视图对象
继承关系如下
- AbstractCachingViewResolver - UrlBasedViewResolver - InternalResourceViewResolver

5.1. AbstractCachingViewResolver
AbstractCachingViewResolver
的主要功能是把视图名字解析成视图对象
public abstract class AbstractCachingViewResolver extends WebApplicationObjectSupport implements ViewResolver { // 把视图名字解析成视图对象 @Override public View resolveViewName(String viewName, Locale locale) throws Exception { // 如果不使用缓存,则每次都加载一次视图文件 if (!isCache()) { return createView(viewName, locale); } else { // 获取缓存键 Object cacheKey = getCacheKey(viewName, locale); // 获取缓存 View view = this.viewAccessCache.get(cacheKey); if (view == null) { synchronized (this.viewCreationCache) { view = this.viewCreationCache.get(cacheKey); if (view == null) { // 缓存中不存在,加载创建视图对象,并加入缓存 view = createView(viewName, locale); // ... 代码省略if (view != null) { this.viewAccessCache.put(cacheKey, view); this.viewCreationCache.put(cacheKey, view); } } } } return (view != UNRESOLVED_VIEW ? view : null); } }protected View createView(String viewName, Locale locale) throws Exception { return loadView(viewName, locale); }// 加载视图,子类实现 protected abstract View loadView(String viewName, Locale locale) throws Exception; }

5.2. UrlBasedViewResolver
UrlBasedViewResolver
的主要功能是支持把直接视图名字映射为 url
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered { @Override protected View createView(String viewName, Locale locale) throws Exception { // ... 代码省略// 以"redirect:"开头的重定向,可以跳到其他视图 if (viewName.startsWith(REDIRECT_URL_PREFIX)) { String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length()); RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible()); // ... 代码省略return view; }// 以"forward:"开头的重定向,可以转发到其他视图 if (viewName.startsWith(FORWARD_URL_PREFIX)) { String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length()); InternalResourceView view = new InternalResourceView(forwardUrl); return view; }// 其他保持父类行为 return super.createView(viewName, locale); } }

public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered { // 加载视图 @Override protected View loadView(String viewName, Locale locale) throws Exception { // 构建视图 AbstractUrlBasedView view = buildView(viewName); // ... 代码省略return view; }// 构建视图 protected AbstractUrlBasedView buildView(String viewName) throws Exception { // 初始化视图类 AbstractUrlBasedView view = instantiateView(); // 设置路径 view.setUrl(getPrefix() + viewName + getSuffix()); // 设置解析数据 view.setAttributesMap(getAttributesMap()); // ... 代码省略return view; } }

5.3. InternalResourceViewResolver
InternalResourceViewResolver
的主要功能是支持 InternalResourceView 和 JstlView
public class InternalResourceViewResolver extends UrlBasedViewResolver { @Override protected AbstractUrlBasedView instantiateView() { return (getViewClass() == InternalResourceView.class ? new InternalResourceView() : (getViewClass() == JstlView.class ? new JstlView() : super.instantiateView())); } }

6. 视图渲染 6.1. View
View
是所有扩展视图组件的基础接口,主要就是 render 方法
public interface View { void render(@Nullable Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; }

6.2. AbstractView
AbstractView
的主要功能是支持 Spring 对视图组件以 bean 形式来管理
public abstract class AbstractView extends WebApplicationObjectSupport implements View, BeanNameAware { // 渲染视图 @Override public void render(@Nullable Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { // 合并其他数据到模型中 Map mergedModel = createMergedOutputModel(model, request, response); // 渲染合并的模型数据 renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); }// 合并其他数据到模型中 protected Map createMergedOutputModel(@Nullable Map model, HttpServletRequest request, HttpServletResponse response) { // 路径变量 Map pathVars = (this.exposePathVariables ? (Map) request.getAttribute(View.PATH_VARIABLES) : null); // 注入的静态属性 int size = this.staticAttributes.size(); size += (model != null ? model.size() : 0); size += (pathVars != null ? pathVars.size() : 0); // 合并路径变量与静态属性到模型中 Map mergedModel = CollectionUtils.newLinkedHashMap(size); mergedModel.putAll(this.staticAttributes); if (pathVars != null) { mergedModel.putAll(pathVars); } if (model != null) { mergedModel.putAll(model); }// ... 代码省略return mergedModel; }// 渲染合并的模型数据,子类实现 protected abstract void renderMergedOutputModel( Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; }

6.3. AbstractUrlBasedView
AbstractUrlBasedView
的主要功能是要求有一个 url 数据,其他没有什么功能
6.4. AbstractTemplateView
AbstractTemplateView
的主要功能是实现模板渲染,纯接口数据(不需要模板渲染的),直接继承 AbstractView 就可以了
public abstract class AbstractTemplateView extends AbstractUrlBasedView { // 渲染合并的模型数据 @Override protected final void renderMergedOutputModel( Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {// ... 代码省略,载入请求属性、session属性、spring宏属性到模型数据中// 渲染合并的模型数据到模板 renderMergedTemplateModel(model, request, response); }// 渲染合并的模型数据到模板,子类实现 protected abstract void renderMergedTemplateModel( Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; }

6.5. FreeMarkerView
FreeMarkerView
的主要功能是用 FreeMarker 渲染视图
public class FreeMarkerView extends AbstractTemplateView { // 渲染合并的模型数据到模板 @Override protected void renderMergedTemplateModel( Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { doRender(model, request, response); }protected void doRender(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {// ... 代码省略// 构建FreeMarker模板对象 SimpleHash fmModel = buildTemplateModel(model, request, response); // ... 代码省略// 获取模板文件,渲染模板到response processTemplate(getTemplate(locale), fmModel, response); }// 渲染模板到response protected void processTemplate(Template template, SimpleHash model, HttpServletResponse response) throws IOException, TemplateException { // 输入模板渲染结果到response writer template.process(model, response.getWriter()); } }

6.6. MappingJackson2JsonView
MappingJackson2JsonView
的主要功能是用 jackson 来序列化输出接口数据,直接继承 AbstractView
public class MappingJackson2JsonView extends AbstractView { // 渲染合并的模型数据 @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { // 字节数组输出流 ByteArrayOutputStream temporaryStream = null; // 输出流 OutputStream stream; // 需要更新'Content-Length'头 if (this.updateContentLength) { // 创建一个新的临时输出流 temporaryStream = createTemporaryOutputStream(); stream = temporaryStream; } else { // 不然使用response的输出流 stream = response.getOutputStream(); }// 把一些不需要的对象过滤掉,包装成可序列化的对象 Object value = https://www.it610.com/article/filterAndWrapModel(model, request); // 把结果写入输出流中 writeContent(stream, value); if (temporaryStream != null) { // 如果有新的临时输出流,把这个新的流写入到response对象中 writeToResponse(response, temporaryStream); } }// 把结果写入输出流中 protected void writeContent(OutputStream stream, Object object) throws IOException { // 生成一个JsonGenerator try (JsonGenerator generator = this.objectMapper.getFactory().createGenerator(stream, this.encoding)) { // ... 代码省略Object value = object; Class serializationView = null; FilterProvider filters = null; // 获取序列化视图和过滤器 if (value instanceof MappingJacksonValue) { MappingJacksonValue container = (MappingJacksonValue) value; value = https://www.it610.com/article/container.getValue(); serializationView = container.getSerializationView(); filters = container.getFilters(); }// 给writer加入序列化视图 ObjectWriter objectWriter = (serializationView != null ? this.objectMapper.writerWithView(serializationView) : this.objectMapper.writer()); // 给writer加入过滤器,如字段过滤 if (filters != null) { objectWriter = objectWriter.with(filters); } objectWriter.writeValue(generator, value); // ... 代码省略// 刷新数据 generator.flush(); } } }

后续 更多博客,查看 https://github.com/senntyou/blogs
作者:深予之 (@senntyou)
【Spring 源码解析七(异常处理与视图解析)】版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)

    推荐阅读