【springboot】响应处理-数据响应

前面几篇有关【springboot】请求处理原理各模块的文章结束后,就到了响应处理。

响应处理又可以分为(一)响应页面(二)响应数据

(一)响应页面常见于一些单体项目中,主要表现为服务器响应我们发出的请求给我们跳转到对应的页面。(二)响应数据主要见于一些前后端分离的项目,前端向后端发送请求,后端向前端发送JSON数据(或者其他类型的数据,如xml、xlsx、图片音频视频、自定义协议数据等)。

后面的文章都会以(一)响应JSON和(二)内容协商两个模块的内容来开展,本文先介绍(一)响应JSON。

在springboot中来实现响应JSON就必须先在我们项目的pom文件中引入对应的starter-web场景:

然后点旁边那个圆圆的O标志,就会进到springboot为我们集中管理版本(复习:springboot的一大特色)的pom文件中(名字是spring-boot-dependencies-版本号.pom),打开如果看到一大片红的报错,不要害怕,只是因为有的包没有导入,跟普通的项目pom文件是一样的,刷新maven就帮你全下载好了。

我的版本是2.7.4的:

可以看到其中2.7.4版本的starter-json依赖是web场景为我们自动引入的json场景。

同理,继续深入可以获得有关版本的更多详细信息:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.4</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
    <version>2.13.4</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.13.4</version>
    <scope>compile</scope>
</dependency>

响应JSON的实现需要有关①jackson.jar(上文已引入)和②@ResponseBody注解

②只需要在我们的controller类上加@ResponseBody注解。

这里写一个普通的controller(添加普通@Controller注解):

这就可以向前端(页面)返回JSON数据。

开始就这个过程debug。仍然从DispatcherServlet来到这个位置(InvokeAndHandleMethod类):

 查看this.returnValueHandlers有哪些值:(可选的处理器handler/processor,预告一下是[11])

还可以查看我们的返回值,的确就是controller方法中声明的数据。 

最核心的处理返回值的逻辑在于handleReturnValue方法: 

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        } else {
            handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
        }
}

进入selectHandler方法,可以看到该方法返回值是HandleMethodReturnValueHandler类型的,即得到适合处理本controller方法的方法返回值处理器。因此可知handleReturnValue方法处理返回值的逻辑跟之前几篇文章讲(一)请求处理——参数处理的逻辑是一样的,需要根据我们的参数or返回值找到合适的参数or返回值处理器(handler),然后有针对的handleXxx方法来处理具体逻辑。

@Nullable
    private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
        boolean isAsyncValue = this.isAsyncReturnValue(value, returnType);
        Iterator var4 = this.returnValueHandlers.iterator();

        HandlerMethodReturnValueHandler handler;
        do {
            do {
                if (!var4.hasNext()) {
                    return null;
                }

                handler = (HandlerMethodReturnValueHandler)var4.next();
            } while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler));
        } while(!handler.supportsReturnType(returnType));

        return handler;
}

selectHandler的过程中首先通过isAsyncReturnValue方法判断是不是异步的返回值,然后这里就是找handler的核心了——又是通过迭代来默认的可选handler列表中(设计模式:适配器模式)找合适的handler。

private boolean isAsyncReturnValue(@Nullable Object value, MethodParameter returnType) {
        Iterator var3 = this.returnValueHandlers.iterator();

        HandlerMethodReturnValueHandler handler;
        do {
            if (!var3.hasNext()) {
                return false;
            }

            handler = (HandlerMethodReturnValueHandler)var3.next();
        } while(!(handler instanceof AsyncHandlerMethodReturnValueHandler) || !((AsyncHandlerMethodReturnValueHandler)handler).isAsyncReturnValue(value, returnType));

        return true;
}

 这一步判断结束,不是异步的返回值:

于是继续回到selectHandler方法中判断,可以留意到HandleMethodReturnValueHandler类型:

public interface HandlerMethodReturnValueHandler {
    boolean supportsReturnType(MethodParameter returnType);

    void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}

 或者ctrl+F12可以查看当前类(接口)的继承关系。

不难知道supportsReturnType方法是判断方法是否支持该返回值的,handleMethodValue是在supportsReturnType为true时才进行处理执行返回值的。

这个跟之前请求参数解析的原理一样的。(supportsParmeter的判断)可以查看HandleMethodReturnValueHandler接口的supportsReturnType方法。HandleMethodReturnValueHandler接口有很多实现类,对应的就是不同的方法返回值处理(判断是否支持再决定是否作为handler处理)的实现。

但是同时debug也发现, 这个supportsReturnType来自,在他的上面有一个之前介绍参数解析时分析过的supportsParameter方法,不过是判断对象不一样。但是他们都来自这个方法处理器(for RequestResponseBody--请求响应体)。 

不管如何得到的handler是这个类型的:

(也警示我们:处理器不一定是handler结尾的名字,还可以是processor,也是处理器的意思)

 最后执行到最终核心处理(②):

@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

		mavContainer.setRequestHandled(true);
		ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
		ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

		// Try even with null return value. ResponseBodyAdvice could get involved.
		writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

下一篇文章就是介绍这个最里层的handleReturnValue是怎么处理请求响应体返回值的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值