注:源代码来自享学课堂,略有修改,学习之后所做笔记,方便回顾,也给大家一个参考
why:
Java序列化仅仅是Java编解码技术的一种
1.网络传输
2.对象持久化
java自带序列化的缺点
1、无法跨语言
2、序列化之后的流太大
3、序列化新能的,耗时长
netty常用的序列化
Netty内置了对JBoss Marshalling和Protocol Buffers的支持
Protocol Buffers
一下只是简化的代码,pipleLine添加ProtobufEncoder、ProtobufDecoder编解码就行,其他的相关文件,请参考protocol使用文档
导入jar
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
客户端
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception {
// 用来添加报文长度字段
ch.pipeline().addLast(
new ProtobufVarint32LengthFieldPrepender());
//添加 ProtobufEncoder 进行序列化将实体类编码为字节
ch.pipeline().addLast(new ProtobufEncoder());
//添加自己的业务Handler
ch.pipeline().addLast(
new ProtoBufClientHandler());
}
});
服务端
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
//添加 ProtobufVarint32FrameDecoder 以分离数据帧
ch.pipeline().addLast(
new ProtobufVarint32FrameDecoder());
//添加 ProtobufDecoder 反序列化将字节解码为实体
ch.pipeline().addLast(new ProtobufDecoder(
PersonProto.Person.getDefaultInstance()
));
//添加自己业务Handler
ch.pipeline().addLast(new ProtoBufServerHandler());
}
内置MessagePack,使用MsgPackEncoder序列化
导入jar
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack</artifactId>
<version>0.6.12</version>
</dependency>
需要被序列化的对象加上@Message注解(一下省略了set/get方法,使用是请自行加上)
@Data
@Message
public class User {
private String id;
private String userName;
private int age;
}
使用MessagePack自定义编解码器
编码器
public class MsgPackEncoder extends MessageToByteEncoder<Object> {
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)
throws Exception {
MessagePack messagePack = new MessagePack();
byte[] raw = messagePack.write(msg);
out.writeBytes(raw);
}
}
解码器:这里不使用ByteToMessageDecode,而使用MessageToMessageDecoder,是应为把bytebuf当做message来处理的
public class MsgPackDecoder extends MessageToMessageDecoder<ByteBuf> {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg,
List<Object> out) throws Exception {
int length = msg.readableBytes();
byte[] array = new byte[length];
msg.getBytes(msg.readerIndex(),array,0,length);
MessagePack messagePack = new MessagePack();
out.add(messagePack.read(array,User.class));
}
}
客户端主函数
public class MyClient {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress("127.0.0.1",8080))
.handler(new MyChannelInit());
ChannelFuture future = bootstrap.connect().sync();
future.channel().closeFuture().sync();
group.shutdownGracefully().sync();
}
private static class MyChannelInit extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//粘包,编码
pipeline.addLast(new LengthFieldPrepender(2));
//序列化
pipeline.addLast(new MyMessageEncoder());
//入站解码
pipeline.addLast(new LineBasedFrameDecoder(1024));
//自定义handler,
pipeline.addLast(new MyClientHandler());
}
}
}
客户端handler
public class MyClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
private AtomicInteger counter = new AtomicInteger(0);
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
System.out.println("client Accept[" + byteBuf.toString(CharsetUtil.UTF_8)
+ "] and the counter is:" + counter.incrementAndGet());
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//还是一个一个发送,接收也是一个一个接收的
User[] users = makeUsers();
for (User user : users) {
ctx.write(user);
}
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
/**
* 生成多个用户对象
* @return 数组
*/
private User[] makeUsers() {
User[] users = new User[10];
User user;
for (int i = 0; i < 10; i++) {
user = new User();
user.setAge(i);
String userName = "序列化-" + i;
user.setUserName(userName);
users[i] = user;
}
return users;
}
}
服务端主函数
LengthFieldBasedFrame:实际数据包长度 = 长度域中记录的数据长度 + lengthFieldOffset + lengthFieldLength + lengthAdjustment
public class MyServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(group)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(8080))
.childHandler(new MyServerChannelInit());
ChannelFuture future = bootstrap.bind().sync();
future.channel().closeFuture().sync();
group.shutdownGracefully().sync();
}
private static class MyServerChannelInit extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//这里服务器只是给客户端发送简单的字符串消息,所以未加出站编码相关处理
//入站分理处编码的长度并拿到数据
pipeline.addLast(new LengthFieldBasedFrameDecoder(65535,0,2,0,2));
//反序列化
pipeline.addLast(new MyMessageDecoder());
//自定义handler
pipeline.addLast(new MyServerHandler());
}
}
}
服务端handler
@ChannelHandler.Sharable
public class MyServerHandler extends ChannelInboundHandlerAdapter {
private AtomicInteger counter = new AtomicInteger(0);
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//将上一个handler生成的数据强制转型
User user = (User) msg;
System.out.println("Server Accept[" + user
+ "] and the counter is:" + counter.incrementAndGet());
//服务器的应答
String resp = "I process user :" + user.getUserName()
+ System.getProperty("line.separator");
ctx.writeAndFlush(Unpooled.copiedBuffer(resp.getBytes()));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
服务端结果
Server Accept[User(id=null, userName=序列化-0, age=0)] and the counter is:1
Server Accept[User(id=null, userName=序列化-1, age=1)] and the counter is:2
Server Accept[User(id=null, userName=序列化-2, age=2)] and the counter is:3
Server Accept[User(id=null, userName=序列化-3, age=3)] and the counter is:4
Server Accept[User(id=null, userName=序列化-4, age=4)] and the counter is:5
Server Accept[User(id=null, userName=序列化-5, age=5)] and the counter is:6
Server Accept[User(id=null, userName=序列化-6, age=6)] and the counter is:7
Server Accept[User(id=null, userName=序列化-7, age=7)] and the counter is:8
Server Accept[User(id=null, userName=序列化-8, age=8)] and the counter is:9
Server Accept[User(id=null, userName=序列化-9, age=9)] and the counter is:10
客户端结果
client Accept[I process user :序列化-0] and the counter is:1
client Accept[I process user :序列化-1] and the counter is:2
client Accept[I process user :序列化-2] and the counter is:3
client Accept[I process user :序列化-3] and the counter is:4
client Accept[I process user :序列化-4] and the counter is:5
client Accept[I process user :序列化-5] and the counter is:6
client Accept[I process user :序列化-6] and the counter is:7
client Accept[I process user :序列化-7] and the counter is:8
client Accept[I process user :序列化-8] and the counter is:9
client Accept[I process user :序列化-9] and the counter is:10