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 = 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
版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)