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 许可证)