一、知识点
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)运行方式
- 运行 ClientTest
- 注释掉 client 包下的 dto 和 ClientTest
- 运行 ServerTest
- 运行结果:
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