Spring Boot 如果 RestController 中返回 null,则不会走进自定义 MappingJackson2HttpMessageConverter?

2018-05-04 18:28:12 +08:00
 FreeBSD

1. RestController 的代码

    @GetMapping("/{id}")
    @ResponseBody
    XXDto findById(@PathVariable String id) {
        return service.findById(id); // 此处如果返回 null,相应的转换没有做
    }

2. 代码 MappingJackson2HttpMessageConverter

@Configuration
public class HttpMessageConverter {
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {

        return new MappingJackson2HttpMessageConverter() {
            @Override
            protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
                if (object instanceof ArrayList) {
                    List list = (List) object;
                    if (!list.isEmpty()) {
                        if (list.get(0) instanceof SwaggerResource) {
                            super.writePrefix(generator, object);
                            return;
                        }
                    }
                }

                if (object instanceof Json || object instanceof SecurityConfiguration || object instanceof UiConfiguration) {
                    super.writePrefix(generator, object);
                    return;
                }

                generator.writeRaw("{\"code\": 0, \"result\": ");
                super.writePrefix(generator, object);
            }

            @Override
            protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {
                if (object instanceof ArrayList) {
                    List list = (List) object;
                    if (!list.isEmpty()) {
                        if (list.get(0) instanceof SwaggerResource) {
                            super.writeSuffix(generator, object);
                            return;
                        }
                    }
                }

                if (object instanceof Json || object instanceof SecurityConfiguration || object instanceof UiConfiguration) {
                    super.writeSuffix(generator, object);
                    return;
                }

                generator.writeRaw("}");
                super.writeSuffix(generator, object);
            }
        };
    }
}

3. 问题

当上述 1 中方法返回 null 时,2 中的 writePrefix 和 writeSuffix 不会被调到?有什么办法解决这个问题吗?

7322 次点击
所在节点    Java
11 条回复
letitbesqzr
2018-05-04 21:27:28 +08:00
Spring mvc 在 RequestResponseBodyMethodProcesser 会检测返回结果是不是 null , 如果不为 null 才会走 HttpMessageConverter 去处理。
letitbesqzr
2018-05-04 21:35:42 +08:00
纠错,是 org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor

如果确实要返回的 null 走你自己的 HttpMessageConverter, 建议自己去覆盖 RequestResponseBodyMethodProcessor 以接受 null。 或者自己定义一个 annotation @ResponseBodyNull 创建一个对应的 HandlerMethodReturnValueHandler
aa6563679
2018-05-05 00:05:23 +08:00
我记得在 spring mvc 里如果要手动处理 HttpServletResponse 就需要返回 null 或 void
FreeBSD
2018-05-05 11:10:55 +08:00
@letitbesqzr 感谢。看来只能手撸了。我之前还想过 AOP 的招
FreeBSD
2018-05-05 16:53:36 +08:00
按照[Custom HttpMessageConverter in Spring MVC]( https://stackoverflow.com/questions/22890952/custom-httpmessageconverter-in-spring-mvc) 没有成功
BBCCBB
2018-05-05 18:22:43 +08:00
建议你外面套一层
```java
class Response<T> {
int code;
String msg;
T value;
}
```
然后返回一个 Response<XXDto>
FreeBSD
2018-05-05 19:55:08 +08:00
@BBCCBB 嗯,是个方法,但是比较土啊
BBCCBB
2018-05-05 20:11:50 +08:00
@FreeBSD 额,这个方法绝壁不土,我待过的公司都是这种套路,因为你失败的时候可以返回具体的 code 和失败原因 msg,也便于前台展示
FreeBSD
2018-05-05 21:49:42 +08:00
@letitbesqzr 按照#5 楼链接的实现,发现还是有问题。转换时并没调用自定义的 RequestResponseBodyMethodProcessor 中的 handleReturnValue 方法。能再给点建议吗?
cqy2016
2018-05-06 14:59:50 +08:00
想在方法上省掉 wrapper 的话,扩展不应该用 message convert
提供一个 ResponseBodyAdvice 就行了
james2013
2018-05-16 17:59:34 +08:00
以前也是用 BBCCBB 的方法,cqy2016 说的很好,试了下,完美解决楼主的问题,并且做了其它几个方面的适配:
@ControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> {

@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
if("org.springframework.http.converter.json.MappingJackson2HttpMessageConverter".equals(converterType.getName())){
return true;
}
return false;
}

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if(body instanceof BaseResponseBean) return body;
return ResponseUtil.turnData(body);
}
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/452195

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX