Amber2011
V2EX  ›  Java

Spring 有什么方式可以在不同方法中更改 @RequestResponseBody 中同一个 entity 的序列化方式

By Amber2011 at 2023 年 3 月 2 日 · 2343 次点击

现在有个需求需要先请求 A 接口,再拿 A 接口的结果请求 B 接口

A 接口的结果和 B 接口的请求体实际上是一样的,但是 json 序列化的方式不同

A 接口 {name:'xxx',code:'xxx'....} B 接口 {BB_name:'xxx',BB_code:''}

如果现在想声明一个类来同时充当这 2 个接口的请求和响应,怎么在拿到 A 的结果直接把 bean 给 B,B 通过方法上的注解或者什么其他手段在发送 B 接口的时候,将 requestBody 的 json field 自动拼上 BB_前缀

  • 用 map 梭哈的话 replace 一下 key 名就好,但是后续应该还会有类似的接口,就想能不能写点什么工具

  • 用 @JsonSerialize 好像会改变整个类的,在方法参数上用好像不生效

  • 现在是写了注解在方法参数里,定义了前缀和后缀 . methodB(@Anno(prefix="BB_")@RequestBody Obj obj)

    • 但是后续不太会操作了.先是写了个自定义的 RequestBodyAdvice,在 afterBodyRead()里面直接改 body 的值,然后 return 后报错了. 现在在看 HandlerMethodArgumentResolver,在想 resolveArgument()里面应该怎么改.

菜鸡一个,也不知道思路对不对,请大佬们指点一下.

8 条回复  •  2023-03-03 12:05:52 +08:00
wleexi
   1
wleexi  
   2023 年 3 月 2 日
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor

看下这个
brust
   2
brust  
   2023 年 3 月 2 日
自定义两个 bean 感觉好点,然后 mapstruct 转一下
Amber2011
   3
Amber2011  
OP
   2023 年 3 月 2 日
@wleexi
已经在看这个类的接口 HandlerMethodReturnValueHandler 了,还没弄太明白,等明天再研究研究.方向对了就好

@brust
现在正在跑的版本是这样的,定义了 2 个 bean,然后互转. 就只是担心后续同类接口都要写 2 个 bean 就折磨了.自己想实现的这个方式写一半能力不足卡住了😂,不太想废掉这中方式,想再研究一下
litchinn
   4
litchinn  
   2023 年 3 月 3 日
RequestBodyAdvice, ResponseBodyAdvice 应该可以处理吧,
以下纯属个人吐槽
@Anno(prefix="BB_")这种方式感觉不灵活,应该在类上加上两个不同的注解 @ReqSerial @ResSerial 来指定怎么序列化
然后你会发现真要这么写了,工作量并没有比 2 楼说的方式来的小
所以个人感觉最好的方式就是用代码生成器定义模板,根据需求直接生成这两个类和相关 mapstruct 的代码,这样效率且代码易读、易维护
bk201
   5
bk201  
   2023 年 3 月 3 日
这个不就是 json 序列化改造一下就行了吗? jsonalias 之类的
wleexi
   6
wleexi  
   2023 年 3 月 3 日
对, 实现这个接口就可以了。
wleexi
   7
wleexi  
   2023 年 3 月 3 日
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
// TODO 可通过客户端的传递的请求头来切换不同的响应体的内容
mavContainer.setRequestHandled(true);
// returnValue = POJO
ApiResponse apiResponse = ApiResponse.ok(returnValue);
HttpServletResponse response = (HttpServletResponse) webRequest.getNativeResponse();
response.addHeader("v", "3");
ServletServerHttpResponse httpOutMessage = createOutputMessage(webRequest);
converter.write(apiResponse, MediaType.APPLICATION_JSON, httpOutMessage);
}
Aresxue
   8
Aresxue  
   2023 年 3 月 3 日
写一个 XxxBeanSerializerModifier 继承 com.fasterxml.jackson.databind.ser.BeanSerializerModifier 获取注解做修改

修改 spring mvc 序列化的 objectMapper 对象,objectMapper.setSerializerFactory(objectMapper.getSerializerFactory()
.withSerializerModifier(new XxxBeanSerializerModifier()));
© 2026 V2EX · 35ms · 3.9.8.5