接口标记为@ResponseBody却不进入ResponseBodyAdvice
一、背景:
我们的接口为了统一,在ResponseBodyAdvice中对返回值做统一处理,默认添加了errorNo和errorInfo字段返回。
最近同事改接口代码的时候,发现接口返回值是空的。乍一看,没什么重大修改。
接口代码大致就是下面这个样子:
@ResponseBody
@RequestMapping("test")
public void test(HttpServletRequest request, HttpServletResponse response){
// 业务逻辑处理
}
二、问题分析
顺着这个接口,单步调试跟到Spring的源码ServletInvocableHandlerMethod#invokeAndHandle方法
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()) {
mavContainer.setRequestHandled(true);
// 直接进入到这里就return出去了
return;
}
} else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
try {
// 要进到这里才会进入到ResponseBodyAdvice中
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
} catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
}
throw ex;
}
}
再对着源码,看下return出去的4个条件,核对一下我们的接口
void类型,返回值确实是null
isRequestNotModified(webRequest) ,false
getResponseStatus() != null ,false
如果在test方法上标记@ResponseStatus(HttpStatus.OK),这里取到的就不是null
mavContainer.isRequestHandled(),true
那么问题来了,mavContainer.isRequestHandled()=true是什么时候设置的呢?
重新debug,发现在ServletResponseMethodArgumentResolver#resolveArgument中设置的,源码截取如下:
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
if (mavContainer != null) {
// 就是这里设置的了
mavContainer.setRequestHandled(true);
}
// 略 ...
}
三、问题小结
通过上面的分析,问题已经明朗了。
- 接口一直都是返回null的。开发此次修改的时候,在接口入参里面加了HttpServletResponse
- 因为有HttpServletResponse入参,就会进入到ServletResponseMethodArgumentResolver
- 因为ModelAndViewContainer不为null,mavContainer.setRequestHandled(true);
- 满足前面ServletInvocableHandlerMethod#invokeAndHandle的条件,直接return
- 返回空结果
接口标记为@ResponseBody却不进入ResponseBodyAdvice的更多相关文章
- 接口没添加@responseBody注解
今天在重写springaop小demo时,发现调用接口时,可以在控制台上正常返回结果,但是页面报错,debug半天,可以看到是调用了modelview的时候出错,找不到视图了.. debug的时候控制 ...
- 为什么这些java接口没有抽象方法?浅谈Java标记接口
在jdk的源码中,存在这样的一些接口,他们不包含任何的(抽象)方法,但是却广泛的存在. 这种接口我们称之为Mark Interface,也就是标记接口. 这些接口呢,我们不用来实现任何的方法,他们的作 ...
- 内功心法 -- Java标记接口
写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------这篇博客主要来谈谈" ...
- Java 标记接口
没有声明或定义方法的接口称为标记接口(Mark Interface).某个类实现该接口时不需要重写方法,表明具有接口标记的功能.Java中常用的3个标记接口如下: 1 Serializable jav ...
- Java的四个标记接口:Serializable、Cloneable、RandomAccess和Remote接口
一.概述 标记接口是一些没有属性和方法的接口,也是一种设计思想.Java中的一个标记接口表示的的是一种类的特性,实现了该标记接口的类则具有该特性.如实现了Serializable接口的类,表示这个类的 ...
- Java标记接口
写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------这篇博客主要来谈谈" ...
- java接口调用——webservice就是一个RPC而已
很多新手一听到接口就蒙逼,不知道接口是什么!其实接口就是RPC,通过远程访问别的程序提供的方法,然后获得该方法执行的接口,而不需要在本地执行该方法.就是本地方法调用的升级版而已,我明天会上一篇如何通过 ...
- IGS_学习笔记05_IREP开发Concurrent Program为客户化集合接口(案例)
20150819 Created By BaoXinjian
- 利用Swagger2自动生成对外接口的文档
一直以来做对外的接口文档都比较原始,基本上都是手写的文档传来传去,最近发现了一个新玩具,可以在接口上省去不少麻烦. swagger是一款方便展示的API文档框架.它可以将接口的类型最全面的展示给对方开 ...
随机推荐
- err Invalid input of type: 'dict'. Convert to a byte, string or number first
一个问题引发的血案: 用python向redis写入数据报错: redis.exceptions.DataError: Invalid input of type: 'dict'. Convert t ...
- mysql addtime() 函数
mysql> select addtime('1997-12-31 23:59:52' , '1 1:1:1'); +-------------------------------------- ...
- Tkinter 之爬虫框架项目实战
一.效果图 二.源码 ''' 测试内容页爬取''' def test_content_url(self): try: url = self.test_url_var.get().strip() ite ...
- 【BIRT】修改主题背景颜色
下图是BIRT默认的颜色配置,为了跟系统颜色格局相一致,此处需要对颜色进行修改; 下面简单介绍了如何修改不同位置的背景颜色 对应文件地址均在目录:../webcontent/birt/styles下 ...
- D3.js的v5版本入门教程(第三章)—— 选择元素和绑定数据
D3.js的v5版本入门教程(第三章) 在D3.js中,选择元素和绑定元素是最基本的内容,也是很重要的内容,等你看完整个教程后你会发现,这些D3.js教程都是在选择元素和绑定元素的基础上展开后续工作的 ...
- x86-64位指令学习
参考文章: (1)x86-64指令系统过程调用学习笔记 https://blog.csdn.net/weixin_44735312/article/details/89818907 创建文本sum.c ...
- GD-GAN: Generative Adversarial Networks for Trajectory Prediction and Group Detection in Crowds
GD-GAN: Generative Adversarial Networks for Trajectory Prediction and Group Detection in Crowds 2019 ...
- python+lego ev3的心得总结 随时更新
一.连接方面 1.试了蓝牙连接,被电脑防火墙拒绝了很多次,很奇怪,明明都pin码都对上了,然后瞬间被踢开. 2.数据线直连,在一台win7上怎么试也不行,在另一台上自动上windows update上 ...
- ue4读取灰度图生成三维地形mesh
转自:https://www.cnblogs.com/gucheng/p/10116857.html 新建ue c++工程. 在Build.cs中添加"ProceduralMeshCompo ...
- Altera FPGA 远程升级有关的几个IP的使用
在做在线远程升级的时候,一般需要两步:1.将数据写到外挂的flash中.2重新启动FPGA配置. 不过要做到远程升级,一般需要在原始程序中就考虑到加入远程升级模块,remote updata IP, ...