BeanUtils.copyProperties + hessian导致类型转换异常

一、知识点

BeanUtils 是 org.springframework.beans 包下的类。

  • BeanUtils.copyProperties,是浅拷贝,引用类型拷贝的是地址。
  • 范型擦除。(List<Child> 拷贝给 List<Parent>,即使范型类型不一致,也能拷贝成功。List<Parent> 值是 List<Child> 的地址,实际类型还是 List<Child> )

Hessian 序列化,反序列化找不到类时自动转换成HashMap。

二、测试代码

客户端:使用 hessian 将数据序列化后,存入本地文件。

服务端:从本地文件读取数据,用hessian 反序列化,获取 dto。

1)客户端

package com.llk.helloworld.worktest.BeanUtilsErrorTest.client;

import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;

@Getter
@Setter
public class Address implements Serializable {

    private static final long serialVersionUID = 1L;

    private String province;

    private String city;
}
package com.llk.helloworld.worktest.BeanUtilsErrorTest.client;

import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;

@Getter
@Setter
public class RequestDto implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    private String code;

    private List<com.llk.helloworld.worktest.BeanUtilsErrorTest.client.Address> addressList;
}
package com.llk.helloworld.worktest.BeanUtilsErrorTest;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import org.springframework.beans.BeanUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;

public class ClientTest {
    public static void main(String[] args)throws Exception{

        com.llk.helloworld.worktest.BeanUtilsErrorTest.client.Address cAddress = new com.llk.helloworld.worktest.BeanUtilsErrorTest.client.Address();
        cAddress.setProvince("p1");
        cAddress.setCity("c1");
        com.llk.helloworld.worktest.BeanUtilsErrorTest.client.RequestDto cRequestDto = new com.llk.helloworld.worktest.BeanUtilsErrorTest.client.RequestDto();
        cRequestDto.setCode("001");
        cRequestDto.setName("name001");
        cRequestDto.setAddressList(Arrays.asList(cAddress));
        //赋值
        com.llk.helloworld.worktest.BeanUtilsErrorTest.server.RequestDto sRequestDto = new com.llk.helloworld.worktest.BeanUtilsErrorTest.server.RequestDto();
        BeanUtils.copyProperties(cRequestDto,sRequestDto);
        System.out.println(sRequestDto);

        //序列化
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        Hessian2Output output = new Hessian2Output(os);
        output.writeObject(sRequestDto);
        output.close();
        byte[] bytes = os.toByteArray();

        //字节流存入文件
        FileOutputStream fos = new FileOutputStream("/Users/llk/Desktop/my.dat");
        fos.write(bytes);
        fos.close();

    }

}

 2)服务端

package com.llk.helloworld.worktest.BeanUtilsErrorTest.server;

import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;

@Getter
@Setter
public class Address implements Serializable {

    private static final long serialVersionUID = 1L;

    private String province;

    private String city;
}
package com.llk.helloworld.worktest.BeanUtilsErrorTest.server;

import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;

@Getter
@Setter
public class RequestDto implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    private String code;

    private List<com.llk.helloworld.worktest.BeanUtilsErrorTest.server.Address> addressList;
}
package com.llk.helloworld.worktest.BeanUtilsErrorTest;

import com.caucho.hessian.io.Hessian2Input;
import com.llk.helloworld.worktest.BeanUtilsErrorTest.server.Address;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;

public class ServerTest {

    public static void main(String[] args)throws Exception{
        //文件中获取字节流
        FileInputStream fis = new FileInputStream( "/Users/llk/Desktop/my.dat");
        byte[] bytes1 = new byte[fis.available()];
        fis.read(bytes1);

        //反序列化
        ByteArrayInputStream in = new ByteArrayInputStream(bytes1);
        Hessian2Input input = new Hessian2Input(in);
        com.llk.helloworld.worktest.BeanUtilsErrorTest.server.RequestDto res = (com.llk.helloworld.worktest.BeanUtilsErrorTest.server.RequestDto)input.readObject();
        Address address = res.getAddressList().get(0);
        System.out.println("结果"+address);
        input.close();
    }
}

 3)运行方式

  1. 运行 ClientTest
  2. 注释掉 client 包下的 dto 和 ClientTest
  3. 运行 ServerTest
  4. 运行结果:

    Exception in thread "main" java.lang.ClassCastException: java.util.HashMap cannot be cast to com.llk.helloworld.worktest.BeanUtilsErrorTest.server.Address

三、结果分析

1、浅拷贝+范型擦除,导致 server 包下的 RequestDto 中的 address 属性,类型是client包下的 address。

/Users/llk/Desktop/my.dat 文件内容,如下:

C0@com.llk.helloworld.worktest.BeanUtilsErrorTest.server.RequestDto�namecode addressList`name001001qjava.util.Arrays$ArrayListC0=com.llk.helloworld.worktest.BeanUtilsErrorTest.client.Address�provincecityap1c1

2、hessian 反序列化,若找不到类,转 HashMap

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值