netty: marshalling传递对象,传输附件GzipUtils
netty: marshalling传递对象,传输附件GzipUtils
前端与服务端传输文件时,需要双方需要进行解压缩,也就是Java序列化。可以使用java进行对象序列化,netty去传输,但java序列化硬伤太多(无法跨语言,码流太大,性能太低),所以最好使用主流的编辑码框架来配合netty使用。此处使用的是JBossMarshalling框架。
用到的包:
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.jboss.marshalling/jboss-marshalling -->
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling</artifactId>
<version>2.0.0.CR1</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.jboss.marshalling/jboss-marshalling-serial -->
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-serial</artifactId>
<version>2.0.0.CR1</version>
</dependency>
用到的压缩包工具类:
gziputils.java
public class GzipUtils {
	 public static byte[] gzip(byte[] data) throws Exception{
	        ByteArrayOutputStream bos = new ByteArrayOutputStream();
	        GZIPOutputStream gzip = new GZIPOutputStream(bos);
	        gzip.write(data);
	        gzip.finish();
	        gzip.close();
	        byte[] ret = bos.toByteArray();
	        bos.close();
	        return ret;
	    }
	    public static byte[] ungzip(byte[] data) throws Exception{
	        ByteArrayInputStream bis = new ByteArrayInputStream(data);
	        GZIPInputStream gzip = new GZIPInputStream(bis);
	        byte[] buf = new byte[1024];
	        int num = -1;
	        ByteArrayOutputStream bos = new ByteArrayOutputStream();
	        while((num = gzip.read(buf, 0 , buf.length)) != -1 ){
	            bos.write(buf, 0, num);
	        }
	        gzip.close();
	        bis.close();
	        byte[] ret = bos.toByteArray();
	        bos.flush();
	        bos.close();
	        return ret;
	    }
	    public static void main(String[] args) throws Exception{
	        //读取文件
	        String readPath = System.getProperty("user.dir") + File.separatorChar + "sources" +  File.separatorChar + "Netty+3.1中文用户手册.doc.jpg";
	        File file = new File(readPath);
	        FileInputStream in = new FileInputStream(file);
	        byte[] data = new byte[in.available()];
	        in.read(data);
	        in.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 + "Netty+3.1中文用户手册.doc.jpg";
	        FileOutputStream fos = new FileOutputStream(writePath);
	        fos.write(ret2);
	        fos.close();        
	    }
}
Request.java类
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.java类
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;
	}	
}
MarshallingCodeCFactory.java
序列号编码解码类
public final class MarshallingCodeCFactory {
	/**
	 * 解码器
	 * @return
	 */
	public static MarshallingDecoder buildMarshallingDecoder() {
		final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
		final MarshallingConfiguration configuration = new MarshallingConfiguration();
		configuration.setVersion(5);
		UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
		//构建MarshallingDecoder对象,两个参数分别为provider和消息序列化后的最大长度
		MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024*1024*1);
		return decoder;
	}
	/**
	 * 编码器
	 * @return
	 */
	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对象,参数为provider;
		MarshallingEncoder encoder = new MarshallingEncoder(provider);
		return encoder;
	}
}
开始开发client,server功能
server.java
public class Server {
	public static void main(String[] args) throws InterruptedException {
		EventLoopGroup boss = new NioEventLoopGroup();
		EventLoopGroup worker = new NioEventLoopGroup();
		ServerBootstrap b = new  ServerBootstrap();
		b.group(boss, worker)
		.channel(NioServerSocketChannel.class)
		.option(ChannelOption.SO_BACKLOG, 1024)
		.handler(new LoggingHandler(LogLevel.INFO))
		.childHandler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel ch) throws Exception {
				// TODO Auto-generated method stub
				//设置编码解码
				ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
				ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
				ch.pipeline().addLast(new ServerHandler());
			}
		});
		ChannelFuture cf = b.bind(8765).sync();
		cf.channel().closeFuture().sync();
		boss.shutdownGracefully();
		worker.shutdownGracefully();
	}
}
serverHandler.java
需要继承ChannelHandlerAdapter类
public class ServerHandler extends ChannelHandlerAdapter {
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		// TODO Auto-generated method stub
		//super.exceptionCaught(ctx, cause);
		cause.printStackTrace();
		ctx.close();
	}
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		// TODO Auto-generated method stub
		//super.channelRead(ctx, msg);
		Request 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 + request.getId() +".png";
		FileOutputStream outputStream = new FileOutputStream(path);
		outputStream.write(attachment);
		outputStream.close();
		//返回数据
		Response response = new Response();
		response.setId(request.getId());
		response.setName("response: " + request.getName());
		response.setResponseMessage("相应的内容: " + request.getRequestMessage());
		ctx.writeAndFlush(response);
	}
}
client.java类
public class Client {
	public static void main(String[] args) throws Exception {
		EventLoopGroup worker = new NioEventLoopGroup();
		Bootstrap b = new Bootstrap();
		b.group(worker)
		.channel(NioSocketChannel.class)
		.handler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel ch) throws Exception {
				// TODO Auto-generated method stub
				//设置编码解码
				ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
				ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
				ch.pipeline().addLast(new ClientHandler());
			}
		});
		ChannelFuture cf = b.connect("127.0.0.1", 8765).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 + "resources" + File.separatorChar + "1.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));
			cf.channel().writeAndFlush(request);
		}
		System.out.println("user.dir: " + System.getProperty("user.dir")  + File.separatorChar + "resources" + File.separatorChar + "1.png" );
		cf.channel().closeFuture().sync();
		worker.shutdownGracefully();
	}
}
ClientHandler.java类
需要继承ChannelHandlerAdapter类
public class ClientHandler extends ChannelHandlerAdapter {
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		// TODO Auto-generated method stub
		//super.exceptionCaught(ctx, cause);
		cause.printStackTrace();
		ctx.close();
	}
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		// TODO Auto-generated method stub
		//super.channelRead(ctx, msg);
		try {
			Response response = (Response) msg;
			System.out.println("Client : " + response.getId() + ","+response.getName()+","+response.getResponseMessage());
		} finally {
			// TODO: handle finally clause
			ReferenceCountUtil.release(msg);
		}
	}
}
目录如下:

netty: marshalling传递对象,传输附件GzipUtils的更多相关文章
- netty: 编解码之jboss marshalling, 用marshalling进行对象传输
		
jboss marshalling是jboss内部的一个序列化框架,速度也十分快,这里netty也提供了支持,使用十分方便. TCP在网络通讯的时候,通常在解决TCP粘包.拆包问题的时候,一般会用以下 ...
 - netty的对象传输
		
pom <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <grou ...
 - Netty4.x中文教程系列(四)  对象传输
		
Netty4.x中文教程系列(四) 对象传输 我们在使用netty的过程中肯定会遇到传输对象的情况,Netty4通过ObjectEncoder和ObjectDecoder来支持. 首先我们定义一个U ...
 - Android 全局获取 Context 与使用 Intent 传递对象
		
=====================全局获取 Context======================== Android 开发中很多地方需要用到 Context,比如弹出 Toast.启动活 ...
 - Android--Intent传递对象
		
Intent 传递对象通常有两种实现方式,Serializable 和 Parcelable: 一.Serializable:序列化,表示将一个对象转换成可存储或可传输的状态,序列化后的对象可以在网络 ...
 - Intent传递对象——Serializable和Parcelable区别
		
为什么要将对象序列化? 1.永久性保存对象,保存对象的字节序列到本地文件中: 2.用过序列化对象在网络中传递对象: 3.通过序列化对象在进程间传递对象. 1.实现Serializable接口 Seri ...
 - 使用HttpURLConnection实现在android客户端和服务器之间传递对象
		
一般情况下,客户端和服务端的数据交互都是使用json和XML,相比于XML,json更加轻量级,并且省流量,但是,无论我们用json还是用xml,都需要我们先将数据封装成json字符串或者是一个xml ...
 - Android中的Parcel机制 实现Bundle传递对象
		
Android中的Parcel机制 实现了Bundle传递对象 使用Bundle传递对象,首先要将其序列化,但是,在Android中要使用这种传递对象的方式需要用到Android Parc ...
 - 为什么Intent传递对象的时候必须要将对象序列化呢?
		
Intent可以算是四大组件之间的胶水,比如在Activity1与Activity2之间传递对象的时候,必须要将对象序列化, 可是为什么要将对象序列化呢? Intent在启动其他组件时,会离开当前应用 ...
 
随机推荐
- 原生js监听input值发生变化
			
原生JS中可以使用oninput,onpropertychange,onchange oninput,onpropertychange,onchange的用法 1) onchange 触发事件必须满足 ...
 - springboot注入的四个注解
			
java配置主要靠java类和一些注解来达到和xml配置一样的效果,比较常用的注解有: @Configuration:声明一个类作为配置类,代替xml文件@Bean:声明在方法上,将方法的返回值加入B ...
 - Fastjson爆出重大漏洞,攻击者可使整个业务瘫痪
			
360网络安全响应中心 https://cert.360.cn/warning/detail?id=82a509e4543433625d6fe4361b5802c9 报告编号:B6-2019-0905 ...
 - k8s部署traefik
			
基础知识 同nginx相比,traefik能够自动感知后端容器变化,从而实现自动服务发现. traefik部署在k8s上分为daemonset和deployment两种方式各有优缺点: daemon ...
 - .NET Window服务启动又马上停止,报错IO.FileNotFoundException
			
最近公司需要开发一个Window服务推送系统,读取MongoDB写入消息队列,推送到各终端平台 但是在开发完成,最后的部署阶段,选中服务右击启动 看似正常,服务显示已启动(但实质已经被终止,因为Win ...
 - Javascript实现的智能消防栓状态监测画面
			
系统需要添加智能消防栓模块.集成了一家采用NbIOT通讯的智能消防栓产品.由第厂家平台对接NbIot特联网平台,我们平台提供一个api从第三方平台接收消防栓状态,用SignlaR把状态推送到前端.需要 ...
 - Sql Server 使用游标辅助循环
			
项目临时表#TMPxmdt 存有ID,起始年度,完成年度(int型)两个字段: 实现功能:将#TMPxmdt表中每个ID对应的起始年度至完成年度中所有年度以(ID, ND)的形式插入另一个临时表#TM ...
 - Ant Design Pro实现导出Excel
			
react Ant Design ProUI框架导出Excel(只能导出当前列表数据) 插件安装 npm install js-export-excel 安装完成之后开始引入 import Expor ...
 - Matlab函数装饰器
			
info.m function result_func= info(msg) function res_func =wrap(func) function varargout = inner_wrap ...
 - vue 解决ios编辑器输入框不能拉起
			
一.问题描述:Android .pc.下可以正常使用,在ios下可以拉起输入框但是无法输入 <div contenteditable="true" ></div& ...