项目里 前后端页面的http请求 及 dubbo服务间的RPC调用,返回值类型统一是一个Result,其结构如下。

@Datapublic class Result implements Serializable {    private static final long serialVersionUID = 1L;    /**     * 返回处理消息     */    private String message = "操作成功!";    /**     * 返回代码     */    private Integer code = 0;    /**     * 返回数据对象 data     */    @Getter    private T data;}

项目的RPC使用的是dubbo。我们在项目中定义了一个公用的DubboTraceFilter。这个Filter会将接口方法返回值Result对象打印到log文件里。序列化方式用的是 fastjson 的JSON#toJSONString。

背景介绍完毕。接下来说我要解决的事情。

注意到Result的data字段。它是泛型T的实例,就是说,这个data会是任意类型的数据。

从log里看,当data里是集合数据,例如,分页查询的场景,打印出来的log会超长。

这导致日志量很大,同时,这种无用的日志刷屏,也不利于我们排查问题。

简言之,看下面两段json串(为便于阅读,进行了格式化),希望log里出现后者。

{    "message": "成功",    "code": 200,    "result": ["0memob92142f2-ad8a-4812-913e-002f8f9d1894", "1memo77d4ad82-078f-4f73-a26e-c5302a596042", "2memoa69185c2-670d-480b-b1d2-19fd1326ecd5", "3memoee5d13a7-83bd-4430-a4b0-198e65201dc7", "4memo519d9d69-a27f-4864-8dd4-889ada1790a3", "5memo85034936-564b-41d8-94f0-ff1ac7be8d92", "6memoa22d4b20-828a-4ac5-a3fe-461283fc4154", "7memo7b2b8880-80b2-41f8-93d9-553467287e13", "8memo55afe9f2-e6b5-481c-9978-773fb5ff0f14", "9memoa5a92ffd-4e72-42f1-8d81-7221d2f371a3"],    "timestamp": 1666961782888}
{    "code": 200,    "message": "成功",    "result": "[\"0memob92142f2-ad8a-4812-913e-002f8f9d1894\",\"1memo77d4ad82-078f-4f73-a26e-c5302a596042\",\"2memoa6...",    "timestamp": 1666961782888}

那么,如何解决这个痛点?

我相信,找开发组里的任何一位同学,他都能解决。改DubboTraceFilter里的代码就行了,对序列化的json串进行相关截取。

而我想说什么呢?

一劳永逸!

程序里有还有其他地方也存在通过 JSON#toJSONString(Result) 打印log的代码。 难道逐个改吗?

所以,有没有简单的办法,改一处就全改了。

世上无易事,用心求精进。只要不放弃,办法就会有。

解决办法是 利用com.alibaba.fastjson.serializer.ObjectSerializer 和com.alibaba.fastjson.annotation.JSONField。

首先,自定义一个ObjectSerializer:StringAbbreviatingSerializer

import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.serializer.JSONSerializer;import com.alibaba.fastjson.serializer.ObjectSerializer;import org.apache.commons.lang.StringUtils;import java.io.IOException;import java.lang.reflect.Type;public class StringAbbreviatingSerializer implements ObjectSerializer {    /**     *     * @param serializer     * @param object field的值     * @param fieldName field的name     * @param fieldType field的类型,如java.lang.String     * @param features     * @throws IOException     */    @Override    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {        serializer.write( StringUtils.abbreviate(JSON.toJSONString(object),100));    }}

View Code

然后,使用com.alibaba.fastjson.annotation.JSONField 注解。

    @JSONField(serializeUsing = StringAbbreviatingSerializer.class)    private T data;

完了吗?我要补充——一并重写Result的toString方法。彻底一劳永逸。

@Datapublic class Result implements Serializable {    。。。。        @Override    public String toString() {        return JSON.toJSONString(this);    }}

要说明的是,加上这个注解后,对Result的实际值并不会有影响(包括http请求和dubbo调用,亲测)。所以,放心用,放心去序列化。妈妈再也不用担心我的日志爆屏了。

over!


当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!–buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/16837507.html


hr.signhr{width:80%;margin:0 auto;border: 0;height: 4px;background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0))}