netty 本地模拟客户端

This commit is contained in:
limqhz
2020-06-09 23:21:23 +08:00
parent 96584aa44d
commit 644c0063e7
21 changed files with 1726 additions and 17 deletions

View File

@@ -3,6 +3,7 @@ package com.sv.netty.netty;
import com.google.common.collect.Maps;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
@@ -65,13 +66,13 @@ public class BootService {
private Map<ChannelOption, Object> channelOptions;
@Autowired
private ServerProtocolInitalizer serverProtocolInitalizer;
private final ServerProtocolInitializer serverProtocolInitializer;
/**
* 初始化netty启动配置
*/
public void init() {
// bossGroup 只处理连接请求真正的客户端业务处理是由workerGroup 处理的 都是无效循环的
workerGroup = new NioEventLoopGroup();
bossGroup = new NioEventLoopGroup();
channelOptions = Maps.newHashMap();
@@ -81,16 +82,17 @@ public class BootService {
// channelOptions.put(ChannelOption.TCP_NODELAY,TCP_NODELAY);
channelOptions.put(ChannelOption.SO_REUSEADDR,reuseaddr);
bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(serverProtocolInitalizer);
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 设置服务器的通道是NIOServerSocketChannel
.childHandler(serverProtocolInitializer);
for (Map.Entry<ChannelOption, Object> entry : channelOptions.entrySet()) {
bootstrap.option(entry.getKey(), entry.getValue());
}
bootstrap.childOption(ChannelOption.TCP_NODELAY,nodelay);
bootstrap.childOption(ChannelOption.SO_KEEPALIVE,keepalive);
// 绑定一个端口并且同步 启动服务器
serverChannelFuture = bootstrap.bind(new InetSocketAddress(port)).sync();
logger.info("成功bind端口:" + port);
// 对关闭通道进行监听 (异步模型)
serverChannelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
logger.error("启动NETTY TCP异常:", e);
@@ -122,4 +124,9 @@ public class BootService {
public void setChannelOptions(Map<ChannelOption, Object> channelOptions) {
this.channelOptions = channelOptions;
}
public BootService(ServerProtocolInitializer serverProtocolInitializer) {
this.serverProtocolInitializer = serverProtocolInitializer;
}
}

View File

@@ -23,6 +23,11 @@ public class ClientHandler extends ChannelInboundHandlerAdapter {
public ClientHandler() {
}
/**
* 当通道就绪就会触发
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
@@ -33,10 +38,16 @@ public class ClientHandler extends ChannelInboundHandlerAdapter {
super.channelInactive(ctx);
}
/**
* 当通道有读取事件时触发
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
System.out.println("接收服务器响应msg:[" + msg + "]");
logger.info("接收服务器响应msg:[" + msg + "]");
}
@Override

View File

@@ -4,6 +4,7 @@ import com.sv.netty.config.Constant;
import com.sv.netty.config.SpringContextHolder;
import com.sv.netty.service.MessageService;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,6 +33,12 @@ public class ServerHandler extends ChannelInboundHandlerAdapter {
super.channelActive(ctx);
}
/**
* 读取客户端发送的消息
* @param ctx 上下文对象 管道pipeline通道channel , 地址
* @param msg 客户端发送的数据
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
@@ -76,6 +83,12 @@ public class ServerHandler extends ChannelInboundHandlerAdapter {
messageService.destory(ctx.channel());
}
/**
* 处理异常、一般需要关闭通道
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
@@ -100,12 +113,12 @@ public class ServerHandler extends ChannelInboundHandlerAdapter {
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
IdleStateEvent event = (IdleStateEvent) evt;
// 如果Channel读取数据闲置则关闭连接
// if (event.state() == IdleState.READER_IDLE) {
// String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
// logger.info("Client [" + clientIP + "] has idle");
// messageService.destory(ctx.channel());
// ctx.channel().close();
// }
if (event.state() == IdleState.READER_IDLE) {
String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
logger.info("Client [" + clientIP + "] has idle");
messageService.destory(ctx.channel());
ctx.channel().close();
}
}
}

View File

@@ -1,14 +1,13 @@
package com.sv.netty.netty;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
@@ -18,16 +17,18 @@ import org.springframework.stereotype.Component;
* @Date 09/05/2017 5:19 PM
*/
@Component
public class ServerProtocolInitalizer extends ChannelInitializer<SocketChannel> {
public class ServerProtocolInitializer extends ChannelInitializer<SocketChannel> {
private static Logger logger = LoggerFactory.getLogger(ServerProtocolInitializer.class);
private final int IDLE_TIME = 30; //连接检测空闲时间
private final int READ_TIME = 30; //读超时时间
private final int WRITE_TIME = 30; //写超时时间
private final int READ_TIMEOUT = 600; //读超时时间
@Override
protected void initChannel(SocketChannel ch) throws Exception {
protected void initChannel(SocketChannel ch){
ChannelPipeline pipeline = ch.pipeline();
logger.info("ServerProtocolInitializer");
pipeline.addFirst(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 4, 0, 0));
pipeline.addLast(new IdleStateHandler(IDLE_TIME, READ_TIME, WRITE_TIME));
pipeline.addLast(new ReadTimeoutHandler(READ_TIMEOUT));

View File

@@ -0,0 +1,13 @@
package test.netty.nio.net;
import test.netty.nio.net.client.ClientThread;
/**
* 开启一个客户端,
*/
public class ClientTest {
public static void main(String[] args) {
ClientThread instance = ClientThread.getInstance();
instance.start();
}
}

View File

@@ -0,0 +1,90 @@
package test.netty.nio.net.client;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import test.netty.nio.net.dto.HeartBeat;
import test.netty.nio.net.dto.Message;
/**
* 通讯服务器请求处理
*
* @author peakren
* @date 05/12/2017 10:27 PM
*/
@ChannelHandler.Sharable
public class ClientHandler extends ChannelInboundHandlerAdapter {
private final static String TAG = "ClientHandler";
private boolean hasRead = false;
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
super.channelRegistered(ctx);
// ClientTcpSession.getInstance().setContext(ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
//服务器连上以后立即模拟心跳返回
ctx.writeAndFlush(getHbMessage());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
// GlobalConfig.isConnected =false;
ClientThread.getInstance().clearFuture();
ClientThread.getInstance().restart();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
// Message message = JsonMapper.fromJson(msg.toString(), Message.class);
// MessageService.getInstance().execute(message);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
// GlobalConfig.isConnected = false;
ctx.close();
}
/**
* 获取心跳返回消息
*
* @return
*/
private Message getHbMessage() {
HeartBeat hb = new HeartBeat();
// hb.setVersionCode(AppUtil.getVersionCode(StartApplication.getAppContext()));
Message message = new Message();
message.setCmdId(Cmd.HB.id);
// message.setDeviceId(DeviceIdUtil.generateDeviceId(mContext));
return message;
}
/**
* 心跳处理
*
* @param ctx
* @param evt
* @throws Exception
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.ALL_IDLE) {
ctx.writeAndFlush(getHbMessage());
}
}
}
}

View File

@@ -0,0 +1,38 @@
package test.netty.nio.net.client;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
public class ClientInitializer extends ChannelInitializer<SocketChannel> {
private final static int TIME_HEART_BEAT = 20;
public ClientThread.ReConnectHandler reConnectHandler;
public ClientHandler dmClientHandler;
public ClientInitializer(ClientThread.ReConnectHandler handler) {
reConnectHandler = handler;
}
public ClientInitializer(ClientThread.ReConnectHandler handler, ClientHandler dmClientHandler) {
reConnectHandler = handler;
this.dmClientHandler = dmClientHandler;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("reconnect", reConnectHandler);
pipeline.addLast("idleStateHandler", new IdleStateHandler(TIME_HEART_BEAT, TIME_HEART_BEAT, TIME_HEART_BEAT));
pipeline.addLast(new MessageEncoder());
pipeline.addFirst(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 4, 0, 0));
pipeline.addLast(new MessageDecoder());
pipeline.addLast(dmClientHandler);
}
}

View File

@@ -0,0 +1,124 @@
package test.netty.nio.net.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
/**
* 客户端通讯
*
* @author peakren
* @date 07/12/2017 10:12 PM
*/
public class ClientThread extends Thread{
private static ClientThread instance;
private volatile EventLoopGroup workerGroup;
private volatile Bootstrap bootstrap;
private volatile boolean closed = false;
private String remoteHost;
private int remotePort;
private ChannelFuture future;
public static ClientThread getInstance() {
if (instance == null) {
synchronized (ClientThread.class) {
if (instance == null) {
instance = new ClientThread("127.0.0.1", 56791);
}
}
}
return instance;
}
private ClientThread(String remoteHost, int remotePort) {
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
public void run() {
closed = false;
workerGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(workerGroup);
bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.TCP_NODELAY, true);
bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
ReConnectHandler reConnectHandler = new ReConnectHandler();
ClientHandler dmClientHandler = new ClientHandler();
ClientInitializer channelInitializer = new ClientInitializer(reConnectHandler, dmClientHandler);
bootstrap.handler(channelInitializer);
doConnect();
}
public void clearFuture(){
future = null;
}
public void doConnect() {
System.out.println("现在开始链接了");
if (closed) {
return;
}
System.out.println("连接 = " + remoteHost + " " + remotePort);
future = bootstrap.connect(new InetSocketAddress(remoteHost, remotePort));
future.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) throws Exception {
f.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
if (!f.isSuccess()) {
doConnect();
System.out.println("等待连接");
} else {
System.out.println("已连接");
}
}
}, 2, TimeUnit.SECONDS);
}
});
}
public void close() {
closed = true;
workerGroup.shutdownGracefully();
}
public void restart() {
close();
run();
}
@ChannelHandler.Sharable
public class ReConnectHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
System.out.println("inactive");
ctx.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
doConnect();
}
}, 1, TimeUnit.SECONDS);
}
}
}

View File

@@ -0,0 +1,45 @@
package test.netty.nio.net.client;
/**
* 消息协议指令定义
*
* @Author peakren
* @Date 08/12/2017 11:51 AM
*/
public enum Cmd {
HB("hb", "心跳"),
FACEID("faceid", "人脸识别"),
FACEID_RESPONSE("faceid_response_upload", "识别结果"),
RECEV_FACE_IMAGE("recev_face_image", "接收人脸照片"),
RECEV_FACE_IMAGE_R("recev_face_image_r", "返回上传图片结果"),
OPEN_DOOR("open_door", "开门禁");
public String id;
public String text;
Cmd(String id, String text) {
this.id = id;
this.text = text;
}
public static Cmd getCmd(String id) {
for (Cmd cmd : Cmd.values()) {
if (cmd.id.equalsIgnoreCase(id)) {
return cmd;
}
}
return Cmd.HB;
}
}

View File

@@ -0,0 +1,40 @@
package test.netty.nio.net.client;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import java.nio.ByteOrder;
/**
* 自定义解码器,解决粘包和分包问题
*
* @author peakren
* @date 07/12/2017 10:03 PM
*/
public class CustomDecoder extends LengthFieldBasedFrameDecoder {
public CustomDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
}
public CustomDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip);
}
public CustomDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
}
public CustomDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
super(byteOrder, maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
}
@Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
return super.decode(ctx, in);
}
}

View File

@@ -0,0 +1,14 @@
package test.netty.nio.net.client;
/**
* Created by hehelt on 16/2/26.
*/
public class DataConfig {
public static final int MAGIC_WORD = 0x9DDD;
public static final int MAGIC_WORD_INDEX = 0;
public static final int LENGTH_INDEX = 4;
public static final int DATA_INDEX = 8;
}

View File

@@ -0,0 +1,48 @@
package test.netty.nio.net.client;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.io.UnsupportedEncodingException;
import java.util.List;
/**
* Created by hehelt on 16/2/26.
* <p/>
* 解码器
*/
public class MessageDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.capacity() >= DataConfig.LENGTH_INDEX) {
int magicWord = in.readInt();
if (magicWord == DataConfig.MAGIC_WORD) {
int length = in.readInt();
byte[] msg = new byte[length];
in.readBytes(msg);
String message = new String(msg, "utf-8");
out.add(message);
}
}
}
/**
* 解析从服务器接受的消息
*
* @param buf
* @return
*/
private String getMessage(ByteBuf buf) {
byte[] con = new byte[buf.readableBytes()];
buf.readBytes(con);
try {
return new String(con, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,24 @@
package test.netty.nio.net.client;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import test.netty.nio.net.dto.JsonMapper;
import test.netty.nio.net.dto.Message;
/**
* 自定义编码器, 1个字节固定头+4个字节长度+内容
*/
public class MessageEncoder extends MessageToByteEncoder<Message> {
private String charset = "utf-8";
private final static String TAG = "MessageEncoder";
@Override
protected void encode(ChannelHandlerContext ctx, Message message, ByteBuf out) throws Exception {
out.writeInt(DataConfig.MAGIC_WORD);
String msg = JsonMapper.toJson(message);
out.writeInt(msg.getBytes(charset).length);
out.writeBytes(msg.getBytes(charset));
}
}

View File

@@ -0,0 +1,142 @@
package test.netty.nio.net.dto;
import com.google.gson.annotations.Expose;
public class AddFaceResponse {
/**
* code : 0
* data : {"company_id":1,"id":4,"origin_url":"/static/upload/origin/2018-08-09/v2_1ea4b7847d1ea56b773aec99441af52dcbf9ca7d.jpg","quality":0.992649,"subject_id":null,"url":"/static/upload/photo/2018-08-09/v2_fa9dcfd045ff5232aa446f5645cbb031eef7ac74.jpg","version":7}
* page : {}
*/
@Expose
private int code;
@Expose
private DataBean data;
@Expose
private PageBean page;
@Expose
private String desc;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public PageBean getPage() {
return page;
}
public void setPage(PageBean page) {
this.page = page;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static class DataBean {
/**
* company_id : 1
* id : 4
* origin_url : /static/upload/origin/2018-08-09/v2_1ea4b7847d1ea56b773aec99441af52dcbf9ca7d.jpg
* quality : 0.992649
* subject_id : null
* url : /static/upload/photo/2018-08-09/v2_fa9dcfd045ff5232aa446f5645cbb031eef7ac74.jpg
* version : 7
*/
@Expose
private int company_id;
@Expose
private int id;
@Expose
private String origin_url;
@Expose
private double quality;
@Expose
private Object subject_id;
@Expose
private String url;
@Expose
private int version;
public int getCompany_id() {
return company_id;
}
public void setCompany_id(int company_id) {
this.company_id = company_id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getOrigin_url() {
return origin_url;
}
public void setOrigin_url(String origin_url) {
this.origin_url = origin_url;
}
public double getQuality() {
return quality;
}
public void setQuality(double quality) {
this.quality = quality;
}
public Object getSubject_id() {
return subject_id;
}
public void setSubject_id(Object subject_id) {
this.subject_id = subject_id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
public static class PageBean {
}
}

View File

@@ -0,0 +1,86 @@
package test.netty.nio.net.dto;
import com.google.gson.annotations.Expose;
import java.io.Serializable;
/**
* Created by peakren on 19/01/2018.
*/
public class BaseDto implements Serializable {
private static final long serialVersionUID = 3139438146199448677L;
@Expose
private String cmdId; //指令
@Expose
private String deviceId; //设备ID
/**
* 客户端IP
*/
@Expose
private String clientIp;
/**
* 状态码 0正常 1错误
*/
@Expose
private int errorCode = 0;
/**
* 错误返回信息
*/
@Expose
private String errorMsg;
public String getCmdId() {
return cmdId;
}
public void setCmdId(String cmdId) {
this.cmdId = cmdId;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
/**
* 客户端IP,获取的内网IP
*
* @return
*/
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}

View File

@@ -0,0 +1,52 @@
package test.netty.nio.net.dto;
import com.google.gson.annotations.Expose;
import java.io.Serializable;
/**
* 会员基本信息
* MemberDto.java
*
* @author peakren
* @date 2018/12/20 8:39 PM
*/
public class FaceImageDto implements Serializable {
@Expose
private Integer faceId;
@Expose
private Integer memberId;
@Expose
private String faceImage;
public Integer getFaceId() {
return faceId;
}
public void setFaceId(Integer faceId) {
this.faceId = faceId;
}
public Integer getMemberId() {
return memberId;
}
public void setMemberId(Integer memberId) {
this.memberId = memberId;
}
public String getFaceImage() {
return faceImage;
}
public void setFaceImage(String faceImage) {
this.faceImage = faceImage;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,44 @@
package test.netty.nio.net.dto;
import com.google.gson.annotations.Expose;
import java.io.Serializable;
/**
* 客户端心跳数据包
* HeartBeat.java
*
* @author peakren
* @date 07/12/2017 10:23 PM
*/
public class HeartBeat implements Serializable {
@Expose
private String versionCode; //客户端版本号
@Expose
private String apkUrl; //升级的软件下载地址
public String getVersionCode() {
return versionCode;
}
/**
* 客户端版本号
*
* @param versionCode
*/
public void setVersionCode(String versionCode) {
this.versionCode = versionCode;
}
public String getApkUrl() {
return apkUrl;
}
public void setApkUrl(String apkUrl) {
this.apkUrl = apkUrl;
}
}

View File

@@ -0,0 +1,62 @@
package test.netty.nio.net.dto;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
/**
* Created by ranfi on 12/9/14.
*/
public class JsonMapper {
private final static Gson gson;
static {
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
builder.excludeFieldsWithoutExposeAnnotation();
gson = builder.create();
}
private JsonMapper() {
}
/**
* Object可以是POJO也可以是Collection或数组。 如果对象为Null, 返回"null". 如果集合为空集合, 返回"[]".
*
* @param obj
* @return
*/
public static String toJson(Object obj) {
return gson.toJson(obj);
}
public static String toJson(Object obj, Type type) {
return gson.toJson(obj, type);
}
/**
* 反序列化POJO或简单Collection如List<String>.
* <p/>
* 如果JSON字符串为Null或"null"字符串, 返回Null. 如果JSON字符串为"[]", 返回空集合.
* <p/>
* 如需反序列化复杂Collection如List<MyBean>, 请使用fromJson(String, JavaType)
*/
public static <T> T fromJson(String jsonValue, Class<T> clazz) {
return gson.fromJson(jsonValue, clazz);
}
public static <T> T fromJson(String jsonValue, Type type) {
return gson.fromJson(jsonValue, type);
}
public static <T> List<T> fromJson(String jsonValue) {
return gson.fromJson(jsonValue, new TypeToken<List<T>>() {
}.getType());
}
}

View File

@@ -0,0 +1,148 @@
package test.netty.nio.net.dto;
import com.google.gson.annotations.Expose;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 会员基本信息
* MemberDto.java
*
* @author peakren
* @date 2018/12/20 8:39 PM
*/
public class MemberDto implements Serializable {
/**
* 头像
*/
@Expose
private String avatar;
/**
* 姓名
*/
@Expose
private String name;
/**
* 手机号码
*/
@Expose
private String mobile;
/**
* 余额
*/
@Expose
private BigDecimal amount;
/**
* 场地名称
*/
@Expose
private String placeName;
/**
* 会员卡名称
*/
@Expose
private String cardName;
@Expose
private String message;
/**
* 1成功进场 0不允许进场
*/
@Expose
private int code;
@Expose
private BigDecimal placePrice;
@Expose
private boolean first;
public BigDecimal getPlacePrice() {
return placePrice;
}
public void setPlacePrice(BigDecimal placePrice) {
this.placePrice = placePrice;
}
public boolean isFirst() {
return first;
}
public void setFirst(boolean first) {
this.first = first;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getPlaceName() {
return placeName;
}
public void setPlaceName(String placeName) {
this.placeName = placeName;
}
public String getCardName() {
return cardName;
}
public void setCardName(String cardName) {
this.cardName = cardName;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

View File

@@ -0,0 +1,68 @@
package test.netty.nio.net.dto;
import com.google.gson.annotations.Expose;
/**
* <pre>上位机与通讯服务器的数据协议格式</pre>
*
* @author peakren
* @date 07/12/2017 9:57 PM
*/
public class Message extends BaseDto {
private static final long serialVersionUID = -7944124768291562453L;
/**
* 消息内容
*/
@Expose
private MemberDto result;
@Expose
private FaceImageDto faceImage;
/**
* 机器识别返回字符串
*/
@Expose
private String content;
public int getDoor() {
return door;
}
public void setDoor(int door) {
this.door = door;
}
@Expose
private int door;
public MemberDto getResult() {
return result;
}
public void setResult(MemberDto result) {
this.result = result;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public FaceImageDto getFaceImage() {
return faceImage;
}
public void setFaceImage(FaceImageDto faceImage) {
this.faceImage = faceImage;
}
}