记录一次springAop引发的惨案

记录一次springAop引发的惨案

一、问题场景

因为项目中的id是long类型,在controller返回前端的时候会失真(js的类型和java不一致,不知道的百度)

//需要的结果
{
    "errorCode": 0,
    "msg": "处理成功",
    "data": {
        "AA": [ {
                "id": "1564127421015329420",
                "code": "ecf687fcc1438f18ae14c20f288aa386c681f37995c24fdc9457c9b3666d578f",  
            }
        ]
    }
}

二、解决

因此在实体类上的id字段加上了@JsonSerialize(using= ToStringSerializer.class)注解
这个是spring默认的转换json的工具,jackson提供的
但是在加了注解之后发现有的方法有效,有的方法没有效果,现在给出解决办法一

  public void save(HttpServletResponse response, @RequestBody XXX xxx) throws Exception {
        //token校验
        User user = checkToken(xxx.getToken());
        ApiResult result =  xxxService.save(xxx);
        //return result;
        //直接利用response的getWriter获得输出流,向外输出,就是页面
        ObjectMapper objectMapper = new ObjectMapper();
        String bbb = objectMapper.writeValueAsString(result);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().print(bbb);
        //ResponseUtils.writeContent(response,bbb);
    }

上述方法虽能解决,总觉得不够优雅,搂着跟踪源码,找到输出的代码

//这个代码在 org.springframework.http.converter.AbstractGenericHttpMessageConverter里面
public final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType,
			HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

		final HttpHeaders headers = outputMessage.getHeaders();
		addDefaultHeaders(headers, t, contentType);

		if (outputMessage instanceof StreamingHttpOutputMessage) {
			StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
			streamingOutputMessage.setBody(outputStream -> writeInternal(t, type, new HttpOutputMessage() {
				@Override
				public OutputStream getBody() {
					return outputStream;
				}
				@Override
				public HttpHeaders getHeaders() {
					return headers;
				}
			}));
		}
		else {
			writeInternal(t, type, outputMessage);//这一步就是进行json转换的
			outputMessage.getBody().flush();//这一步直接输出
		}
	}

这里分享一下如何查看结果是否被转化为json
这个是进入write方法的返回对象,里面的id还是Long类型,接着到最后一步

用idea的可以在断点里面打开计算
在这里插入图片描述
点击红点,打开计算输入公式,看到输出流,就是一堆数字,直接右键,view as string 就能看到字符串结果。

回归正题,其实我的问题并不是有没有转化,而是发现这个方法根本没有进入断点,找了半天终于发现这个controller上面加了aop的注解,aop的注解使用的是around方法,但是没有返回值,而是直接输出在页面

HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
    	ResponseUtils.writeJson(response, result);
    	//return result;

其实发现只用将aop的返回结果改为Object,在最后返回result即可。
aop的配置就不贴出来了,这里提供了一种解决long类型的数据失真解决方法

三、结束

问题解决,记录于此!
本文为原创文章转载请注明出处。
aop的如有疑问请留言。

发布了42 篇原创文章 · 获赞 13 · 访问量 8316

猜你喜欢

转载自blog.csdn.net/weixin_43328357/article/details/97393642