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<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this.returnValueHandlers == null) { // 获取默认的响应值处理器 List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } } // 初始化`@ControllerAdvice`注解标注的组件 private void initExceptionHandlerAdviceCache() { // ... 代码省略 // 获取有`@ControllerAdvice`注解的bean List<ControllerAdviceBean> 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<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { List<HandlerMethodArgumentResolver> 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<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() { List<HandlerMethodReturnValueHandler> 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<Throwable> 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<ControllerAdviceBean, ExceptionHandlerMethodResolver> 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<String, ?> 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<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // 合并其余数据到模型中 Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); // 渲染合并的模型数据 renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); } // 合并其余数据到模型中 protected Map<String, Object> createMergedOutputModel(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) { // 门路变量 Map<String, Object> pathVars = (this.exposePathVariables ? (Map<String, Object>) request.getAttribute(View.PATH_VARIABLES) : null); // 注入的动态属性 int size = this.staticAttributes.size(); size += (model != null ? model.size() : 0); size += (pathVars != null ? pathVars.size() : 0); // 合并门路变量与动态属性到模型中 Map<String, Object> 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<String, Object> 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<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // ... 代码省略,载入申请属性、session属性、spring宏属性到模型数据中 // 渲染合并的模型数据到模板 renderMergedTemplateModel(model, request, response); } // 渲染合并的模型数据到模板,子类实现 protected abstract void renderMergedTemplateModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception;}
6.5. FreeMarkerView
FreeMarkerView
的次要性能是用 FreeMarker 渲染视图
public class FreeMarkerView extends AbstractTemplateView { // 渲染合并的模型数据到模板 @Override protected void renderMergedTemplateModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { doRender(model, request, response); } protected void doRender(Map<String, Object> 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<String, Object> 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 = 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 = 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)
版权申明:自在转载-非商用-非衍生-放弃署名(创意共享 3.0 许可证)