All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.zlyx.easynetty.client.core.AbstractNettyClient Maven / Gradle / Ivy

package com.zlyx.easynetty.client.core;

import java.lang.reflect.ParameterizedType;
import java.util.Arrays;

import com.alibaba.fastjson.JSONObject;
import com.zlyx.easycore.tool.EasyBuffer;
import com.zlyx.easycore.tool.Hex;
import com.zlyx.easycore.utils.ByteUtils;
import com.zlyx.easycore.utils.JsonUtils;
import com.zlyx.easycore.utils.LogUtils;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

/**
 * 
 * @Auth 赵光
 * @Desc 描述 Netty非塞式->长连接->客户端
 * @Date 2019年4月8日
 */
public abstract class AbstractNettyClient extends AbstractBaseNettyClient implements Runnable {

	protected String key;

	protected ChannelFactory factory;

	protected Class tClass;

	public AbstractNettyClient(String key, String host, int port) throws Exception {
		if(key == null) {
			key = EasyBuffer.valueOf(this.hashCode());
		}
		this.key = key;
		this.tClass = getTClass(this.getClass());
		this.factory = new ChannelFactory(this, host, port);
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		LogUtils.info(this.getClass(), key + "-> 客户端与服务端建立连接...");
		this.write(doOnConnection(ctx));
	}

	/**
	 * 客户端与服务端建立连接时
	 * 
	 * @param ctx
	 */
	public abstract T doOnConnection(ChannelHandlerContext ctx) throws Exception;

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		LogUtils.info(this.getClass(), key + "-> 客户端与服务端连接关闭...");
		doCloseConnection(ctx);
	}

	/**
	 * 客户端与服务端断开连接时调用
	 * 
	 * @param ctx
	 */
	public void doCloseConnection(ChannelHandlerContext ctx) throws Exception {
	}

	@SuppressWarnings("unchecked")
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
		try {
			byte[] response = (byte[]) message;
			T data = null;
			if (response != null) {
				if (Hex.class == tClass) {
					data = (T) Hex.newHex(ByteUtils.bytesToHexString(response));
				} else if (byte[].class == tClass) {
					data = (T) response;
				} else if (JSONObject.class == tClass) {
					data = (T) JsonUtils.parse(response);
				} else {
					data = (T) new String(response);
				}
			}
			this.write(doService(ctx.channel(), data));
		} catch (Exception e) {
			LogUtils.err(e);
		} finally {
			ReferenceCountUtil.release(message);
		}
	}

	/**
	 * 长连接交互业务
	 * 
	 * @param          
	 * @param channnel
	 * @param msg
	 * @return
	 * @throws Exception
	 */
	public abstract T doService(Channel channel, T res) throws Exception;

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}

	public void write(T msg) throws Exception {
		if (msg != null) {
			if (Hex.class == tClass) {
				this.writeBytes(ByteUtils.hexStringToByte(((Hex) msg).getHex()));
			} else if (byte[].class == tClass) {
				this.writeBytes((byte[]) msg);
			} else if (JSONObject.class == tClass) {
				this.writeBytes(((JSONObject) msg).toString().getBytes());
			} else if (String.class == tClass) {
				this.writeBytes(((String) msg).getBytes());
			} else if (Object.class == tClass) {
				this.writeBytes(msg.toString().getBytes());
			} else {
				this.writeBytes(((String) msg).getBytes());
			}
		}
	}

	/**
	 * 向服务端输出Byte数组
	 * 
	 * @param bytes byte数组
	 * @throws Exception
	 */
	public void writeBytes(byte[] bytes) throws Exception {
		if (bytes != null) {
			LogUtils.info(this.getClass(), key + " -> " + Arrays.toString(bytes));
			factory.getChannel(key).writeAndFlush(bytes);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
		LogUtils.err(e);
		ctx.close();
	}

	public String getKey() {
		return key;
	}

	@Override
	public void run() {
		try {
			this.factory.getChannel(key);
			LogUtils.info(this.getClass(), key + "-> 建立一个连接");
		} catch (Exception e) {
			LogUtils.err(e);
		}
	}

	/***
	 * 关闭通道
	 */
	public void close() {
		this.factory.getChannel(key).close();
	}

	@SuppressWarnings("unchecked")
	public Class getTClass(Class tClass) throws Exception {
		if (tClass.getGenericSuperclass().getTypeName().contains("<")) {
			return (Class) ((ParameterizedType) tClass.getGenericSuperclass()).getActualTypeArguments()[0];
		} else if (tClass != Object.class) {
			return getTClass(tClass.getSuperclass());
		}
		throw new Exception("You must define an generics to specify data types!");
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy