SpringBoot第九天 - Web数据响应

SpringBoot - Web数据响应

研究SpringBoot进行Web开发时如何处理响应。

1. 数据响应类型

数据响应分为两大类:响应页面,响应数据。

响应页面在我们开发单体应用经常用到,处理器直接返回视图名。
响应页面的原理会在接下来的视图解析章节讲解。

做前后端分离开发场景大多数还是响应数据,常用响应数据类型:

  • JSON数据格式
  • XML格式
  • xls,xlsx表格
  • 图片,音视频等媒体格式
  • 自定义协议数据等

本章节我们以处理器响应JSON数据来研究数据响应原理。

学习SpringMVC时我们知道,响应JSON需要两步:

  1. 导入jackson依赖;
  2. 在处理器方法上使用@ResponseBody注解。

SpringBoot在web场景的启动器spring-boot-starter-web中已经为我们配置了jackson,
所以使用web场景启动器开发时只需使用@ResponseBody注解即可。

2. ReturnValueHandler原理

2.1 上节遗留的细节

上节研究SpringBoot请求参数处理的时候,我们了解到了参数解析器ArgumentResolver

// org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
// RequestMappingHandlerAdapter.java Line:850~904

// 真正使用处理器适配器执行目标处理器的方法
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   
    try {
   
        // ... 省略其他代码
        // 给执行方法设置参数解析器
        if (this.argumentResolvers != null) {
   
            invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        }
        // 给执行方法设置返回值解析器
        if (this.returnValueHandlers != null) {
   
            invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        }
        // ... 省略其他代码
        // 调用处理器方法并处理请求
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        // ... 省略其他代码
    }
    finally {
   
        webRequest.requestCompleted();
    }
}

同时还有一个组件ReturnValueHandler

2.2 返回值处理器概述

返回值处理器(ReturnValueHandler):SpringMVC使用返回值处理器处理处理器的返回值,
根据返回值的内容响应对应的信息。

返回值处理器和参数解析器相似,本质都是一个接口HandlerMethodReturnValueHandler

这个接口也有两个方法:

  • boolean supportsReturnType:判断此返回值处理器是否支持当前返回值类型;
  • void handleReturnValue:处理当前返回值的方法。

SpringMVC提供了15种返回值处理器实现类(Spring 2.4.5,严格顺序):

名称 作用
ModelAndViewMethodReturnValueHandler 处理ModelAndView类型及其子类的返回值
ModelMethodProcessor 处理Model类型及其子类的返回值
ViewMethodReturnValueHandler 处理返回值为View类型及其子类的返回值
ResponseBodyEmitterReturnValueHandler 处理ResponseBodyEmitter类型及其子类,包括使用ResponseEntity包装的类的返回值,在Spring 5.0中还支持响应式适配类型
StreamingResponseBodyReturnValueHandler 处理StreamingResponseBody类型及其子类或ResponseEntity<StreamingResponseBody>类型的返回值
HttpEntityMethodProcessor 处理HttpEntity类型及其子类但不包括RequestEntity类型的返回值
HttpHeadersReturnValueHandler 处理HttpHeaders类型及其子类的返回值
CallableMethodReturnValueHandler 处理Callable类型及其子类的返回值
DeferredResultMethodReturnValueHandler 处理DeferredResult类型及其子类、ListenableFuture类型及其子类和CompletionStage类型及其子类的返回值
AsyncTaskMethodReturnValueHandler 处理WebAsyncTask类型及其子类的返回值
ServletModelAttributeMethodProcessor
annotationNotRequired = false
处理被@ModelAttribute注解的方法的返回值
RequestResponseBodyMethodProcessor 处理带有@ResponseBody注解的返回值
ViewNameMethodReturnValueHandler 处理视图名返回值(void或者String)
MapMethodProcessor 处理Map类型及其子类的返回值
ServletModelAttributeMethodProcessor
annotationNotRequired = true
处理没有被@ModelAttribute注解标注且类型为简单类型的返回值

这些处理器也是各有各的返回值支持类型,各有各的处理方法。

2.3 返回值处理器原理(源码)

供调试的处理器方法:

@RequestMapping("/user")
@ResponseBody
public User getUser() {
   
    return new User("张三", 21, true);
}

调试来到ServletInvocableHandlerMethod类的invokeAndHandle方法:

// org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle
// ServletInvocableHandlerMethod.java Line:103~133

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
   

    // 执行目标处理器,并获取返回值
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    // 设置响应状态
    setResponseStatus(webRequest);

    // 如果没有返回值
    if (returnValue == null) {
   
        if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
   
            disableContentCachingIfNecessary(webRequest);
            mavContainer.setRequestHandled(true);
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值