草庐IT

Hessian2序列化支持这一点,让重构dubbo接口更容易了

buguge - Keep it simple,stupid 2023-04-17 原文

先看如下Hessian2序列化的测试代码。

// ------- MyDto -------
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;

@Data
@Accessors(chain = true)
public class MyDto implements Serializable {
    private String id;
    private String name;
    private Integer num;
}

//  ------ Hessian2序列化测试类 --------
import org.junit.Test;
import java.io.IOException;
import java.util.Base64;

public class Hessian2SerializationTest {
    @Test
    public void test() throws IOException {
        MyDto myDto1 = new MyDto();
        myDto1.setNum(1);
        byte[] bytes = Hessian2SerializationUtil.serialize(myDto1);
        /**
         * 通过{@link Base64#getEncoder()}把byte数组序列化成base64串。相应地,利用{@link Base64#getDecoder()}进行字符串的反序列化
         */
        String base64String = Base64.getEncoder().encodeToString(bytes); //new String(serialize, Charsets.UTF_8);
        System.out.println("base64串=" + base64String);
        MyDto myDto2 = (MyDto) Hessian2SerializationUtil.deSerialize(bytes);
        System.out.println(myDto2.getNum());

    }

    @Test
    public void test2() throws IOException {

        String serializedBase64Text = "QxRkdWJib2RlbW8uZHRvLk15RHRvMZMHaW50ZWdlcgRuYW1lAmlkYOFOTg==";
        byte[] bytes = Base64.getDecoder().decode(serializedBase64Text); //s.getBytes(Charsets.UTF_8);
        MyDto myDto2 = (MyDto) Hessian2SerializationUtil.deSerialize(bytes);
        System.out.println(myDto2.getNum());

    }

}

 

Hessian2序列化工具类

import com.alibaba.com.caucho.hessian.io.Hessian2Input;
import com.alibaba.com.caucho.hessian.io.Hessian2Output;
import com.alibaba.com.caucho.hessian.io.SerializerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class Hessian2SerializationUtil {
    /**
     * hessian2序列化,返回字节数组
     * @param obj 数据对象
     * @return
     * @throws IOException
     */
    public static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);
        try {
            hessian2Output.setSerializerFactory(new SerializerFactory());
            hessian2Output.writeObject(obj);
        } finally {
            byteArrayOutputStream.close();
            hessian2Output.close();
        }
        return byteArrayOutputStream.toByteArray();
    }

    /**
     * hessian2反序列化,得到反序列对象
     * @param bytes 序列化时生成的字节数组
     * @return
     * @throws IOException
     */
    public static Object deSerialize(byte[] bytes) throws IOException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        Hessian2Input hessianInput = new Hessian2Input(byteArrayInputStream);
        try {
            hessianInput.setSerializerFactory(new SerializerFactory());
            return hessianInput.readObject();
        } finally {
            byteArrayInputStream.close();
            hessianInput.close();
        }
    }
}
View Code

 

我要说什么呢?
我要说的是MyDto的num属性。当num是Integer时,我们得到hessian2序列化结果,然后,修改num为Long,前面的序列化结果可以正常反序列化。反之,num先是Long并且取值在int范围内,然后修改成Integer,亦能正常反序列化。

 

这一点对我在做的重构工作有什么帮助呢?

我们的系统中,服务商的主属性--服务商id,在不同子系统里,这个id字段的类型不统一,varchar/int/bigint,这就致使程序pojo里对应的这个服务商id属性,有的是String,有的是Integer,有的是Long,这给我们的系统迭代(开发&运维)带来了许多麻烦。系统不断升级迭代,服务越来越多,重构的工作量以及风险就加剧,产生系统熵增。

这几天的北京,市民陆续“阳”起来,我们公司也不例外,2/3的伙伴们都居家养病了。非常时期,一些开发需求就暂缓。我在上周不幸中招,经过难熬的一周,现已基本阳康,趁此机会,take action!决定动手重构一把。

其中,中台通道系统的channel-provider里有一个dubbo服务LevyMerchantRelationService,它依赖一个数据传输对象LevyMerchantRelationDTO,LevyMerchantRelationDTO里的服务商id类型是Integer。从dubbo控制台来观察,LevyMerchantRelationService的消费者有14个应用共8个java工程。

那么,我们要变更LevyMerchantRelationDTO里的服务商id类型为Long,这些工程中涉及到这个属性的代码,都要跟着做调整。大好的消息是,有了上面hessian2序列化的这个优势(dubbo RPC默认序列化方式是Hessian2),我们在上线的时候,就不用把14个消费者应用都同时上线,这将极大节省跨小组沟通和上线工作量,更重要的是,dubbo服务正常调用,丝毫不影响系统稳定。

 

这一点,增强了我这次重构的自信!

那么,我立马想到,如果dubbo接口方法的参数列表里有Integer的服务商id,是不是也能直接改成Long而不影响dubbo消费者的调用呢?经验证,这个是行不通的!

 

有关Hessian2序列化支持这一点,让重构dubbo接口更容易了的更多相关文章

  1. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  2. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  3. ruby - 在 Ruby 中比较序列 - 2

    假设我必须(小型到中型)阵列:tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]如何确定tokens是否以相同的顺序包含template的所有条目?(请注意,在上面的示例中,应忽略第一个“ccc”,从而由于最后一个“ccc”而导致匹配。) 最佳答案 这适用于您的示例数据。tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]po

  4. ruby-on-rails - carrierwave:在序列化动态属性上安装 uploader - 2

    首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟

  5. ruby - 如何使用 readline 支持重新安装 ruby​​? - 2

    我已经按照https://github.com/wayneeseguin/rvm#installation上的说明通过RVM安装了Ruby.有关信息,我有所有文件(readline-5.2.tar.gz、readline-6.2.tar.gz、ruby-1.9.3-p327.tar.bz2、rubygems-1.8.24.tgz、wayneeseguin-rvm-stable.tgz和yaml-0.1.4.tar.gz)在~/.rvm/archives目录中,我不想在任何目录中重新下载它们方式。当我这样做时:sudo/usr/bin/apt-getinstallbuild-essent

  6. ruby-on-rails - "undefined method ` stub_request '"访问 RSpec 支持文件中的方法时 - 2

    我的Ruby-on-Rails项目中有以下文件结构,用于规范:/spec/msd/serviceservice_spec.rb/support/my_modulerequests_stubs.rb我的request_stubs.rb有:moduleMyModule::RequestsStubsmodule_functiondeflist_clientsurl="dummysite.com/clients"stub_request(:get,url).to_return(status:200,body:"clientsbody")endend在我的service_spec.rb我有:re

  7. ruby - Ruby 是否支持逐字字符串? - 2

    Ruby是否支持(找不到更好的词)非转义(逐字)字符串?就像在C#中一样:@"c:\ProgramFiles\"...或者在Tcl中:{c:\ProgramFiles\} 最佳答案 是的,您需要在字符串前加上%前缀,然后是描述其类型的单个字符。你想要的是%q{c:\programfiles\}。镐书很好地涵盖了这一点here,部分是通用分隔输入。 关于ruby-Ruby是否支持逐字字符串?,我们在StackOverflow上找到一个类似的问题: https:/

  8. ruby - 在 Ruby 1.8 中支持 Ruby 1.9 的哈希语法 - 2

    我正在编写一个Rubygem,在我的代码中使用{key:'value'}哈希语法。我的测试都在1.9.x中通过,但我(可以理解)在1.8.7中得到syntaxerror,unexpected':',expecting')'。是否有支持1.8.x的最佳实践?我是否需要使用我们的老friend=>重写代码,还是有更好的策略? 最佳答案 我认为你运气不好,如果你想支持1.8,那么你必须使用=>。像往常一样,我会提到在1.9的某些情况下您必须使用=>:如果键不是一个符号。请记住,任何对象(符号、字符串、类、float……)都可以是Ruby哈

  9. 机器学习——时间序列ARIMA模型(四):自相关函数ACF和偏自相关函数PACF用于判断ARIMA模型中p、q参数取值 - 2

    文章目录1、自相关函数ACF2、偏自相关函数PACF3、ARIMA(p,d,q)的阶数判断4、代码实现1、引入所需依赖2、数据读取与处理3、一阶差分与绘图4、ACF5、PACF1、自相关函数ACF自相关函数反映了同一序列在不同时序的取值之间的相关性。公式:ACF(k)=ρk=Cov(yt,yt−k)Var(yt)ACF(k)=\rho_{k}=\frac{Cov(y_{t},y_{t-k})}{Var(y_{t})}ACF(k)=ρk​=Var(yt​)Cov(yt​,yt−k​)​其中分子用于求协方差矩阵,分母用于计算样本方差。求出的ACF值为[-1,1]。但对于一个平稳的AR模型,求出其滞

  10. ruby-on-rails - Rails 编辑序列化的 JSON 数据 - 2

    我有一个存储JSON数据的列。当它处于编辑状态时,我不知道如何显示它。serialize:value,JSON=f.fields_for:valuedo|ff|.form-group=ff.label:short=ff.text_field:short,class:'form-control'.form-group=ff.label:long=ff.text_field:long,class:'form-control' 最佳答案 代替=f.fields_for:valuedo|ff|请使用以下代码:=f.fields_for:va

随机推荐