前端与服务端传输文件时,需要双方需要进行解压缩,也就是Java序列化。可以使用java进行对象序列化,netty去传输,但java序列化硬伤太多(无法跨语言,码流太大,性能太低),所以最好使用主流的编辑码框架来配合netty使用。此处使用的是JBossMarshalling框架。
附下载链接
1,jboss-marshalling-1.3.0.CR9.jar
2,jboss-marshalling-serial-1.3.0.CR9.jar
demo目录
解压缩类:GZipUtils.java
package bhz.netty.serial;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;public class GZipUtils {public static byte[] gzip(byte[] data) throws Exception{ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);gzipOutputStream.write(data);gzipOutputStream.finish();gzipOutputStream.close();byte[] ret = byteArrayOutputStream.toByteArray();byteArrayOutputStream.close();return ret;}public static byte[] ungzip(byte[] data) throws Exception{ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);byte[] buf = new byte[1024];int num = -1;ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();while((num = gzipInputStream.read(buf,0,buf.length)) != -1) {byteOutputStream.write(buf,0,num);}gzipInputStream.close();byteArrayInputStream.close();byte[] ret = byteOutputStream.toByteArray();byteOutputStream.flush();byteOutputStream.close();return ret;}public static void main(String[] arg0) throws Exception{String readPath = System.getProperty("user.dir")+File.separatorChar+"sources"+File.separatorChar+"001.png";File file = new File(readPath);FileInputStream inputStream = new FileInputStream(file);byte[] data = new byte[inputStream.available()];inputStream.read(data);inputStream.close();System.out.println("文件原始大小为:"+data.length);//测试压缩byte[] ret1 = GZipUtils.gzip(data);System.out.println("压缩之后大小为:"+ret1.length);//测试还原byte[] ret2 = GZipUtils.ungzip(ret1);System.out.println("还原时候大小为:"+ret2.length);String writePath = System.getProperty("user.dir")+File.separatorChar+"receive"+File.separatorChar+"001.png";FileOutputStream outputStream = new FileOutputStream(writePath);outputStream.write(ret2);outputStream.close();}
}
客户端发送给服务端的请求对象Request
package bhz.netty.serial;import java.io.Serializable;public class Request implements Serializable{private static final long SerialVersionUID = 1L;private String id;private String name;private String requestMessage;private byte[] attachment;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getRequestMessage() {return requestMessage;}public void setRequestMessage(String requestMessage) {this.requestMessage = requestMessage;}public byte[] getAttachment() {return attachment;}public void setAttachment(byte[] attachment) {this.attachment = attachment;}}
服务端发送给客户端的回复对象Response
package bhz.netty.serial;import java.io.Serializable;public class Response implements Serializable{private static final long SerialVersionUID = 1L;private String id;private String name;private String responseMessage;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getResponseMessage() {return responseMessage;}public void setResponseMessage(String responseMessage) {this.responseMessage = responseMessage;}}
Marshalling框架编解码类MarshallingCodeCFactory.java
package bhz.netty.serial;import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider;public final class MarshallingCodeCFactory {/** 创建JBoss Marshalling解码器MarshallingDecoder* @return MarshallingDecoder* */public static MarshallingDecoder buildMarshallingDecoder() {final MarshallerFactory marshallingFactory = Marshalling.getProvidedMarshallerFactory("serial");final MarshallingConfiguration configuration = new MarshallingConfiguration();configuration.setVersion(5);UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallingFactory, configuration);//构件Netty的marshallingDecoder对象,两个参数分别为Provider和单个消息序列化后的最大长度MarshallingDecoder decoder = new MarshallingDecoder(provider,1024*1024*1);return decoder;}/** 创建Marshalling解码器 MarshallingEncoder* return MarshallingEncoder* */public static MarshallingEncoder buildMarshallingEncoder() {final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");final MarshallingConfiguration configuration = new MarshallingConfiguration();configuration.setVersion(5);MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);MarshallingEncoder encoder = new MarshallingEncoder(provider);return encoder;}}
服务端Server
package bhz.netty.serial;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;public class Server {public static void main(String[] args) throws Exception{// TODO Auto-generated method stubEventLoopGroup boss = new NioEventLoopGroup();EventLoopGroup worker = new NioEventLoopGroup();ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(boss,worker).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG,1024).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel sc) throws Exception {// TODO Auto-generated method stubsc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());sc.pipeline().addLast(new ServerHandler());}});ChannelFuture channelFuture = bootstrap.bind(8888).sync();channelFuture.channel().closeFuture().sync();boss.shutdownGracefully();worker.shutdownGracefully();}}
服务端处理方法ServerHandler.java
package bhz.netty.serial;import java.io.File;
import java.io.FileOutputStream;import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class ServerHandler extends SimpleChannelInboundHandler {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {// TODO Auto-generated method stubRequest request = (Request)msg;System.out.println("Server :" + request.getId()+" , "+request.getName()+" , "+request.getRequestMessage());byte[] attachment = GZipUtils.ungzip(request.getAttachment());String path = System.getProperty("user.dir")+File.separatorChar+"receive"+File.separatorChar+"001.png";FileOutputStream fileOutputStream = new FileOutputStream(path);fileOutputStream.write(attachment);fileOutputStream.close();Response response = new Response();response.setId(request.getId());response.setName("response : "+request.getId());response.setResponseMessage("相应内容 : "+request.getId());ctx.writeAndFlush(response);}
}
客户端Client
package bhz.netty.serial;import java.io.File;
import java.io.FileInputStream;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;public class Client {public static void main(String[] args) throws Exception{// TODO Auto-generated method stubEventLoopGroup worker = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap();bootstrap.group(worker).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel sc) throws Exception {// TODO Auto-generated method stubsc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());sc.pipeline().addLast(new ClientHandle());}});ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",8888).sync();for(int i=0;i<5;i++) {Request request = new Request();request.setId(""+i);request.setName("Pro"+i);request.setRequestMessage("数据信息Client~Server:"+i);String path = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "001.png";File file = new File(path);FileInputStream inputStream = new FileInputStream(file);byte[] data = new byte[inputStream.available()];inputStream.read(data);inputStream.close();request.setAttachment(GZipUtils.gzip(data));channelFuture.channel().writeAndFlush(request);}channelFuture.channel().closeFuture().sync();worker.shutdownGracefully();}}
客户端处理类
package bhz.netty.serial;import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class ClientHandle extends SimpleChannelInboundHandler{@Overrideprotected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {// TODO Auto-generated method stubResponse response = (Response)msg;System.out.println("Client :" + response.getId()+" , "+response.getName()+" , "+response.getResponseMessage());}
}
运行结果
注意:先启动服务端,在启动客户端
结论:
可以看出,这里实现了客户端与服务端进行了对象的传输,不再是简单的String对象的传输,并进行了图片的编辑码处理(其他文件同理)。