From e6bc99430fe49882a81626584f403805f3186e00 Mon Sep 17 00:00:00 2001 From: limqhz Date: Wed, 24 Feb 2021 11:33:45 +0800 Subject: [PATCH] add old netty frameWork --- README.md | 2 +- api/build.gradle | 2 +- build.gradle | 2 +- entity/build.gradle | 4 +- .../src/main/java/com/sv/dto/EnterResult.java | 24 + netty-pad/build.gradle | 49 ++ .../src/main/java/com/NettyApplication.java | 73 ++ .../com/sv/netty/config/ChannelTypeCache.java | 63 ++ .../java/com/sv/netty/config/Constant.java | 33 + .../sv/netty/config/SpringContextHolder.java | 72 ++ .../sv/netty/controller/MessageControler.java | 44 ++ .../main/java/com/sv/netty/netty/BaseDto.java | 93 +++ .../java/com/sv/netty/netty/BootService.java | 134 ++++ .../java/com/sv/netty/netty/ChannelParam.java | 88 +++ .../com/sv/netty/netty/ClientHandler.java | 85 +++ .../src/main/java/com/sv/netty/netty/Cmd.java | 39 ++ .../java/com/sv/netty/netty/MemberDto.java | 148 ++++ .../com/sv/netty/netty/MessageDecoder.java | 43 ++ .../java/com/sv/netty/netty/MessageDto.java | 24 + .../com/sv/netty/netty/MessageEncoder.java | 66 ++ .../java/com/sv/netty/netty/ResponseDTO.java | 60 ++ .../main/java/com/sv/netty/netty/Result.java | 39 ++ .../com/sv/netty/netty/ServerHandler.java | 133 ++++ .../netty/ServerProtocolInitializer.java | 43 ++ .../com/sv/netty/service/MessageService.java | 35 + .../impl/TcpMessageHandlerAdapter.java | 324 +++++++++ .../java/com/sv/netty/utils/CommonUtils.java | 76 +++ .../java/com/sv/netty/utils/EncodeUtils.java | 77 +++ .../java/com/sv/netty/utils/JsonMapper.java | 204 ++++++ .../java/com/sv/netty/utils/JsonUtils.java | 94 +++ .../java/com/sv/netty/utils/LiveTime.java | 28 + .../main/resources/config/application-dev.yml | 16 + .../resources/config/application-prod.yml | 17 + .../src/main/resources/config/application.yml | 104 +++ netty-pad/src/main/resources/logback.xml | 46 ++ .../main/resources/mybatis/mybatis-config.xml | 41 ++ .../java/test/netty/nio/net/ClientTest.java | 13 + .../netty/nio/net/client/ClientHandler.java | 90 +++ .../nio/net/client/ClientInitializer.java | 38 ++ .../netty/nio/net/client/ClientThread.java | 124 ++++ .../java/test/netty/nio/net/client/Cmd.java | 45 ++ .../netty/nio/net/client/CustomDecoder.java | 40 ++ .../test/netty/nio/net/client/DataConfig.java | 14 + .../netty/nio/net/client/MessageDecoder.java | 48 ++ .../netty/nio/net/client/MessageEncoder.java | 24 + .../netty/nio/net/dto/AddFaceResponse.java | 142 ++++ .../java/test/netty/nio/net/dto/BaseDto.java | 86 +++ .../test/netty/nio/net/dto/FaceImageDto.java | 52 ++ .../nio/net/dto/FaceRecognizeResponse.java | 639 ++++++++++++++++++ .../test/netty/nio/net/dto/HeartBeat.java | 44 ++ .../test/netty/nio/net/dto/JsonMapper.java | 62 ++ .../test/netty/nio/net/dto/MemberDto.java | 148 ++++ .../java/test/netty/nio/net/dto/Message.java | 68 ++ oms/build.gradle | 2 +- service/build.gradle | 2 +- .../java/com/sv/service/api/VenueService.java | 191 +++--- settings.gradle | 5 +- 57 files changed, 4198 insertions(+), 104 deletions(-) create mode 100644 entity/src/main/java/com/sv/dto/EnterResult.java create mode 100644 netty-pad/build.gradle create mode 100644 netty-pad/src/main/java/com/NettyApplication.java create mode 100644 netty-pad/src/main/java/com/sv/netty/config/ChannelTypeCache.java create mode 100644 netty-pad/src/main/java/com/sv/netty/config/Constant.java create mode 100644 netty-pad/src/main/java/com/sv/netty/config/SpringContextHolder.java create mode 100644 netty-pad/src/main/java/com/sv/netty/controller/MessageControler.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/BaseDto.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/BootService.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/ChannelParam.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/ClientHandler.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/Cmd.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/MemberDto.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/MessageDecoder.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/MessageDto.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/MessageEncoder.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/ResponseDTO.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/Result.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/ServerHandler.java create mode 100644 netty-pad/src/main/java/com/sv/netty/netty/ServerProtocolInitializer.java create mode 100644 netty-pad/src/main/java/com/sv/netty/service/MessageService.java create mode 100644 netty-pad/src/main/java/com/sv/netty/service/impl/TcpMessageHandlerAdapter.java create mode 100644 netty-pad/src/main/java/com/sv/netty/utils/CommonUtils.java create mode 100644 netty-pad/src/main/java/com/sv/netty/utils/EncodeUtils.java create mode 100644 netty-pad/src/main/java/com/sv/netty/utils/JsonMapper.java create mode 100644 netty-pad/src/main/java/com/sv/netty/utils/JsonUtils.java create mode 100644 netty-pad/src/main/java/com/sv/netty/utils/LiveTime.java create mode 100644 netty-pad/src/main/resources/config/application-dev.yml create mode 100644 netty-pad/src/main/resources/config/application-prod.yml create mode 100644 netty-pad/src/main/resources/config/application.yml create mode 100644 netty-pad/src/main/resources/logback.xml create mode 100644 netty-pad/src/main/resources/mybatis/mybatis-config.xml create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/ClientTest.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/ClientHandler.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/ClientInitializer.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/ClientThread.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/Cmd.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/CustomDecoder.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/DataConfig.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/MessageDecoder.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/client/MessageEncoder.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/AddFaceResponse.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/BaseDto.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceImageDto.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceRecognizeResponse.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/HeartBeat.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/JsonMapper.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/MemberDto.java create mode 100644 netty-pad/src/main/test/java/test/netty/nio/net/dto/Message.java diff --git a/README.md b/README.md index 85156ac..14a2e5e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# SmartVenue +# smartvenue This is a smart venue solution. diff --git a/api/build.gradle b/api/build.gradle index 531d2a3..167b402 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -12,7 +12,7 @@ buildscript { } } -group 'SmartVenue' +group 'smartvenue' version '2.0.0' apply plugin: 'java' diff --git a/build.gradle b/build.gradle index 6a872d5..fe59980 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -group 'SmartVenue' +group 'smartvenue' version '1.0-SNAPSHOT' apply plugin: 'java' diff --git a/entity/build.gradle b/entity/build.gradle index 4185fe6..741a2a6 100644 --- a/entity/build.gradle +++ b/entity/build.gradle @@ -1,4 +1,4 @@ -group 'SmartVenue' +group 'smartvenue' version '1.0-SNAPSHOT' ext { springBootVersion = '1.5.7.RELEASE' @@ -84,4 +84,4 @@ buildscript { dependencies { classpath("gradle.plugin.com.arenagod.gradle:mybatis-generator-plugin:1.4") } -} \ No newline at end of file +} diff --git a/entity/src/main/java/com/sv/dto/EnterResult.java b/entity/src/main/java/com/sv/dto/EnterResult.java new file mode 100644 index 0000000..a4ee37e --- /dev/null +++ b/entity/src/main/java/com/sv/dto/EnterResult.java @@ -0,0 +1,24 @@ +package com.sv.dto; + +import java.math.BigDecimal; + +public class EnterResult { + private Integer status; + private BigDecimal money; + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public BigDecimal getMoney() { + return money; + } + + public void setMoney(BigDecimal money) { + this.money = money; + } +} diff --git a/netty-pad/build.gradle b/netty-pad/build.gradle new file mode 100644 index 0000000..a24047a --- /dev/null +++ b/netty-pad/build.gradle @@ -0,0 +1,49 @@ +buildscript { + ext { + springBootVersion = '1.5.6.RELEASE' + } + repositories { + maven { + url 'http://maven.aliyun.com/nexus/content/groups/public/' + } + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") + } +} +apply plugin: 'java' +apply plugin: 'org.springframework.boot' + +group 'smartvenue' +version '1.0-SNAPSHOT' + +sourceCompatibility = 1.8 + + +repositories { +// maven {url 'http://maven.ydd100.cn/repository/maven-public/'} + //mavenCentral() + maven { + url 'http://maven.aliyun.com/nexus/content/groups/public/' + } +} +ext { + version = '1.0' + springBootVersion = '1.5.4.RELEASE' + nettyVersion = '4.1.10.Final' + junitVersion = "4.11" + jacksonVersion = "2.5.0" +} + + +[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8' + +dependencies { + compile fileTree(include: '*.jar', dir: 'src/libs') + compile project(':service') + + compile "io.netty:netty-all:${nettyVersion}" + compile 'mysql:mysql-connector-java:6.0.6' + + +} diff --git a/netty-pad/src/main/java/com/NettyApplication.java b/netty-pad/src/main/java/com/NettyApplication.java new file mode 100644 index 0000000..5d80165 --- /dev/null +++ b/netty-pad/src/main/java/com/NettyApplication.java @@ -0,0 +1,73 @@ +package com; + +import com.sv.netty.config.SpringContextHolder; +import com.sv.netty.netty.BootService; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.mybatis.spring.annotation.MapperScan; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + +@SpringBootApplication +@EnableScheduling +@EnableAsync +@MapperScan(value = {"com.sv.mapper"}) +public class NettyApplication { + + private static Logger logger = LoggerFactory.getLogger(NettyApplication.class); + + public static void main(String[] args) { + logger.debug("应用启动成功..."); + ConfigurableApplicationContext context = SpringApplication.run(NettyApplication.class, args); + SpringContextHolder.setContext(context); + //启动netty + BootService bootService = (BootService) context.getBean("bootService"); + bootService.run(); + + //启动任务队列,处理 +// QueueTaskQueueDaemonThread queueTaskQueueDaemonThread = (QueueTaskQueueDaemonThread) context.getBean("queueTaskQueueDaemonThread"); +// queueTaskQueueDaemonThread.init(); + } + + private int corePoolSize = 5;//线程池维护线程的最少数量 + + private int maxPoolSize = 15;//线程池维护线程的最大数量 + + private int queueCapacity = 5; //缓存队列 + + private int keepAlive = 60;//允许的空闲时间 + + + @Bean("scheduledExecutorService") + public ScheduledExecutorService initScheduledExecutorService() { + ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(400, + new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build()); + return executorService; + } + + @Bean + public Executor executor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(corePoolSize); + executor.setMaxPoolSize(maxPoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setThreadNamePrefix("mqExecutor-"); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy()); + executor.setKeepAliveSeconds(keepAlive); + executor.initialize(); + return executor; + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/config/ChannelTypeCache.java b/netty-pad/src/main/java/com/sv/netty/config/ChannelTypeCache.java new file mode 100644 index 0000000..1637d7f --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/config/ChannelTypeCache.java @@ -0,0 +1,63 @@ +package com.sv.netty.config; + +import io.netty.util.internal.PlatformDependent; + +import java.util.concurrent.ConcurrentMap; + +/** + * 通道类型全局存储 + * + * @author Demon + * @since 09/01/2018 + */ +public class ChannelTypeCache { + + public static final Integer TCP = 1; + + public static final Integer WEB_SOCKET = 2; + + /** + * 存储用户和通道类型 + * value: 1Tcp 2WebSocket + */ + public static final ConcurrentMap channelTypes = PlatformDependent.newConcurrentHashMap(); + + /** + * 设置通道类型 + * + * @param memberId 会员编号 + * @param channelType 通道类型:1Tcp 2WebSocket + */ + public static void putChannelType(Integer memberId, Integer channelType) { + channelTypes.put(memberId, channelType); + } + + /** + * 获取通道类型 + * + * @param memberId 会员编号 + * @return 通道类型:1Tcp 2WebSocket + */ + public static Integer getChannelType(Integer memberId) { + return channelTypes.get(memberId); + } + + /** + * 判断是否存在用户 + * + * @param memberId 会员编号 + * @return 是否存在用户 + */ + public static boolean contains(Integer memberId) { + return channelTypes.containsKey(memberId); + } + + /** + * 删除通道类型 + * + * @param memberId 会员编号 + */ + public static void removeChannelType(Integer memberId) { + channelTypes.remove(memberId); + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/config/Constant.java b/netty-pad/src/main/java/com/sv/netty/config/Constant.java new file mode 100644 index 0000000..19e7612 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/config/Constant.java @@ -0,0 +1,33 @@ +package com.sv.netty.config; + +import com.sv.netty.netty.ChannelParam; +import io.netty.util.AttributeKey; + +/** + * Created by ranfi on 2/22/16. + */ +public class Constant { + + public static final String ACCESS_TOKEN_KEY = "access_token_key"; + + //消息队列发送消息到netty + public static final String sendToMachine = "netty-doll-machine"; + + //消息队列发送消息到netty + public static final String sendToService = "netty-doll-service"; + + //消息队列发送消息到netty + public static final String ROOM_SERVICE_TOPIC = "gt-room-service-topic"; + + /** + * session中存储终端发送的额外参数 + */ + public static AttributeKey CHANNEL_PARAM = AttributeKey.newInstance("CHANNEL_PARAM"); + + /** + * 每局结束后的保护时间 + */ + public static final Integer GAME_OVER_PROTECTION_SECONDS = 5; + + +} diff --git a/netty-pad/src/main/java/com/sv/netty/config/SpringContextHolder.java b/netty-pad/src/main/java/com/sv/netty/config/SpringContextHolder.java new file mode 100644 index 0000000..51833c0 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/config/SpringContextHolder.java @@ -0,0 +1,72 @@ +/** + * Description: + * SpringContextHolder.java Create on 2013-3-8 上午10:19:20 + * @author xiaopin + * @version 1.0 + * Copyright (c) 2013 BMS,Inc. All Rights Reserved. + */ +package com.sv.netty.config; + +import org.springframework.context.ApplicationContext; + +/** + * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext. + * + * @author calvin + */ +public class SpringContextHolder { + + private static ApplicationContext applicationContext; + + /** + * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量. + */ + public void setApplicationContext(ApplicationContext applicationContext) { + SpringContextHolder.applicationContext = applicationContext; // NOSONAR + } + + + /** + * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量. + */ + public static void setContext(ApplicationContext applicationContext) { + SpringContextHolder.applicationContext = applicationContext; // NOSONAR + } + /** + * 取得存储在静态变量中的ApplicationContext. + */ + public static ApplicationContext getApplicationContext() { + checkApplicationContext(); + return applicationContext; + } + + /** + * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋于对象的类 + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { + checkApplicationContext(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋对象的类 如果有多个Bean符合Class, 取出第一个 + */ + public static T getBean(Class requiredType) { + checkApplicationContext(); + return SpringContextHolder.applicationContext.getBean(requiredType); + } + + /** + * 清除applicationContext静态变量. + */ + public static void cleanApplicationContext() { + applicationContext = null; + } + + private static void checkApplicationContext() { + if (SpringContextHolder.applicationContext == null) { + throw new IllegalStateException("applicaitonContext未注册请在applicationContext.xml中定义SpringContextHolder"); + } + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/controller/MessageControler.java b/netty-pad/src/main/java/com/sv/netty/controller/MessageControler.java new file mode 100644 index 0000000..189f98c --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/controller/MessageControler.java @@ -0,0 +1,44 @@ +package com.sv.netty.controller; + +import com.sv.entity.face.FaceRecognizeResponse; +import com.sv.netty.netty.MemberDto; +import com.sv.netty.netty.ResponseDTO; +import com.sv.netty.service.MessageService; +import com.sv.netty.service.impl.TcpMessageHandlerAdapter; +import com.sv.service.oms.DeviceService; +import com.sv.service.oms.VenueService; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +@RestController +public class MessageControler { + + @Resource() + private TcpMessageHandlerAdapter messageService; + + @Resource + private DeviceService deviceService; + + @Resource + private VenueService venueService; + + @RequestMapping("/message/send/t") + public ResponseDTO sendMessage1() { + FaceRecognizeResponse recognizeResponse = new FaceRecognizeResponse(); + recognizeResponse.setPerson(new FaceRecognizeResponse.PersonBeanX()); + recognizeResponse.getPerson().setId(49); + messageService.enter(deviceService.findById(1), recognizeResponse, venueService.findById(32)); + return ResponseDTO.ok(); + } + +// +// @RequestMapping("/upload/image") +// public ResponseDTO sendMessage(){ +// messageService.sendMessage(memberDto); +// return ResponseDTO.ok(); +// } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/BaseDto.java b/netty-pad/src/main/java/com/sv/netty/netty/BaseDto.java new file mode 100644 index 0000000..d5f3ec8 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/BaseDto.java @@ -0,0 +1,93 @@ +package com.sv.netty.netty; + + +import com.sv.entity.Device; + +import java.io.Serializable; + +/** + * Created by peakren on 19/01/2018. + */ + +public class BaseDto implements Serializable { + + private static final long serialVersionUID = 3139438146199448677L; + + + private String cmdId; //指令 + + private String deviceId; //设备ID + + /** + * 客户端IP + */ + private String clientIp; + + private String content; + + /** + * 状态码 0正常 1错误 + */ + + private int errorCode = 0; + + /** + * 错误返回信息 + */ + + 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; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/BootService.java b/netty-pad/src/main/java/com/sv/netty/netty/BootService.java new file mode 100644 index 0000000..234827e --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/BootService.java @@ -0,0 +1,134 @@ +package com.sv.netty.netty; + +import com.google.common.collect.Maps; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.net.InetSocketAddress; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +/** + * netty启动服务 + * + * @Author peakren + * @Date 03/05/2017 6:18 PM + */ +@Component +public class BootService { + + private Logger logger = LoggerFactory.getLogger(BootService.class); + + private volatile EventLoopGroup workerGroup; + private volatile EventLoopGroup bossGroup; + private volatile ServerBootstrap bootstrap; + private ChannelFuture serverChannelFuture; + + /** + * 启动netty的控制线程 + */ + private Executor messageExecutor; + + /** + * 下面几个是由spring注入 + */ + @Value("${netty.port}") + private int port; + + @Value("${so.keepalive}") + private Boolean keepalive; + + @Value("${so.backlog}") + private int backlog; + + @Value("${tcp_nodelay}") + private boolean nodelay; + + @Value("${so.reuseaddr}") + private boolean reuseaddr; + + @Value("${boss.thread.count}") + private int bossCount; + + @Value("${worker.thread.count}") + private int workerCount; + + private Map channelOptions; + + private final ServerProtocolInitializer serverProtocolInitializer; + + /** + * 初始化netty启动配置 + */ + public void init() { + // bossGroup 只处理连接请求,真正的客户端业务处理是由workerGroup 处理的 都是无效循环的 + workerGroup = new NioEventLoopGroup(); + bossGroup = new NioEventLoopGroup(); + channelOptions = Maps.newHashMap(); + try { +// channelOptions.put(ChannelOption.SO_KEEPALIVE,keepalive); + channelOptions.put(ChannelOption.SO_BACKLOG,backlog); +// channelOptions.put(ChannelOption.TCP_NODELAY,TCP_NODELAY); + channelOptions.put(ChannelOption.SO_REUSEADDR,reuseaddr); + bootstrap = new ServerBootstrap(); + bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 设置服务器的通道是NIOServerSocketChannel + .childHandler(serverProtocolInitializer); + for (Map.Entry 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(); + // serverChannelFuture的用处 + serverChannelFuture.addListener(f -> { + if (f.isSuccess()){ + logger.info("成功bind端口:" + port); + } + }); + // 对关闭通道进行监听 (异步模型) + serverChannelFuture.channel().closeFuture().sync(); + } catch (InterruptedException e) { + logger.error("启动NETTY TCP异常:", e); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + /** + * 开启单独的线程运行netty服务,避免和spring mvc冲突 + */ + public void run() { +// messageExecutor = Executors.newFixedThreadPool(1); + messageExecutor = Executors.newSingleThreadExecutor(); + messageExecutor.execute(() -> init()); + } + + public void destroy() throws Exception { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + serverChannelFuture.channel().closeFuture().sync(); + } + + public void setPort(int port) { + this.port = port; + } + + public void setChannelOptions(Map channelOptions) { + this.channelOptions = channelOptions; + } + + public BootService(ServerProtocolInitializer serverProtocolInitializer) { + this.serverProtocolInitializer = serverProtocolInitializer; + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/ChannelParam.java b/netty-pad/src/main/java/com/sv/netty/netty/ChannelParam.java new file mode 100644 index 0000000..00e4f28 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/ChannelParam.java @@ -0,0 +1,88 @@ +package com.sv.netty.netty; + +/** + * 会话中存储的对象 + * + * @author peakren + * @since 16/05/2017 11:09 PM + */ +public class ChannelParam { + + /** + * 设备ip + */ + private String clientIp; + + /** + * 设备编号 + */ + private String deviceSn; + + /** + * 会员编号 + */ + private Integer memberId; + + /** + * 昵称 + */ + private String nickname; + + /** + * 头像 + */ + private String avatar; + + public ChannelParam() { + + } + + public ChannelParam(String clientIp){ + this.clientIp = clientIp; + } + + public ChannelParam(String clientIp, String deviceSn) { + this.clientIp = clientIp; + this.deviceSn = deviceSn; + } + + public String getClientIp() { + return clientIp; + } + + public void setClientIp(String clientIp) { + this.clientIp = clientIp; + } + + public String getDeviceSn() { + return deviceSn; + } + + public void setDeviceSn(String deviceSn) { + this.deviceSn = deviceSn; + } + + public Integer getMemberId() { + return memberId; + } + + public void setMemberId(Integer memberId) { + this.memberId = memberId; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/ClientHandler.java b/netty-pad/src/main/java/com/sv/netty/netty/ClientHandler.java new file mode 100644 index 0000000..9ba542a --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/ClientHandler.java @@ -0,0 +1,85 @@ +package com.sv.netty.netty; + +import com.sv.netty.utils.JsonMapper; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 客户端处理器 + * + * @author ranfi + */ +public class ClientHandler extends ChannelInboundHandlerAdapter { + + private static Logger logger = LoggerFactory.getLogger(ClientHandler.class); + + private static final String MESSAGE = "Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients."; + + public ClientHandler() { + } + + /** + * 当通道就绪就会触发 + * @param ctx + * @throws Exception + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + super.channelActive(ctx); + } + + /** + * 当通道失效就会触发 + * @param ctx + * @throws Exception + */ + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + } + + /** + * 当通道有读取事件时触发 + * @param ctx + * @param msg + * @throws Exception + */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + super.channelRead(ctx, msg); + logger.info("接收服务器响应msg:[" + msg + "]"); + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) + throws Exception { + super.userEventTriggered(ctx, evt); + IdleStateEvent event = (IdleStateEvent) evt; + // 如果IoSession闲置,则关闭连接 + if (event.state() == IdleState.READER_IDLE) { + String json = JsonMapper.nonDefaultMapper().toJson(null); + ctx.writeAndFlush(json); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) + throws Exception { + super.exceptionCaught(ctx, cause); + logger.error("ClientHandler exceptionCaught",cause); + Channel channel = ctx.channel(); + if(channel.isActive()) { + ctx.close(); + } + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/Cmd.java b/netty-pad/src/main/java/com/sv/netty/netty/Cmd.java new file mode 100644 index 0000000..181c42b --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/Cmd.java @@ -0,0 +1,39 @@ +package com.sv.netty.netty; + +/** + * 消息协议指令定义 + * + * @Author peakren + * @Date 08/12/2017 11:51 AM + */ +public enum Cmd { + + + HB("hb", "心跳"), + + FACEID("faceid", "人脸识别"), + OPEN_DOOR("open_door", "开门"), + + FACEID_RESPONSE("faceid_response_upload", "人脸结果"); + + 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; + } + +} + diff --git a/netty-pad/src/main/java/com/sv/netty/netty/MemberDto.java b/netty-pad/src/main/java/com/sv/netty/netty/MemberDto.java new file mode 100644 index 0000000..726e266 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/MemberDto.java @@ -0,0 +1,148 @@ +package com.sv.netty.netty; + + +import java.io.Serializable; +import java.math.BigDecimal; + + +/** + * 会员基本信息 + * MemberDto.java + * + * @author peakren + * @date 2018/12/20 8:39 PM + */ +public class MemberDto implements Serializable { + + /** + * 头像 + */ + + private String avatar; + + /** + * 姓名 + */ + + private String name; + + /** + * 手机号码 + */ + + private String mobile; + + /** + * 余额 + */ + + private BigDecimal amount; + + /** + * 是否第一次进入 + */ + private boolean first = false; + + /** + * 场地价格 + */ + private BigDecimal placePrice; + /** + * 场地名称 + */ + + private String placeName; + + /** + * 会员卡名称 + */ + + private String cardName; + + private String message; + + /** + * 1成功进场 0不允许进场 + */ + private int code; + + 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; + } + + 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; + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/MessageDecoder.java b/netty-pad/src/main/java/com/sv/netty/netty/MessageDecoder.java new file mode 100644 index 0000000..783c5ec --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/MessageDecoder.java @@ -0,0 +1,43 @@ +package com.sv.netty.netty; + +import com.sv.netty.utils.EncodeUtils; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + + +/** + * TCP消息解码器 + * + * @Author peakren + * @Date 08/05/2017 10:34 PM + */ +public class MessageDecoder extends ByteToMessageDecoder { + + private final static int MESSAGE_LENGTH = 4; + private final static int MESSAGE_SEQNO = 4; + private final static int MESSAGE_HEAD = 8; + private final static int MESSAGE_MAX_LENGTH = 12; + private final static int MAGIC_WORD = 0x9DDD; //码头 + + private static Logger logger = LoggerFactory.getLogger(MessageDecoder.class); + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + if (in.capacity() >= MESSAGE_MAX_LENGTH) { + int magicWord = in.readInt(); + if (magicWord == MAGIC_WORD) { + int length = in.readInt(); + byte[] msg = new byte[length]; + in.readBytes(msg); + String message = new String(msg, "utf-8"); + out.add(message); + } + } + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/MessageDto.java b/netty-pad/src/main/java/com/sv/netty/netty/MessageDto.java new file mode 100644 index 0000000..3bfef09 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/MessageDto.java @@ -0,0 +1,24 @@ +package com.sv.netty.netty; + +public class MessageDto extends BaseDto { + + + private Object result; + private Integer door; + + public Object getResult() { + return result; + } + + public void setResult(Object result) { + this.result = result; + } + + public Integer getDoor() { + return door; + } + + public void setDoor(Integer door) { + this.door = door; + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/MessageEncoder.java b/netty-pad/src/main/java/com/sv/netty/netty/MessageEncoder.java new file mode 100644 index 0000000..6026563 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/MessageEncoder.java @@ -0,0 +1,66 @@ +package com.sv.netty.netty; + +import com.sv.netty.utils.CommonUtils; +import com.sv.netty.utils.JsonUtils; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.Charset; + + +/** + * 自定义消息编码器 + * + * @Author peakren + * @Date 07/05/2017 10:43 PM + */ +public class MessageEncoder extends MessageToByteEncoder { + + private final static int MESSAGE_LENGTH = 4; + private final static int MESSAGE_SEQNO = 8; + private final static int MESSAGE_HEAD = 4; + private final static String mSeqno = "doll"; + private final static int MAGIC_WORD = 0x9DDD; + + private static Logger logger = LoggerFactory.getLogger(MessageEncoder.class); + + Charset charset = Charset.forName("UTF-8"); + + @Override + protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception { + String message = JsonUtils.encode(msg); + logger.info("send message content:" + message); + byte[] bodys = message.getBytes(charset.name()); + + int len = bodys.length; + out.writeInt(MAGIC_WORD); //发送预留数据字节码 + out.writeInt(len); //发送head字节码 + out.writeBytes(bodys); //发送消息内容 + } + + byte[] getIntBytes(int crc) { + byte[] targets = new byte[4]; + targets[0] = (byte) (crc & 0xff); + targets[1] = (byte) ((crc >> 8) & 0xff); + targets[2] = (byte) ((crc >> 16) & 0xff); + targets[3] = (byte) (crc >> 24); + return targets; + } + + byte[] getLongBytes(long crc) { + byte[] targets = new byte[8]; + targets[0] = (byte) (crc & 0xff); + targets[1] = (byte) ((crc >> 8) & 0xff); + targets[2] = (byte) ((crc >> 16) & 0xff); + targets[3] = (byte) (crc >> 24 & 0xff); + targets[4] = (byte) (crc >> 32 & 0xff); + targets[5] = (byte) (crc >> 40 & 0xff); + targets[6] = (byte) (crc >> 48 & 0xff); + targets[7] = (byte) (crc >> 56); + return targets; + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/ResponseDTO.java b/netty-pad/src/main/java/com/sv/netty/netty/ResponseDTO.java new file mode 100644 index 0000000..7f4b6fb --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/ResponseDTO.java @@ -0,0 +1,60 @@ +package com.sv.netty.netty; + + +import org.springframework.util.Assert; + +import java.util.LinkedHashMap; + +public class ResponseDTO extends LinkedHashMap { + public static final String ERR_CODE = "err_code"; + public static final String ERR_MSG = "err_msg"; + public static final String TIMESTAMP = "timestamp"; + private static final long serialVersionUID = 8410965932046471023L; + + public ResponseDTO() { + this(0, "OK"); + } + + public ResponseDTO(Integer errCode, String errMsg) { + this(errCode, errMsg, System.currentTimeMillis() / 1000L); + } + + public ResponseDTO(Integer errCode, String errMsg, Long timestamp) { + this.addAttribute("err_code", errCode); + this.addAttribute("err_msg", errMsg); + this.addAttribute("timestamp", timestamp); + } + + + + public ResponseDTO(Integer errCode, String errMsg, String attrName, Object attrValue) { + this(errCode, errMsg); + this.addAttribute(attrName, attrValue); + } + + public static ResponseDTO ok() { + return new ResponseDTO(); + } + + public static ResponseDTO ok(String msg) { + ResponseDTO ret = ok(); + ret.setErrorMsg(msg); + return ret; + } + + public ResponseDTO addAttribute(String attrName, Object attrValue) { + Assert.notNull(attrName, "属性名称不能为空"); + this.put(attrName, attrValue); + return this; + } + + + + public void setErrorCode(Integer errCode) { + this.addAttribute("err_code", errCode); + } + + public void setErrorMsg(String errMsg) { + this.addAttribute("err_msg", errMsg); + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/Result.java b/netty-pad/src/main/java/com/sv/netty/netty/Result.java new file mode 100644 index 0000000..cd38461 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/Result.java @@ -0,0 +1,39 @@ +package com.sv.netty.netty; + +public class Result { + + + /** + * Code : 0 + * Message : success + * Data : false + */ + + private int Code; + private String Message; + private boolean Data; + + public int getCode() { + return Code; + } + + public void setCode(int Code) { + this.Code = Code; + } + + public String getMessage() { + return Message; + } + + public void setMessage(String Message) { + this.Message = Message; + } + + public boolean isData() { + return Data; + } + + public void setData(boolean Data) { + this.Data = Data; + } +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/ServerHandler.java b/netty-pad/src/main/java/com/sv/netty/netty/ServerHandler.java new file mode 100644 index 0000000..10c599f --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/ServerHandler.java @@ -0,0 +1,133 @@ +package com.sv.netty.netty; + +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; + +import java.net.InetSocketAddress; + +/** + * 服务器接受TCP协议数据处理器 + * + * @author ranfi + */ + +@ChannelHandler.Sharable +public class ServerHandler extends ChannelInboundHandlerAdapter { + + private static Logger logger = LoggerFactory.getLogger(ServerHandler.class); + + private MessageService messageService; + + public ServerHandler() { + messageService = SpringContextHolder.getBean("messageService"); + } + + /** + * 通道就绪事件 + * @param ctx + * @throws Exception + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + 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); + //taskQueue +// ctx.channel().eventLoop().execute() + //scheduleTaskQueue +// ctx.channel().eventLoop().schedule() + String clientIp = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getClientIp(); + try { + messageService.receive(ctx.channel(), msg.toString()); + } catch (Exception e) { + logger.error("[" + clientIp + "] host unknown error"); + } + } + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress(); + logger.info("There is a client Registered. ip:" + clientIP); + ctx.channel().attr(Constant.CHANNEL_PARAM).set(new ChannelParam(clientIP)); + messageService.online(ctx.channel()); + } + + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + super.channelUnregistered(ctx); + } + + /** + * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward + * to the next {@link ChannelHandler} in the {@link ChannelPipeline}. + *

+ * Sub-classes may override this method to change behavior. + * + * @param ctx + */ + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress(); + logger.error("Client ip [" + clientIP + "] has inactive"); + Integer memberId = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getMemberId(); + String nickname = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getNickname(); + String machineSn = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getDeviceSn(); + messageService.doOffLine(memberId, nickname,machineSn); + messageService.destory(ctx.channel()); + } + + /** + * 处理异常、一般需要关闭通道 + * @param ctx + * @param cause + * @throws Exception + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) + throws Exception { + super.exceptionCaught(ctx, cause); + logger.error("ServerHandler exceptionCaught",cause); + Channel channel = ctx.channel(); + if(channel.isActive()) { + ctx.close(); + } + } + + /** + * Calls {@link ChannelHandlerContext#fireUserEventTriggered(Object)} to forward + * to the next {@link ChannelHandler} in the {@link ChannelPipeline}. + *

+ * Sub-classes may override this method to change behavior. + * + * @param ctx + * @param evt + */ + @Override + 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(); + } + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/netty/ServerProtocolInitializer.java b/netty-pad/src/main/java/com/sv/netty/netty/ServerProtocolInitializer.java new file mode 100644 index 0000000..157d6c3 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/netty/ServerProtocolInitializer.java @@ -0,0 +1,43 @@ +package com.sv.netty.netty; + +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; +import io.netty.handler.timeout.ReadTimeoutHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * 服务器端协议初始化适配器 + * + * @Author peakren + * @Date 09/05/2017 5:19 PM + */ +@Component +public class ServerProtocolInitializer extends ChannelInitializer { + + 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){ + ChannelPipeline pipeline = ch.pipeline(); + logger.info("ServerProtocolInitializer"); + // 通过指定的长度来标识整包的信息,这样就可以自动的处理粘包和半包的问题 + pipeline.addFirst(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 4, 0, 0)); + pipeline.addLast(new ReadTimeoutHandler(READ_TIMEOUT)); + pipeline.addLast(new MessageDecoder()); + pipeline.addLast(new MessageEncoder()); + // 心跳检测机制,通过调用触发下一个handler userEventTriggered 方法 + pipeline.addLast(new IdleStateHandler(READ_TIME, WRITE_TIME,IDLE_TIME)); + pipeline.addLast(new ServerHandler()); + + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/service/MessageService.java b/netty-pad/src/main/java/com/sv/netty/service/MessageService.java new file mode 100644 index 0000000..c88ccf2 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/service/MessageService.java @@ -0,0 +1,35 @@ +package com.sv.netty.service; + +import com.sv.netty.netty.MemberDto; +import io.netty.channel.Channel; + +/** + * 消息实现接口 + * + * @author peakren + * @since 03/05/2017 10:04 PM + */ +public interface MessageService { + + /** + * 接受设备消息 + * + * @param channel + * @param content + */ + void receive(Channel channel, String content); + + void online(Channel channel); + + /** + * 销毁设备的连接 + * + * @param channel + */ + void destory(Channel channel); + + + void doOffLine(Integer memberId, String nickname, String machineSn); + + void sendMessage(MemberDto memberDto); +} diff --git a/netty-pad/src/main/java/com/sv/netty/service/impl/TcpMessageHandlerAdapter.java b/netty-pad/src/main/java/com/sv/netty/service/impl/TcpMessageHandlerAdapter.java new file mode 100644 index 0000000..ffbc658 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/service/impl/TcpMessageHandlerAdapter.java @@ -0,0 +1,324 @@ +package com.sv.netty.service.impl; + +import com.enums.FaceRecognizeEnum; +import com.sv.dto.EnterResult; +import com.sv.entity.Device; +import com.sv.entity.Member; +import com.sv.entity.MemberEnterVenueLog; +import com.sv.entity.Venue; +import com.sv.entity.face.FaceRecognizeResponse; +import com.sv.netty.netty.*; +import com.sv.netty.service.MessageService; +import com.sv.netty.utils.JsonMapper; +import com.sv.service.api.MemberEnterVenueLogService; +import com.sv.service.api.MemberService; +import com.sv.service.api.VenueService; +import com.sv.service.oms.ConfigService; +import com.sv.service.oms.DeviceService; +import com.ydd.oms.entity.sys.Config; +import io.netty.channel.Channel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + + +/** + * 消息实现类 + * + * @Author peakren + * @Date 08/05/2017 10:43 PM + */ +@Service("messageService") +public class TcpMessageHandlerAdapter implements MessageService { + + private Logger logger = LoggerFactory.getLogger(TcpMessageHandlerAdapter.class); + + + @Value("${nettym.url}") + private String url; + + @Resource + private MemberService memberService; + @Resource + private VenueService venueService; + + private Set channels = new HashSet<>(); + + @Resource + private DeviceService deviceService; + + @Resource + private ConfigService configService; + + private Channel enter; + + private Channel out; + + @Resource(name = "scheduledExecutorService") + private ScheduledExecutorService scheduledExecutorService; + + @Resource + private MemberEnterVenueLogService memberEnterVenueLogService; + + + @Resource + private RestTemplate restTemplate; + + public void sendMessage(MemberDto memberDto, Integer deviceId) { + MessageDto messageDto = new MessageDto(); + messageDto.setCmdId(Cmd.FACEID.id); + messageDto.setResult(memberDto); + logger.info("发送消息" + channels.size() + ";deviceId:" + deviceId); + if (deviceId == 1) { + if (enter != null) { + enter.writeAndFlush(messageDto); + } + } else { + out.writeAndFlush(messageDto); + } + } + + public void sendOpenMessage(MessageDto messageDto, Integer deviceId) { + logger.info("发送消息开门" + channels.size()); + if (enter != null) { + enter.writeAndFlush(messageDto); + } + } + + /** + * 接收设备发送过来的协议数据,业务处理后并返回 + * + * @param channel netty的连接通道会话 + * @param content 消息内容 + */ + @Override + public void receive(Channel channel, String content) { + try { + //解析数据 + Cmd cmd = resolveCmd(content); + logger.info("收到消息" + cmd.text); + switch (cmd) { + case HB: + break; + case FACEID_RESPONSE: + synchronized (this) { + resolve(channel, content); + } + break; + default: + break; + } + } catch (Exception e) { + logger.error("消息内容:" + content); + logger.error("处理TCP消息异常", e); + } + } + + @Override + public void online(Channel channel) { + channels.add(channel); + } + + + public synchronized void resolve(Channel channel, String content) { + BaseDto baseDto = JsonMapper.nonEmptyMapper().fromJson(content, BaseDto.class); + FaceRecognizeResponse response = JsonMapper.nonNullMapper().fromJson(baseDto.getContent(), FaceRecognizeResponse.class); + Device device = deviceService.findById(Integer.parseInt(baseDto.getDeviceId())); + Venue venue = venueService.findById(device.getVenueId()); + if (FaceRecognizeEnum.RECOGNIZED.name.equals(response.getType())) { + //识别成功 + if (response.getPerson() != null) { + if (device.getId() == 1) { + //进门 + logger.info("开门"); + enter = channel; + enter(device, response, venue); + } else if (device.getId() == 2) { + //出门 + logger.info("出门"); + out = channel; + out(device, response, venue); + } + } + } + } + + public void enter(Device device, FaceRecognizeResponse response, Venue venue) { + try { + int code = 1; + Member member = memberService.findByFaceId(response.getPerson().getId()); + if (member != null) { + //最后进场记录 + MemberEnterVenueLog enterVenueLog = memberEnterVenueLogService.findMemberLastLogNoType(member.getId(), device.getVenueId()); + if (enterVenueLog != null) { + //有记录 查看 最后一次是否是出场 + if (enterVenueLog.getType() == 1) { + //是出场 不用限制 + } else { + //是进场 + Date date = new Date(); + //本日连续进场次数 + int continuityEnterCount = memberEnterVenueLogService.countEnterByDate(member.getId(), device.getVenueId(), date); + logger.info("连续进场次数:" + continuityEnterCount); + //距离上次入场差多少秒 + int differenceSeconds = (int) (date.getTime() - enterVenueLog.getCreatedTime().getTime()) / (1000); + if (continuityEnterCount <= 0) { + //没有连续进场 间隔5分钟 + Config config = configService.findById(1); + if (differenceSeconds <= (Integer.parseInt(config.getValue()) * 60)) { + //小于5分钟 不允许入场 + code = -1; + } + } else if (continuityEnterCount == 1) { + //有过一次连续进场 间隔20分钟 + Config config = configService.findById(2); + if (differenceSeconds <= (Integer.parseInt(config.getValue()) * 60)) { + //小于20分钟 不允许入场 + code = -1; + } + } else { + //超过两次连续入场 入场失败 + code = -1; + } + } + } + MemberDto memberMessageDto = new MemberDto(); + memberMessageDto.setName(member.getNickname()); + memberMessageDto.setAvatar(member.getAvatar()); + memberMessageDto.setMobile(member.getMobile()); + + memberMessageDto.setPlaceName(""); + member = memberService.findByFaceId(response.getPerson().getId()); + memberMessageDto.setAmount(member.getMoney()); + if (code > 0) { + EnterResult result = venueService.enterVenue(response.getPerson().getId(), device.getId()); + if (result.getStatus() >= 0) { + memberMessageDto.setCode(1); + if (result.getStatus() == 1) { + memberMessageDto.setCardName("会员卡"); + } + if (result.getStatus() == 2) { + memberMessageDto.setPlacePrice(result.getMoney()); + memberMessageDto.setFirst(true); + logger.info(member.getId() + "入场成功:" + member.getMoney().toString()); + member = memberService.findByFaceId(response.getPerson().getId()); + memberMessageDto.setAmount(member.getMoney()); + //5秒后开门 + scheduledExecutorService.schedule(new Runnable() { + @Override + public void run() { + MessageDto messageDto = new MessageDto(); + messageDto.setCmdId(Cmd.OPEN_DOOR.id); + messageDto.setDoor(1); + sendOpenMessage(messageDto, 1); + } + }, 5, TimeUnit.SECONDS); + } else { + //开门 + MessageDto messageDto = new MessageDto(); + messageDto.setCmdId(Cmd.OPEN_DOOR.id); + messageDto.setDoor(1); + sendOpenMessage(messageDto, 1); + logger.info(member.getId() + "入场成功:" + member.getMoney().toString()); + + } + memberMessageDto.setMessage("门禁已开,请入门"); + venueService.addNumber(venue.getId(), 1, member.getId()); + venue = venueService.findById(venue.getId()); + sendNumberChange(venue.getNumber()); + } else { + logger.info(member.getId() + "入场失败:" + member.getMoney().toString()); + memberMessageDto.setCode(-1); + memberMessageDto.setMessage(member.getName() + "您好,您的余额不足,请扫描门禁上张贴的小程序二维码充值"); + } + } else { + logger.info(member.getId() + "入场失败:连续入场"); + memberMessageDto.setCode(0); + Config config = configService.findById(1); + memberMessageDto.setMessage("无出门记录连续入场,请" + config.getValue() + "分钟之后再试"); + } + sendMessage(memberMessageDto, device.getId()); + + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void out(Device device, FaceRecognizeResponse response, Venue venue) { + Member member = memberService.findByFaceId(response.getPerson().getId()); + if (member != null) { + //出场 不用判断直接出 + MemberEnterVenueLog memberEnterVenueLog = new MemberEnterVenueLog(); + memberEnterVenueLog.setOrderSn(""); + memberEnterVenueLog.setType(1); + memberEnterVenueLog.setMemberId(member.getId()); + memberEnterVenueLog.setVeneuType(device.getVenueType()); + memberEnterVenueLog.setVenueId(device.getVenueId()); + memberEnterVenueLog.setPlatformId(member.getPlatformId()); + memberEnterVenueLogService.save(memberEnterVenueLog); + logger.info("用户" + member.getNickname() + "出场"); + MemberDto memberMessageDto = new MemberDto(); + memberMessageDto.setAmount(member.getMoney()); + memberMessageDto.setName(member.getNickname()); + memberMessageDto.setAvatar(member.getAvatar()); + memberMessageDto.setMobile(member.getMobile()); + memberMessageDto.setPlaceName(""); + memberMessageDto.setMessage("欢迎下次再来" + venue.getName()); + memberMessageDto.setCode(2); + MessageDto messageDto = new MessageDto(); + messageDto.setCmdId(Cmd.OPEN_DOOR.id); + messageDto.setDoor(2); + sendOpenMessage(messageDto, device.getId()); + sendMessage(memberMessageDto, device.getId()); + venueService.addNumber(venue.getId(), -1, member.getId()); + venue = venueService.findById(venue.getId()); + sendNumberChange(venue.getNumber()); + } + } + + public void sendNumberChange(Integer number) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap param = new LinkedMultiValueMap<>(); + param.add("LingtekID", "5d14229fcb1f5c1a9046f429"); + param.add("Number", number.toString()); + HttpEntity> request = new HttpEntity<>(param, headers); + ResponseEntity result = restTemplate.exchange("http://lingtek.jalasmart.com/api/v1/lingtek/number", HttpMethod.PUT, request, Result.class); + logger.info("灯光结果" + JsonMapper.nonDefaultMapper().toJson(result)); + } + + + @Override + public void destory(Channel channel) { + channels.remove(channel); + } + + @Override + public void doOffLine(Integer memberId, String nickname, String machineSn) { + + } + + @Override + public void sendMessage(MemberDto memberDto) { + + } + + + protected Cmd resolveCmd(String message) { + BaseDto baseDto = JsonMapper.nonEmptyMapper().fromJson(message, BaseDto.class); + return Cmd.getCmd(baseDto.getCmdId()); + } + + +} diff --git a/netty-pad/src/main/java/com/sv/netty/utils/CommonUtils.java b/netty-pad/src/main/java/com/sv/netty/utils/CommonUtils.java new file mode 100644 index 0000000..7d72218 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/utils/CommonUtils.java @@ -0,0 +1,76 @@ +package com.sv.netty.utils; + +import java.nio.charset.Charset; + +/** + * USER: douya + * DATE: 2017-08-28 + */ +public class CommonUtils { + + + + public static byte[] intToBytes2(int n){ + byte[] b = new byte[4]; + + for(int i = 0;i < 4;i++) + { + b[i]=(byte)(n>>(24-i*8)); + + } + return b; + } + + /** + * byte数组转换成16进制字符串 + * @param src + * @return + */ + public static String bytesToHexString(byte[] src){ + StringBuilder stringBuilder = new StringBuilder(); + if (src == null || src.length <= 0) { + return null; + } + for (int i = 0; i < src.length; i++) { + int v = src[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + return stringBuilder.toString(); + } + + /** + * byte数组转换成16进制字符数组 + * @param src + * @return + */ + public static String[] bytesToHexStrings(byte[] src){ + if (src == null || src.length <= 0) { + return null; + } + String[] str = new String[src.length]; + + for (int i = 0; i < src.length; i++) { + int v = src[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + str[i] = "0"; + } + str[i] = hv; + } + return str; + } + + + public static void main(String[] arg){ + String message = "{\"cmd\":\"text_message\",\"content\":\"开心开心\",\"member_count\":0,\"system\":0,\"vmc_no\":\"322af403825a\""; + byte[] bodys = message.getBytes(Charset.forName("UTF-8")); + String magic = bytesToHexString("doll".getBytes(Charset.forName("UTF-8"))); + String length = bytesToHexString(intToBytes2(bodys.length+8)); + System.out.println(magic+length+bytesToHexString(bodys)); + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/utils/EncodeUtils.java b/netty-pad/src/main/java/com/sv/netty/utils/EncodeUtils.java new file mode 100644 index 0000000..7507d59 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/utils/EncodeUtils.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2005-2009 springside.org.cn + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * $Id: EncodeUtils.java 984 2010-03-21 13:02:44Z calvinxiu $ + */ +package com.sv.netty.utils; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; + +/** + * 各种格式的编码加码工具类. + * + * 集成Commons-Codec,Commons-Lang及JDK提供的编解码方法. + * + * @author ranfi + */ +public class EncodeUtils { + + private static final String DEFAULT_URL_ENCODING = "UTF-8"; + private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); + + /** + * Hex编码. + */ + public static String encodeHex(byte[] input) { + return Hex.encodeHexString(input); + } + + /** + * Hex解码. + */ + public static byte[] decodeHex(String input) { + try { + return Hex.decodeHex(input.toCharArray()); + } catch (DecoderException e) { + return null; + } + } + + /** + * Base64编码. + */ + public static String encodeBase64(byte[] input) { + return Base64.encodeBase64String(input); + } + + /** + * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548). + */ + public static String encodeUrlSafeBase64(byte[] input) { + return Base64.encodeBase64URLSafeString(input); + } + + /** + * Base64解码. + */ + public static byte[] decodeBase64(String input) { + return Base64.decodeBase64(input); + } + + /** + * Base62编码。 + */ + public static String encodeBase62(byte[] input) { + char[] chars = new char[input.length]; + for (int i = 0; i < input.length; i++) { + chars[i] = BASE62[(input[i] & 0xFF) % BASE62.length]; + } + return new String(chars); + } + + +} diff --git a/netty-pad/src/main/java/com/sv/netty/utils/JsonMapper.java b/netty-pad/src/main/java/com/sv/netty/utils/JsonMapper.java new file mode 100644 index 0000000..b4d736d --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/utils/JsonMapper.java @@ -0,0 +1,204 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + */ +package com.sv.netty.utils; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.util.JSONPObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; + +/** + * 简单封装Jackson,实现JSON String<->Java Object的Mapper. + *

+ * 封装不同的输出风格, 使用不同的builder函数创建实例. + * + * @author calvin + */ +public class JsonMapper { + + private static Logger logger = LoggerFactory.getLogger(JsonMapper.class); + + private final ObjectMapper mapper; + + public JsonMapper() { + this(null); + } + + public JsonMapper(Include include) { + mapper = new ObjectMapper(); + // 设置输出时包含属性的风格 + if (include != null) { + mapper.setSerializationInclusion(include); + } + // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性 + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + } + + /** + * 创建只输出非Null且非Empty(如List.isEmpty)的属性到Json字符串的Mapper,建议在外部接口中使用. + */ + public static JsonMapper nonEmptyMapper() { + return new JsonMapper(Include.NON_EMPTY); + } + + /** + * 创建只输出初始值被改变的属性到Json字符串的Mapper, 最节约的存储方式,建议在内部接口中使用。 + */ + public static JsonMapper nonDefaultMapper() { + return new JsonMapper(Include.NON_DEFAULT); + } + + public static JsonMapper nonNullMapper() { + return new JsonMapper(Include.NON_NULL); + } + + /** + * Object可以是POJO,也可以是Collection或数组。 如果对象为Null, 返回"null". 如果集合为空集合, 返回"[]". + */ + public String toJson(Object object) { + + try { + return mapper.writeValueAsString(object); + } catch (IOException e) { + logger.warn("write to json string error:" + object, e); + return null; + } + } + + /** + * 反序列化POJO或简单Collection如List. + *

+ * 如果JSON字符串为Null或"null"字符串, 返回Null. 如果JSON字符串为"[]", 返回空集合. + *

+ * 如需反序列化复杂Collection如List, 请使用fromJson(String, JavaType) + * + * @see #fromJson(String, JavaType) + */ + public T fromJson(String jsonString, Class clazz) { + if (StringUtils.isEmpty(jsonString)) { + return null; + } + + try { + return mapper.readValue(jsonString, clazz); + } catch (IOException e) { + logger.warn("parse json string error:" + jsonString, e); + return null; + } + } + + /** + * 反序列化复杂Collection如List, + * 先使用createCollectionType()或contructMapType()构造类型, 然后调用本函数. + * + * @see #createCollectionType(Class, Class...) + */ + public T fromJson(String jsonString, JavaType javaType) { + if (StringUtils.isEmpty(jsonString)) { + return null; + } + + try { + return (T) mapper.readValue(jsonString, javaType); + } catch (IOException e) { + logger.warn("parse json string error:" + jsonString, e); + return null; + } + } + + /** + * 构造Collection类型. + */ + public JavaType contructCollectionType(Class collectionClass, Class elementClass) { + return mapper.getTypeFactory().constructCollectionType(collectionClass, elementClass); + } + + /** + * 构造Map类型. + */ + public JavaType contructMapType(Class mapClass, Class keyClass, Class valueClass) { + return mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass); + } + + /** + * map 转 bean + * + * @param map + * @param beanClass + * @return + */ + public T convertMapToBean(Map map, Class beanClass) { + try { + return mapper.convertValue(map, beanClass); + } catch (Exception e) { + logger.warn("convertMapToBean error! ", e); + } + return null; + } + + /** + * map 转 bean + * + * @param bean + * @param objectClass + * @return + */ + public T convertBeanToOther(Object bean, Class objectClass) { + try { + return mapper.convertValue(bean, objectClass); + } catch (Exception e) { + logger.warn("convertMapToBean error! ", e); + } + return null; + } + + /** + * 当JSON里只含有Bean的部分屬性時,更新一個已存在Bean,只覆蓋該部分的屬性. + */ + public void update(String jsonString, Object object) { + try { + mapper.readerForUpdating(object).readValue(jsonString); + } catch (JsonProcessingException e) { + logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e); + } catch (IOException e) { + logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e); + } + } + + /** + * 輸出JSONP格式數據. + */ + public String toJsonP(String functionName, Object object) { + return toJson(new JSONPObject(functionName, object)); + } + + /** + * 設定是否使用Enum的toString函數來讀寫Enum, 為False時時使用Enum的name()函數來讀寫Enum, 默認為False. + * 注意本函數一定要在Mapper創建後, 所有的讀寫動作之前調用. + */ + public void enableEnumUseToString() { + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + } + + /** + * 取出Mapper做进一步的设置或使用其他序列化API. + */ + public ObjectMapper getMapper() { + return mapper; + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/utils/JsonUtils.java b/netty-pad/src/main/java/com/sv/netty/utils/JsonUtils.java new file mode 100644 index 0000000..250c659 --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/utils/JsonUtils.java @@ -0,0 +1,94 @@ +package com.sv.netty.utils; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * USER: douya + * DATE: 2017-11-01 + */ +public class JsonUtils { + + + /** + * Logger for this class + */ + private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class); + + private final static ObjectMapper objectMapper = new ObjectMapper(); + + static { + objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + private JsonUtils() { + } + + public static String encode(Object obj) { + try { + return objectMapper.writeValueAsString(obj); + } catch (JsonGenerationException e) { + logger.error("encode(Object)", e); //$NON-NLS-1$ + } catch (JsonMappingException e) { + logger.error("encode(Object)", e); //$NON-NLS-1$ + } catch (IOException e) { + logger.error("encode(Object)", e); //$NON-NLS-1$ + } + return null; + } + + /** + * 将json string反序列化成对象 + * + * @param json + * @param valueType + * @return + */ + public static T decode(String json, Class valueType) { + try { + return objectMapper.readValue(json, valueType); + } catch (JsonParseException e) { + logger.error("decode(String, Class)", e); + } catch (JsonMappingException e) { + logger.error("decode(String, Class)", e); + } catch (IOException e) { + logger.error("decode(String, Class)", e); + } + return null; + } + + /** + * 将json array反序列化为对象 + * + * @param json + * @param typeReference + * @return + */ + @SuppressWarnings("unchecked") + public static T decode(String json, TypeReference typeReference) { + try { + return (T) objectMapper.readValue(json, typeReference); + } catch (JsonParseException e) { + logger.error("decode(String, JsonTypeReference)", e); + } catch (JsonMappingException e) { + logger.error("decode(String, JsonTypeReference)", e); + } catch (IOException e) { + logger.error("decode(String, JsonTypeReference)", e); + } + return null; + } + +} diff --git a/netty-pad/src/main/java/com/sv/netty/utils/LiveTime.java b/netty-pad/src/main/java/com/sv/netty/utils/LiveTime.java new file mode 100644 index 0000000..42788ab --- /dev/null +++ b/netty-pad/src/main/java/com/sv/netty/utils/LiveTime.java @@ -0,0 +1,28 @@ +package com.sv.netty.utils; + +/** + * USER: douya + * DATE: 2017-08-07 + */ +public enum LiveTime { + + SECONDS_15(15 * 1000), SECONDS_30(30 * 1000), + + MINUTES_1(1 * 60 * 1000), MINUTES_2(2 * 60 * 1000), MINUTES_5(5 * 60 * 1000), MINUTES_10(10 * 60 * 1000), MINUTES_30( + 30 * 60 * 1000), + + HOURS_1(1 * 60 * 60 * 1000), HOURS_2(2 * 60 * 60 * 1000), HOURS_5(5 * 60 * 60 * 1000), HOURS_12( + 12 * 60 * 60 * 1000),HOURS_36(36*60*60*1000), + + DAYS_1(1 * 24 * 60 * 60 * 1000), DAYS_2(2 * 24 * 60 * 60 * 1000), DAYS_5(5 * 24 * 60 * 60 * 1000), DAYS_15(15 + * 24 * 60 * 60 * 1000L),DAYS_30(30* 24 * 60 * 60 * 1000L) + + ; + public final long time; + + LiveTime(long time) { + this.time = time; + } + + +} diff --git a/netty-pad/src/main/resources/config/application-dev.yml b/netty-pad/src/main/resources/config/application-dev.yml new file mode 100644 index 0000000..b28576f --- /dev/null +++ b/netty-pad/src/main/resources/config/application-dev.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:mysql://127.0.01:3306/smart_venue?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&useAffectedRows=true&useSSL=false + username: root + password: 123456 + + jpa: + show-sql: true + +oss: + accessKeyId: LTAIlbtS4W2Xe4OV + accessKeySecret: qWMYkSfmXFtRoIv9q9OCbszcF9U7dX + protocol: http + name: smartvenue + endPoint: http://oss-cn-beijing.aliyuncs.com + url: https://smartvenue.oss-cn-beijing.aliyuncs.com/ \ No newline at end of file diff --git a/netty-pad/src/main/resources/config/application-prod.yml b/netty-pad/src/main/resources/config/application-prod.yml new file mode 100644 index 0000000..bdd9b4a --- /dev/null +++ b/netty-pad/src/main/resources/config/application-prod.yml @@ -0,0 +1,17 @@ +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/smart_venue?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&useAffectedRows=true + username: root + password: hyty1234 + driver-class-name: com.mysql.cj.jdbc.Driver + + jpa: + show-sql: true + +oss: + accessKeyId: LTAIlbtS4W2Xe4OV + accessKeySecret: qWMYkSfmXFtRoIv9q9OCbszcF9U7dX + protocol: http + name: smartvenue + endPoint: http://oss-cn-beijing.aliyuncs.com + url: https://smartvenue.oss-cn-beijing.aliyuncs.com/ \ No newline at end of file diff --git a/netty-pad/src/main/resources/config/application.yml b/netty-pad/src/main/resources/config/application.yml new file mode 100644 index 0000000..c56fd2c --- /dev/null +++ b/netty-pad/src/main/resources/config/application.yml @@ -0,0 +1,104 @@ +server: + port: 8021 + context-path: /netty + tomcat: + uri-encoding: utf-8 + + + +spring: + profiles: + include: + -dev + -prod + active: dev + + + # 数据库连接池配置 + druid: + filters: stat + initialSize: 1 + minIdle: 1 + maxActive: 40 + maxWait: 600000 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: SELECT 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxPoolPreparedStatementPerConnectionSize: 20 + WebStatFilter: + enabled: false + urlPattern: + exclusions: + sessionStatMaxCount: + sessionStatEnable: + principalSessionName: + principalCookieName: + profileEnable: + StatViewServlet: + enabled: true + urlPattern: /druid/* + resetEnable: true + loginUsername: druid + loginPassword: druid + allow: + deny: + aop: + auto: true + http: + encoding: + force: true + charset: utf-8 + enabled: true + + jackson: + date-format: yyyy-MM-dd HH:mm:ss + property-naming-strategy: CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES + + redis: + pool: + max-active: 1000 + max-wait: -1 + max-idle: 8 + min-idle: 8 + timeout: 60000 + +# MyBatis Configuration +mybatis: + type-aliases-package: com.ydd.oms.entity + config-location: classpath:mybatis/mybatis-config.xml + mapper-locations: classpath:mybatis/mapper/*/*.xml + + +face: + url: 192.168.1.111 + account: test@test.com + pwd: 123456 + +nettym: + url: http://127.0.0.1:8021/netty/message/send + + +#netty服务器配置 +netty: + port: 56791 +boss: + thread: + count: 1 +worker: + thread: + count: 2 +so: + keepalive: true + backlog: 128 + reuseaddr: true +tcp_nodelay: true + +logging: + level: + com: + sv: + mapper: DEBUG \ No newline at end of file diff --git a/netty-pad/src/main/resources/logback.xml b/netty-pad/src/main/resources/logback.xml new file mode 100644 index 0000000..e7fb94d --- /dev/null +++ b/netty-pad/src/main/resources/logback.xml @@ -0,0 +1,46 @@ + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + ${LOG_HOME}/common-default.log + + ${LOG_HOME}/common-default-%d{yyyy-MM-dd}.log + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + ${LOG_HOME}/common-error.log + + ERROR + + + ${LOG_HOME}/common-error-%d{yyyy-MM-dd}.log + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/netty-pad/src/main/resources/mybatis/mybatis-config.xml b/netty-pad/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 0000000..a39c274 --- /dev/null +++ b/netty-pad/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/ClientTest.java b/netty-pad/src/main/test/java/test/netty/nio/net/ClientTest.java new file mode 100644 index 0000000..a280080 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/ClientTest.java @@ -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(); + } +} \ No newline at end of file diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientHandler.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientHandler.java new file mode 100644 index 0000000..fa584f6 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientHandler.java @@ -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()); + } + } + } + +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientInitializer.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientInitializer.java new file mode 100644 index 0000000..0f345b2 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientInitializer.java @@ -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 { + + 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); + } + +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientThread.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientThread.java new file mode 100644 index 0000000..483b6e3 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/ClientThread.java @@ -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); + } + } + + +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/Cmd.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/Cmd.java new file mode 100644 index 0000000..c4509f8 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/Cmd.java @@ -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; + } + +} + diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/CustomDecoder.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/CustomDecoder.java new file mode 100644 index 0000000..5354b20 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/CustomDecoder.java @@ -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); + } + +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/DataConfig.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/DataConfig.java new file mode 100644 index 0000000..95c2880 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/DataConfig.java @@ -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; + + +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/MessageDecoder.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/MessageDecoder.java new file mode 100644 index 0000000..331abf6 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/MessageDecoder.java @@ -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. + *

+ * 解码器 + */ +public class MessageDecoder extends ByteToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List 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; + } + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/client/MessageEncoder.java b/netty-pad/src/main/test/java/test/netty/nio/net/client/MessageEncoder.java new file mode 100644 index 0000000..086bf81 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/client/MessageEncoder.java @@ -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 { + + 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)); + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/AddFaceResponse.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/AddFaceResponse.java new file mode 100644 index 0000000..bd46e11 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/AddFaceResponse.java @@ -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 { + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/BaseDto.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/BaseDto.java new file mode 100644 index 0000000..074552f --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/BaseDto.java @@ -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; + } + + +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceImageDto.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceImageDto.java new file mode 100644 index 0000000..1efb244 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceImageDto.java @@ -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; + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceRecognizeResponse.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceRecognizeResponse.java new file mode 100644 index 0000000..658bec8 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/FaceRecognizeResponse.java @@ -0,0 +1,639 @@ +package test.netty.nio.net.dto; + +import java.io.Serializable; +import java.util.List; + +public class FaceRecognizeResponse implements Serializable { + + /** + * data : {"status":"recognized","track":6,"timestamp":1533808724,"face":{"image":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCACPAJQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD6Nx7Um33qQ9KZXhJ2IE2+9BXHenU2QtjK9ae+xSGO4QZz0rjPiN8VfCnw00K513xJqscKwA7IVYGWVsZCoCRk/Uge9Vviv8T9E+FPhi68ReIJQ3y+XbWa4825k7BckH8eg71+bXxR+JfiT4reIZNe8SXLMWXyorfd+7gjHRQvTvjPWtKdNyZSVz1vx7+15q/jzWIdJllvdA8Lvd+ZetpWz7dPCoO1RIcAAkjdjsO4yG8K8S6xoF0LCDw3ostnFbRyiaaeffLcStIx34ACoNmz5QODuOTmsF0CjYDwOAKTjua61h4lNIsrqN95Yia8mKZzt3nBp1vqN3aSi4tLiSKVWDKysQVI7g9qq5FGQa0VJCubV/4y8WanJHPqHifVbmSI5jaW7kcx+u3J4r034Z/tX/FP4Z6bfaZaX0eqpeMpjfUGaRrbb/cznOenPTqK8YpGolRVhpXPvb4Jftp2njPU7bw38QILbSrqYbUvg+2FnzwrD+En16V9KjV9H1/SLqPTdVtLvMLOphmVwSOmCDjrivx0BYdDW54U8Xa94P1iDWtC1Ge0uYWBDxtgkA5K/Q1z1KCtoDifsRHdCSKMsfmMaFvYkcipozyR614v+zj8c9O+Mfh4yXBEet2CRxX1sX3YJX5XU9SuBjkDkEV7Opw2a5ZRcSB9KD2pKB1pITHr1ooBAPNFMkoj5ulIy7RyMV89+GP2sPE3iXwh8SoNG8F+Gm8XeCdMtNds7Bbr7ZFqGnef5V5IsqSBVeBXjfbuDNuAAbpXAaf+2z8SdQ02LUZPDXgf7JdSyW6+bFcybtqgnIyTghv/AK1NRi+o0rn19I6lWVdrHBwpOATXNePfHGn/AA68G6l4z1lNtvpkDy7egdx9xAfV2IUcdSM8ZI+bk/bC8UqGP/CE/CssVwssuiXbOh7MDtwCOteD/Hn9oLx/8VLqLQtd1HS002zKyC10iOSG2dyMqzK2CWAYfQVtGFijk/in8V/E/wAWvEtz4k8RSiNXc/ZrOInyrePoFUeuByfc1w7kmpP4absZhwM11U4qxqiuyHNN8s1b+zykcrU0enXMmNkROfatOaxfs2zO8s0hXHNaL2EqSCNl5NOn0i7jgNyYH8sHBcDgGjmRPsmZYyTmlyDxVg2rcjHIqIRkHpVXTBwcdxoFSAAikIK8EUDPWla4WOw+GPxL8SfCnxZZ+K/Dtzte3kHnwMfkuIuN0bD0IGOOR1ByK/U34feLoPH/AIO0bxjpCg22sWi3S7mLBGIy0Z91OQfcGvyFBBGDzX6B/sFfEJfE3w4vvBNzdL53ha7Cxp0HkTKWUD1IZZST/tL6GuWtSurkSR9OAakSMTWwUjnMJJ/nS+Vd97yMf7sP+JqxjBxRsHrXHaxle5AILnvqMw/3UUf0oqfaaKBHkWg62/hueDX7H9nHwTBp92Bp+qamviXTLKSy02YhJ32jPmhFIfyz12cYOK+XLv4NXXgbxl4x+GI13wul5oWtLqlhJfyz/wCladdRRvEYZYkMZGHAIOMFT1xivatasvE/ik6X4nPwt8b6Ne3tlHe6dcaL4q0TTJ5bOdQ3zQhWj+dSMxSHJ4BArn/iL8VNO8WeANL+IE3ww19JPBGsReA/F6J4jW11E2GEawu5Vt0EUYeR51LBRlwVBYY289PazNeVI8sf4Y+O7nyljtvDkgRwZbm31TI8vPJ2lQTgd8Zr50166kvtavZ3kSTbKUDJnaQOBjIBx+FfUup/GvwZaaHcTWvwbtrW41SGa3tr64115GtpFdQzbWHzN1w2Pyr5NMUyO2+Tdyf85711YeE07SDlBRnit/w34duNZuhDGmAELsScAD3rJsLSfUr2LTLRWa4nO2NVXcx5xwO9fQGmeENK0ryUluLcSpBF5ieVtZCxAH3iO5z7ZNd1SXs1ZG9KHMzy288LC3fIRiEznHQVuab4SkUB5V4K8D2967zydCnHk27xOZZpYg4wd+wkNg9COK1EsbNdoMiKFyCvrxxg1xyrN7HqUqCZ5TdeDEFxDctAJESYeYueWQkZxn0Ga6y18L6TJbPayWokhupNpQnKKo9/4eg5wa6PU7jTtMtJZZ0XZHGXC78Egdf6VxGrfEyGG4ubDQoJ5LNAN21SxkJBJP8As9lz7VCqybsdP1VIwNT8CX/hrUp7q2hjv7IQlZU25YhsDIHrz2rG1PwHe26x3emFLiGQjah++M+o9Pf2rvNFu9Vv5P7RmuZW2wgR24ORk/eJJ9AAO+cc1tWUF3PcCOW2kMahcSLGSoJPA9B0zXQpyiTUwsJHg2raTc6dJsuk2ydSB0FZwxgjFe2+PfCUup2Ams7dBJG252AOSvOc4Ht+teMPGI5HQ9VbBrop1Lnm16Hs3oRqvbFfUv8AwT51mWz+Juv+HUT5NQ0hrtjnjMMiKMjuf3x/I18vou48c/Svb/2L/EN1on7QOm2lqMrq1ndafOCQPkKeZ/6FCh/Ciq1ys4ai7H6YodwBBzT6r2bE267uuasV5xgFFFFAHzrafAP4L2H2qe2/Zs+KJtXuMkX9iIyAcdVFzuJzznbnmtXTvBXwjtfDWu/DvQf2dvHGgw+O7aLTrvUz4fmuIrOQ7nt3mZWkZAkuxm2glTtLD0+d/Dnxj8Pa/wCNvDFr40+H/im9v7u6MNjrvi34r3UUWnybwN1xN5QCrGTvywHBIA4xXq51PxBe/FC5+JOg/GD4SW+pmWOKFbHx1dXVlcSwjbAZkiaEOAgAZsDcMNtHAOVZOLVjo0PB/D/g7Xbv4c3vgfUvh7Nc+JvDHiq+j1G/t7uBJ7VgiLLaujNudRJuOBkBiT15rx/xv4fvvDerGG/06SzS8UXNrHJtDeUeASAcDkHivqrxZrfhs32tfFTxFD8O/FviW41GO01e68P2UjaXDMpDFgZykvzxRfNIoIZ2b5jya8K8ZXVh4v8AC1lqaeGNB0uW4vJovtlkJA0iREkgliRy2eg6Ba6aM2wOX+D2nNqXxCtJktpbhrKCW5EcSlnIRSeAOTyRxXU+KfD3i7V/KuVnlsbyLe13BIGjkCu3O7jOeOVNR/s5WVtD8Uoo7m4dFezn8w79oCLtY5Ppwc+2a9a8a6vpthf3d/PA142q6nPa20cxZI5GQDDCQA5UAglhnnPXFViJPQ6sOkeLJ4K8b6U0sen6hcNIxd33MAUlcLudXGeSAM//AK69D0O41e60W1F9cCa4g+W5k8tRlwP9kAHk4zjnGTWRY+LtQ1hruT+xrXTJLL5Z4UYuAckYHvxyRj2ArrPD09lo1v8AaNSlZLZyIYhIVK+dtyRtHAGSMnpiuRqx61JKxzXi/wAPjxBJCdRCxQW7b4lUnJc4yCe4OOnHbrVfTtP0zTTujt4o1UnzScKGHbce+O2a6zVfE2nyRmxgEa/aG3tIUVlkAXA8vPQZI5HPHvWBeWE5QvAmVkXaysMrz3pxbibryCy1HQIpxZ299b/aiN3lJySueTkemRx71vadN5xby1fbJiRcjrgkZrn/AAV4Cl8Oy6jqM919tnmVYgUYuBxl9uQMZwAPxFdRJHNp2nyHT7NEkkXMQIICnB49RyfzqnNjaFlubW3gF88ZlR0YCP8AhkXI3A9umeteBeOvC6+FNTNvq+qaeb+7H21bKwBdLaCTOxXkIGW2kEAA4A5PavpS1tftH2TzrdAYoB8iqAu4n5gfz+teMftI+HYtN1nTNWt4FWfUrcJM5blmQjbx/ukcj0ropTRxYilKdkiz8LfglF4t0XWtW1uWWGP7Ey6QFlCRS3ZBKGVsEmMbSGVQCc8MMc+ifBfRooP2mfB11DptvYx21nLbyRxRBEeRIpMlf7xwyMT1+cZrSttV161sfCNrpsNk2mQaZbpegoAwYsFVhJjAHlgH1JI617V+z94Yj1HxRrPxakW38qa3Ok2sO0ZgbbES/oCVjKE9ww9Kqbujjr4f2dNtnvUAG/CtwKs1n2chBZmAGWOD6j1q013ap/rJ1X6muc8gmoqkdWtMkLKCPWiqSuB8n/Ez4QfEfwz+0LpPjb4NXQ0mTWHudVsLkraTC1ulQLORFcHaw2uDgqR+8x2BGbrvwn+NHijWZL7xjo2m3N42/wA6/trSwt5r9+AryR24RM7Qeg719CajpNh4/wBK0zV/Evwa0vWptKWW3srq+8QPamBm2CUKqISpbYDyDwOtUv8AhXvhnt8IdJjGNvPiiZuPr5YI6micVPc0TPCPCvwH+L3hnxWbK/8AB0Nz4L8VrHpusWQljtpIomVkNwpU4Vot3mDhtw8xcAsWHOXv7J/xH0u81jwVMlvZaLpN1MNMnupQiTW4LMZkYZVy2Dnn0HavdG+BfwzjkuJF+HWlx/amBmRtZvbhVwQcqXYc8duOT61Z1D4V+AH0vTtATwfZNpWkLmws5tTvJltGMhdvLLPwCxJPA6nrTh7mw0z5o0H4QaL8OfjPa6P408axaSNW8MXEtleWNyt3HLftLHCLUwqhdiVckAY3E4ByDjs9fgkg1/U/C2uxJcXekN9m+1lFQSqQHTCDgNtkDeoyOc8Vt/GH4aeBtJvPAXinRfC+jaNbeGNft5L2eJWE08c08ZO6UkswXaw+bjDY5yRWx8T7e61Lxjfz6icukiT20u7cGi2gHB9MggfSsMRVasejg4KW549pvgu3tAllp1qqbg3nSbArSEnjce+PftXW2fhWK48ReHL+2uAIrOFo5kbnzojkEkdAc4GeT1FXAUiJY4wOvGePp3qP4VQNqfiLxDdmS4W301oYV8xfkUldzqmeBnqTjnI71g6jkexCCiYWq+EdI1SBIJLQQxxu8sSQnBViT044+lPi06GNQAMkKqnn0rZllsyq3Ed9Dtd2J3PtK8nnB5xkYz6msa6uzHMhhePMrrHgtu43HkEZHIrVO6OuEEy/YWiQkCFQo7itQ2kLglowc+tZ9i5fYw6E9K2RtxknAx6VdrmnIiOC3VRmJRkEDH1rzP426K+sadY6pJbPK9otxEmzaQm7Z8xDKecL8vbrnNepwuA0wePay4VQvT1OfwNZni7T4NT0JoZQIoYd9zczbypWJFyQCD3G4e+SOKqPu7GNaCWph+HbXU9Y8I2V3q8sYsraC2GnWFvIn7hUQAszqMs3GCGwONx64r6I8HwRaL4RbTYLm4Q3sy30kb4VopA+fLGOiYHA9zXg/wCzzq6fF1GudJ8LyaNpuixub+3gtI3jnuSh2CJi24LwjMOgOfWvoiz0bxHqEcd4uj3Kq6qwNwwjwOoHzelbJ3Wp4eZVFy8qLa6rfJJPJDMypNK0oHpntSNqU8v+tlZvrS6d4L1m1t/sy3NnGPNZ9tzcGRxuOSBjt6Vej8HXZlYXWvQxRbf+WFpubd6fMenv+lS49jxDHe7Z5AkbOWz0ANFdHb+FdGhkDXeoanOF64kVFbHbAX+tFaQgwOHh1ee1vbtJSHXUnWck42RyqoU4z6gelStrDLMsRVQXGR8grKvdN1a/thBpf2mKUMPna3AKnrwD6jitA6Fq7yiOSJ08sYAJA5xzk+lZmqih818HPzSHJ7AVWa5J+5IfXrV3/hF72QRebPAmzOfmJz9f8KmtvCscJ/eXwGRj5EJJ/E0DscjrVjD4htLvSrxYZLa5SMMf+WgZWzkNjjAGR7+nWszUbW71DwzBfXF2tw1jB9lkAbc4+bjGBzwD3zXpK+FdPKRxNLMUVstg7OO/T2qrqvh3SW0+a1gthaRFQB5Yz93JBPvWNWmpK514aq4Ox4jcRJACqtnjr1/nXEWXh/xpeeHvFGj6DqU0FxqV7ay2mSeWjKlyzD5sH5ckdh0r0fWdOS1u40aIrAZGQkliW+Y4xjp2qpJc6doMVxcajdw2Uunp5nmeZgMrZwAeDk7SCMeg5rkR71KfMkzzm602+eXTdH1meSYLpxa7b+NpMfMc5JOSMgE+3FO8HaXNpEM1nJNLJF5hljDk4VmJLY/Gse+8aXmrTXt/pekXMEc4jSzuRbs0W1erEnkgnJ6c1PpfjbV7SeGPXNA+R7cRtLCp3F8gGQoR8oI3H5eQcYreOx2U3c9G0oLuK9gM1sxhSRj0zXL+Gdfs9dtWvrPTL2yUFoCl1HsZsfxqM8g54PeuotzErAqWIdNgHQgDPJ/T9au9jdD0jABOOtQ6lpd5r/hvW/DthLHHc6xDFp8LyfcV5WKgt14BIJ47VKkoeNWPG4Zx6U/SxcyeIdFto5JBBNq1kZgi5yqzKwz3xxzjscc5xQndnFiXZM9a+C/wytvhN4MsPDMFxDczrH5l5cRptE05+8w9RjjnnGK9BJVyDjn61Bbh5SUtoHkVeOFK4/PFW49P1RyNmnEA93kUf1rpppNHymJk5S1E+Y5PrSHPc1eGi6kAC8ltGD3DliPyFPXw28rBZNVkOT91I8E+wJGK2j7pynI+PvF1l4H8Fal4kvX4soJJ0UKGMjqBtUA8EkkcHtRXkX7a2saZpHhvRfBGnTSyXesTi4uFchm+zR5GQABgF++P4KK1jK4Hq+59+/PU5JodiW3sc59auxeHtZcQl44Iw4Jch9wU54wR14q6nhe8kAWe7RBnIKxg/L6da47GxihlA+RAPwoEjA/Wuij8J2oG2W4lfnPBxVgeGNJwC0DEjvvNFh6HJs+1txYZpqyKzfN93ow2bgR3ruItE0yJY9tlFuUHJIznmp/sdrwBbRjHHC0NXRcHZnz14s02WwSSEpJsdw8eIyHbnoAevWvLde02y1a5S91LS4bmO0wZBcxh8LkErhs4zgZ5zx9K+s/Hng5PE+mrBFarLdxOrW59CTg/UAdq+ZbrRJNQ064kyimeJD1O5TxkMBnngg//AF64Kq5Ge7hp86SPPdavTeXslhBZyQQ6ey20apg4TrkduN36VFbWKyuzts8+5jOcHPTtnrnvz610Op6RFARcif5ZpmBjU4JYBcknvxjjp1qO0toYgrFORnGeTVQlc9WnFI09NjSOM4CqNiKgA4UAYxir6zhGGDkgYzjFULeVFBIZcYyc+lLcXQjyWAXau/OeMcf4itG9C5S5di/NcqoQHuRxWr4QvP8AirtAzJjzNUtlYZx/y0BP8q5pJDK4ZxwOMCn2N0+neIdH1aSUiK01G3cgdcbxnH4A0kmcGJk1Fs+2/svkuevFWFPFK5Ev78AhZFDr7gjNNHWuqF4nytWV56igsG4Jpx/eDy2bAb5SfQGkIxXn/wAdvHUfw/8Ahb4g12KYrffY2t7JV5dp5PlXH0BY5/2a6YJSMj4p+N3jST4j/F/X/EZut9pp0p0bTgjZTyIXILDt8xyegznmiuF023khtQ80haWYmWTJOd7HnOe+aKu3KI/UYKACMDk5NKRnqaUdadgVy2HcYEpdlOwKU4HenYfMxu2jbikaWNFLuwVV6knAFcz8SfiDo/w9+H+r+PNStb69s9FWGaeCxQee8MkgjZ1yRnZncRx0zS6GkXc6dIvOlRACx3LwO/NfJXivU18OeKtRubKz3WUdzPE0EfG3L4Xbg4HPHHHNdz4j+N1/4lmOheDY9Q0PT5E2zX80itdzLjdtjUHEQIKgtknOcdK878ZpEFtWgXAii2SAEbSpOSCAOSc8mvOrzTdj18InFKRwGtaw8c86bVYxS/KjdFyAduT1/wDr1iP4glwiITGYyinAIOSxJPuCOK1dVtnZ2XJYSndx2+tYl3oU7qyx3MsLtGeVGQSOQee+MilSaR7EajaLEnik2sYXeMxPIFBJ5JGencYNWNPu7rVpIrqQY2RlFGCFCnrn35qla6BCzG4uYmkbzVYDqoTuCPTr+ddXZ2UMYYLGF6AADAA+lbNc2xUZOWjJdOMrxB5N29/m+YY+U9CKt3GmxXirHM8iLuUloz8ygHkj3xnFS28RjKxMxwvCgdAPp2q9szTimmZVo3Vj6M+CvxDbxRodnoWr6gJNWsEFsxlcGW5XJ2yerHBAJ9R6V6XtJORnaeVOPvDOMj8a+I5hdpJZJplxLFf3Fx5doYWKSCZRuUhh0+oOeK+kvBH/AAk+geGbGy13xFc6lrEyxyane3CL+/nONzbFwIwoO0AdQozzXfTjzo+axdFwmz0wJuB5GQK+N/22/Gr33irQfh5Zyq8enRjVLxcdJWyEU/Rcn6kYr6XHjyLTbWfWtYVV062jkmllRslQnPQdsd+35V+eninxFd+OfGWt+Mb+Zn/tK8klgzn5Ic4RB6AADj3NbRg46s4iig2pubq3JopHbjAOcUVooqW4H6hgZpdvvTPtVsP+W8f/AH0Kje8hxxMh/wCBCuVcr6gTHA6moXuEXLbgAtUprosflcce9VZ5WZSAe46VqowW8l94EmpOZtLlQhGLjgY4znj8ay9a0+z8QaTcaTqVrHLaXlt9mniYZVkOMj9P0rRJUwhCQfamlR2IH40mqb0ujSL5T5x8R+Db3wRqEUE1sHtCGSGYjKFQOFJ656dsZrnbyJLlh5qnKcYJwR+FfTOuWuh39pJBq1zbrAgxI0kijZ36np618veLfEPw50O/lk0Px54fvrW6n8uMxazbvsbdtLMFYk47nsK8jFUXze7qe1hsRT5bSaRmXNmjS5HQetVpLEGRDtG0HJFSy+KfCYVnHibSWVTgyfbI9p+hzVeHxX4VupVgt/E2kyyMdqpHexsxPoAGrKNKa6M9OGIoW+NfeidbRATtXAPFW4Ew2cdqbeXFrpzxxahcxWrzHEazOELn2B61saZ4d1/UozNpuiX93GMfPBbPIoz05UGulRkuhvCvhlvNfeirHw3uasCeKEBpELZIG0HBJ9K1G8H+LI4Xk/4RTVtyLnH2GUk/QBetdr4O+F9zGP7a8VWxjC7HjgZSBG2eC2QOuenY1tCKe5jicXQgrwmm/UZ8NfB8kNwnizWrdUusbrBBx5Snq3B5JAHUV6Q8jEYLfewOTU50i4hIRLWTaB/dPFE9lcog22kzeyoT/SvSpRpQ+0vvPncVifbO54b+094lOlfDh9HthLGup3Is0nilVduQC6kkhmztAwoIwDkjivl+CP7PZxRA5KqK9j+PHhr4jeM/iQ8mn/D3xLJpmixfZ7WWPS55I5nbmRlITGDgcg9RXC/8Kv8AiY2Ek+G/ikLnquj3H5fcrSpOnbSS+889HMRLcTMFiBkbcAqjjBPGSe/0orvm+G3j/RNCnv1+HXiW71KdlVbeHR7hgijvwnWipjOC6oD/2Q==","rect":{"top":918,"right":872,"bottom":990,"left":798}},"person":{"feature_id":0,"confidence":78.397995,"tag":"{\"description\": \"\", \"remark\": \"\", \"subject_type\": 0, \"name\": \"ndy\", \"inviter_id\": null, \"start_time\": 0, \"title\": \"\", \"interviewee\": \"\", \"avatar\": \"/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg\", \"origin_photo_id\": 3, \"birthday\": null, \"id\": 5, \"entry_date\": null, \"department\": \"\", \"interviewee_pinyin\": \"\", \"job_number\": \"\", \"end_time\": 0}","id":"5"},"quality":0.9968518905807287} + * screen : {"camera_address":"rtsp://192.168.1.160:8554/0/0/0","allowed_subject_ids":[],"network_switcher_status":null,"box_token":"95a0f5b6-924d-4323-9296-39d258f2b3f9","description":null,"allow_all_subjects":true,"box_heartbeat":1533806262,"network_switcher":"","camera_name":"","camera_status":0,"allow_visitor":true,"screen_token":"3c566c3f-6d7f-437a-af56-8ba4a7852745","network_switcher_token":null,"box_status":"0","network_switcher_drive":0,"type":1,"id":1,"camera_position":"测试","box_address":"192.168.1.50"} + * person : {"src":"data:image/jpeg;base64,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","remark":"","subject_type":0,"description":"","inviter_id":null,"timestamp":1533808724,"start_time":0,"title":"","interviewee":"","job_number":"","entry_date":null,"origin_photo_id":3,"birthday":null,"avatar":"/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg","department":"","end_time":0,"interviewee_pinyin":"","id":5,"name":"ndy"} + * error : 允许进入 + * open_door : true + * type : recognized + */ + + private DataBean data; + private ScreenBean screen; + private PersonBeanX person; + private String error; + private boolean open_door; + private String type; + + public DataBean getData() { + return data; + } + + public void setData(DataBean data) { + this.data = data; + } + + public ScreenBean getScreen() { + return screen; + } + + public void setScreen(ScreenBean screen) { + this.screen = screen; + } + + public PersonBeanX getPerson() { + return person; + } + + public void setPerson(PersonBeanX person) { + this.person = person; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public boolean isOpen_door() { + return open_door; + } + + public void setOpen_door(boolean open_door) { + this.open_door = open_door; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public static class DataBean { + /** + * status : recognized + * track : 6 + * timestamp : 1533808724 + * face : {"image":"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","rect":{"top":918,"right":872,"bottom":990,"left":798}} + * person : {"feature_id":0,"confidence":78.397995,"tag":"{\"description\": \"\", \"remark\": \"\", \"subject_type\": 0, \"name\": \"ndy\", \"inviter_id\": null, \"start_time\": 0, \"title\": \"\", \"interviewee\": \"\", \"avatar\": \"/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg\", \"origin_photo_id\": 3, \"birthday\": null, \"id\": 5, \"entry_date\": null, \"department\": \"\", \"interviewee_pinyin\": \"\", \"job_number\": \"\", \"end_time\": 0}","id":"5"} + * quality : 0.9968518905807287 + */ + + private String status; + private int track; + private FaceBean face; + private PersonBean person; + private double quality; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public int getTrack() { + return track; + } + + public void setTrack(int track) { + this.track = track; + } + + + public FaceBean getFace() { + return face; + } + + public void setFace(FaceBean face) { + this.face = face; + } + + public PersonBean getPerson() { + return person; + } + + public void setPerson(PersonBean person) { + this.person = person; + } + + public double getQuality() { + return quality; + } + + public void setQuality(double quality) { + this.quality = quality; + } + + public static class FaceBean { + /** + * image : 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 + * rect : {"top":918,"right":872,"bottom":990,"left":798} + */ + + private String image; + private RectBean rect; + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public RectBean getRect() { + return rect; + } + + public void setRect(RectBean rect) { + this.rect = rect; + } + + public static class RectBean { + /** + * top : 918 + * right : 872 + * bottom : 990 + * left : 798 + */ + + private int top; + private int right; + private int bottom; + private int left; + + public int getTop() { + return top; + } + + public void setTop(int top) { + this.top = top; + } + + public int getRight() { + return right; + } + + public void setRight(int right) { + this.right = right; + } + + public int getBottom() { + return bottom; + } + + public void setBottom(int bottom) { + this.bottom = bottom; + } + + public int getLeft() { + return left; + } + + public void setLeft(int left) { + this.left = left; + } + } + } + + public static class PersonBean { + /** + * feature_id : 0 + * confidence : 78.397995 + * tag : {"description": "", "remark": "", "subject_type": 0, "name": "ndy", "inviter_id": null, "start_time": 0, "title": "", "interviewee": "", "avatar": "/static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg", "origin_photo_id": 3, "birthday": null, "id": 5, "entry_date": null, "department": "", "interviewee_pinyin": "", "job_number": "", "end_time": 0} + * id : 5 + */ + + private int feature_id; + private double confidence; + private String tag; + private String id; + + public int getFeature_id() { + return feature_id; + } + + public void setFeature_id(int feature_id) { + this.feature_id = feature_id; + } + + public double getConfidence() { + return confidence; + } + + public void setConfidence(double confidence) { + this.confidence = confidence; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } + } + + public static class ScreenBean { + /** + * camera_address : rtsp://192.168.1.160:8554/0/0/0 + * allowed_subject_ids : [] + * network_switcher_status : null + * box_token : 95a0f5b6-924d-4323-9296-39d258f2b3f9 + * description : null + * allow_all_subjects : true + * box_heartbeat : 1533806262 + * network_switcher : + * camera_name : + * camera_status : 0 + * allow_visitor : true + * screen_token : 3c566c3f-6d7f-437a-af56-8ba4a7852745 + * network_switcher_token : null + * box_status : 0 + * network_switcher_drive : 0 + * type : 1 + * id : 1 + * camera_position : 测试 + * box_address : 192.168.1.50 + */ + + private String camera_address; + private Object network_switcher_status; + private String box_token; + private Object description; + private boolean allow_all_subjects; + private int box_heartbeat; + private String network_switcher; + private String camera_name; + private int camera_status; + private boolean allow_visitor; + private String screen_token; + private Object network_switcher_token; + private String box_status; + private int network_switcher_drive; + private int type; + private int id; + private String camera_position; + private String box_address; + private List allowed_subject_ids; + + public String getCamera_address() { + return camera_address; + } + + public void setCamera_address(String camera_address) { + this.camera_address = camera_address; + } + + public Object getNetwork_switcher_status() { + return network_switcher_status; + } + + public void setNetwork_switcher_status(Object network_switcher_status) { + this.network_switcher_status = network_switcher_status; + } + + public String getBox_token() { + return box_token; + } + + public void setBox_token(String box_token) { + this.box_token = box_token; + } + + public Object getDescription() { + return description; + } + + public void setDescription(Object description) { + this.description = description; + } + + public boolean isAllow_all_subjects() { + return allow_all_subjects; + } + + public void setAllow_all_subjects(boolean allow_all_subjects) { + this.allow_all_subjects = allow_all_subjects; + } + + public int getBox_heartbeat() { + return box_heartbeat; + } + + public void setBox_heartbeat(int box_heartbeat) { + this.box_heartbeat = box_heartbeat; + } + + public String getNetwork_switcher() { + return network_switcher; + } + + public void setNetwork_switcher(String network_switcher) { + this.network_switcher = network_switcher; + } + + public String getCamera_name() { + return camera_name; + } + + public void setCamera_name(String camera_name) { + this.camera_name = camera_name; + } + + public int getCamera_status() { + return camera_status; + } + + public void setCamera_status(int camera_status) { + this.camera_status = camera_status; + } + + public boolean isAllow_visitor() { + return allow_visitor; + } + + public void setAllow_visitor(boolean allow_visitor) { + this.allow_visitor = allow_visitor; + } + + public String getScreen_token() { + return screen_token; + } + + public void setScreen_token(String screen_token) { + this.screen_token = screen_token; + } + + public Object getNetwork_switcher_token() { + return network_switcher_token; + } + + public void setNetwork_switcher_token(Object network_switcher_token) { + this.network_switcher_token = network_switcher_token; + } + + public String getBox_status() { + return box_status; + } + + public void setBox_status(String box_status) { + this.box_status = box_status; + } + + public int getNetwork_switcher_drive() { + return network_switcher_drive; + } + + public void setNetwork_switcher_drive(int network_switcher_drive) { + this.network_switcher_drive = network_switcher_drive; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getCamera_position() { + return camera_position; + } + + public void setCamera_position(String camera_position) { + this.camera_position = camera_position; + } + + public String getBox_address() { + return box_address; + } + + public void setBox_address(String box_address) { + this.box_address = box_address; + } + + public List getAllowed_subject_ids() { + return allowed_subject_ids; + } + + public void setAllowed_subject_ids(List allowed_subject_ids) { + this.allowed_subject_ids = allowed_subject_ids; + } + } + + public static class PersonBeanX { + /** + * src : data:image/jpeg;base64,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 + * remark : + * subject_type : 0 + * description : + * inviter_id : null + * timestamp : 1533808724 + * start_time : 0 + * title : + * interviewee : + * job_number : + * entry_date : null + * origin_photo_id : 3 + * birthday : null + * avatar : /static/upload/photo/2018-08-09/v2_cec2cd5140b55db4051d9c69775ec6ebaea5947b.jpg + * department : + * end_time : 0 + * interviewee_pinyin : + * id : 5 + * name : ndy + */ + + private String src; + private String remark; + private int subject_type; + private String description; + private Object inviter_id; + private int timestamp; + private int start_time; + private String title; + private String interviewee; + private String job_number; + private Object entry_date; + private int origin_photo_id; + private Object birthday; + private String avatar; + private String department; + private int end_time; + private String interviewee_pinyin; + private int id; + private String name; + + public String getSrc() { + return src; + } + + public void setSrc(String src) { + this.src = src; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public int getSubject_type() { + return subject_type; + } + + public void setSubject_type(int subject_type) { + this.subject_type = subject_type; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Object getInviter_id() { + return inviter_id; + } + + public void setInviter_id(Object inviter_id) { + this.inviter_id = inviter_id; + } + + public int getTimestamp() { + return timestamp; + } + + public void setTimestamp(int timestamp) { + this.timestamp = timestamp; + } + + public int getStart_time() { + return start_time; + } + + public void setStart_time(int start_time) { + this.start_time = start_time; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getInterviewee() { + return interviewee; + } + + public void setInterviewee(String interviewee) { + this.interviewee = interviewee; + } + + public String getJob_number() { + return job_number; + } + + public void setJob_number(String job_number) { + this.job_number = job_number; + } + + public Object getEntry_date() { + return entry_date; + } + + public void setEntry_date(Object entry_date) { + this.entry_date = entry_date; + } + + public int getOrigin_photo_id() { + return origin_photo_id; + } + + public void setOrigin_photo_id(int origin_photo_id) { + this.origin_photo_id = origin_photo_id; + } + + public Object getBirthday() { + return birthday; + } + + public void setBirthday(Object birthday) { + this.birthday = birthday; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } + + public int getEnd_time() { + return end_time; + } + + public void setEnd_time(int end_time) { + this.end_time = end_time; + } + + public String getInterviewee_pinyin() { + return interviewee_pinyin; + } + + public void setInterviewee_pinyin(String interviewee_pinyin) { + this.interviewee_pinyin = interviewee_pinyin; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/HeartBeat.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/HeartBeat.java new file mode 100644 index 0000000..d460272 --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/HeartBeat.java @@ -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; + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/JsonMapper.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/JsonMapper.java new file mode 100644 index 0000000..4761ddb --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/JsonMapper.java @@ -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. + *

+ * 如果JSON字符串为Null或"null"字符串, 返回Null. 如果JSON字符串为"[]", 返回空集合. + *

+ * 如需反序列化复杂Collection如List, 请使用fromJson(String, JavaType) + */ + public static T fromJson(String jsonValue, Class clazz) { + return gson.fromJson(jsonValue, clazz); + } + + public static T fromJson(String jsonValue, Type type) { + return gson.fromJson(jsonValue, type); + } + + public static List fromJson(String jsonValue) { + return gson.fromJson(jsonValue, new TypeToken>() { + }.getType()); + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/MemberDto.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/MemberDto.java new file mode 100644 index 0000000..97044af --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/MemberDto.java @@ -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; + } +} diff --git a/netty-pad/src/main/test/java/test/netty/nio/net/dto/Message.java b/netty-pad/src/main/test/java/test/netty/nio/net/dto/Message.java new file mode 100644 index 0000000..351ffaf --- /dev/null +++ b/netty-pad/src/main/test/java/test/netty/nio/net/dto/Message.java @@ -0,0 +1,68 @@ +package test.netty.nio.net.dto; + +import com.google.gson.annotations.Expose; + +/** + *

上位机与通讯服务器的数据协议格式
+ * + * @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; + } + +} diff --git a/oms/build.gradle b/oms/build.gradle index 443f083..48137e2 100644 --- a/oms/build.gradle +++ b/oms/build.gradle @@ -1,4 +1,4 @@ -group 'SmartVenue' +group 'smartvenue' version '1.0.0' ext { springBootVersion = '1.5.7.RELEASE' diff --git a/service/build.gradle b/service/build.gradle index 534fd92..cd199db 100644 --- a/service/build.gradle +++ b/service/build.gradle @@ -1,4 +1,4 @@ -group 'SmartVenue' +group 'smartvenue' version '1.0.0' ext { springBootVersion = '1.5.7.RELEASE' diff --git a/service/src/main/java/com/sv/service/api/VenueService.java b/service/src/main/java/com/sv/service/api/VenueService.java index 5d4f3a5..1ae72f3 100644 --- a/service/src/main/java/com/sv/service/api/VenueService.java +++ b/service/src/main/java/com/sv/service/api/VenueService.java @@ -2,6 +2,7 @@ package com.sv.service.api; import com.enums.*; import com.github.pagehelper.PageHelper; +import com.sv.dto.EnterResult; import com.sv.dto.api.MemberCardDTO; import com.sv.dto.api.MemberCardVenuesDTO; import com.sv.dto.api.VenueDTO; @@ -305,103 +306,103 @@ public class VenueService extends BaseServiceImpl { * @param deviceId * @return 0成功 -1失败 */ -// @Transactional(rollbackFor = Exception.class) -// public synchronized EnterResult enterVenue(Integer faceId, Integer deviceId) { -// EnterResult result = new EnterResult(); -// synchronized (("enter" + faceId.toString()).intern()) { -// Date now = new Date(); -// Device device = deviceService.findById(deviceId); -// Venue venue = venueMapper.findById(device.getVenueId()); -// // 查询当前时间内,场馆对应的价格 -// String time = DateUtilCard.nowTime().toString(); -// VenuePrice venuePrice = venuePriceService.findPrice(device.getVenueId(), time); -// if (venuePrice == null) { -// logger.info("场馆暂未开放"); -// result.setStatus(-2); -// return result; -// } -// if (venue.getStatus().intValue() == 1) { -// logger.info(venue.getName() + "被禁用,入场失败"); -// result.setStatus(-2); -// return result; -// } -// Member member = memberService.findByFaceId(faceId); -// memberService.verify(member); -// if (venue == null || member == null) { -// result.setStatus(-1); -// return result; -// } -// //判断8小时之内 是否连续进场 -// MemberEnterVenueLog enterVenueLog = memberEnterVenueLogService.findMemberLastLog(member.getId(), device.getVenueId()); -// MemberEnterVenueLog log = new MemberEnterVenueLog(); -// log.setMemberId(member.getId()); -// log.setVeneuType(device.getVenueType()); -// log.setVenueId(device.getVenueId()); -// log.setPlatformId(member.getPlatformId()); -// if (enterVenueLog != null) { -// if ((now.getTime() - enterVenueLog.getCreatedTime().getTime()) <= (8 * 60 * 60 * 1000)) { -// //小于8小时直接进场 -// log.setOrderSn(""); -// logger.info("用户:" + member.getNickname() + "小于8小时直接进场"); -// memberEnterVenueLogService.save(log); -// result.setStatus(0); -// return result; -// } -// } -// //进场之前 查看是否有会员卡 -// List cards = memberCardService.findByMemberId(device.getVenueId(), member.getId()); -// if (cards.size() > 0) { -// //有会员卡 查看是否是免费卡 【// 发现这里的逻辑不是优先使用免费卡】 -// MemberCard useCard = null; -// for (MemberCard card : cards) { -// if (!VipTypeEnum.FREECARD.value.equals(card.getCardType())) { -// useCard = card; -// break; -// } else { -// //查看该免费卡是否可用 (一天用一次) -// if (memberEnterVenueLogService.isFreeCardUseful(card.getId())) { -// useCard = card; -// break; -// } -// } -// } -// if (useCard != null) { -// //使用会员卡入场 -// logger.info("用户" + member.getNickname() + "使用" + useCard.getCardType() + "入场"); -// log.setMemberCardId(useCard.getId()); -// log.setPayType(EnterVenuePayTypeEnum.MEMBER_CARD.value); -// String orderSn = orderService.createEnterVenueOrder(venue, member.getId(), PayTypeEnum.MEMBER_CARD, venuePrice.getPrice()); -// // 会员卡入场,增加记录 -// createMemberMoneyLog(MoneyLogEnum.JOIN.value, venue.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.MEMBER_CARD.value, useCard.getCardType(), -// venue.getId(), venue.getType()); -// log.setOrderSn(orderSn); -// memberEnterVenueLogService.save(log); -// result.setStatus(1); -// return result; -// } -// } -// //没有会员卡 扣余额 -// //判断余额是否够 -// if (memberService.isMoneyEnough(member.getId(), venuePrice.getPrice())) { -// logger.info("用户" + member.getNickname() + "使用余额进场"); -// result.setMoney(venuePrice.getPrice()); -// String orderSn = orderService.createEnterVenueOrder(venue, member.getId(), PayTypeEnum.BALANCE, venuePrice.getPrice()); -// log.setOrderSn(orderSn); -// log.setPayType(EnterVenuePayTypeEnum.WEI_XIN.value); -// memberEnterVenueLogService.save(log); -// result.setStatus(2); -// return result; -// } else { -// //余额不足 -// logger.info("用户" + member.getNickname() + "余额不足进场失败"); -// result.setStatus(-2); -// return result; -// } -// } -// } + @Transactional(rollbackFor = Exception.class) + public synchronized EnterResult enterVenue(Integer faceId, Integer deviceId) { + EnterResult result = new EnterResult(); + synchronized (("enter" + faceId.toString()).intern()) { + Date now = new Date(); + Device device = deviceService.findById(deviceId); + Venue venue = venueMapper.findById(device.getVenueId()); + // 查询当前时间内,场馆对应的价格 + String time = DateUtilCard.nowTime().toString(); + VenuePrice venuePrice = venuePriceService.findPrice(device.getVenueId(), time); + if (venuePrice == null) { + logger.info("场馆暂未开放"); + result.setStatus(-2); + return result; + } + if (venue.getStatus().intValue() == 1) { + logger.info(venue.getName() + "被禁用,入场失败"); + result.setStatus(-2); + return result; + } + Member member = memberService.findByFaceId(faceId); + memberService.verify(member); + if (venue == null || member == null) { + result.setStatus(-1); + return result; + } + //判断8小时之内 是否连续进场 + MemberEnterVenueLog enterVenueLog = memberEnterVenueLogService.findMemberLastLog(member.getId(), device.getVenueId()); + MemberEnterVenueLog log = new MemberEnterVenueLog(); + log.setMemberId(member.getId()); + log.setVeneuType(device.getVenueType()); + log.setVenueId(device.getVenueId()); + log.setPlatformId(member.getPlatformId()); + if (enterVenueLog != null) { + if ((now.getTime() - enterVenueLog.getCreatedTime().getTime()) <= (8 * 60 * 60 * 1000)) { + //小于8小时直接进场 + log.setOrderSn(""); + logger.info("用户:" + member.getNickname() + "小于8小时直接进场"); + memberEnterVenueLogService.save(log); + result.setStatus(0); + return result; + } + } + //进场之前 查看是否有会员卡 + List cards = memberCardService.findByMemberId(device.getVenueId(), member.getId()); + if (cards.size() > 0) { + //有会员卡 查看是否是免费卡 【// 发现这里的逻辑不是优先使用免费卡】 + MemberCard useCard = null; + for (MemberCard card : cards) { + if (!VipTypeEnum.FREECARD.value.equals(card.getCardType())) { + useCard = card; + break; + } else { + //查看该免费卡是否可用 (一天用一次) + if (memberEnterVenueLogService.isFreeCardUseful(card.getId())) { + useCard = card; + break; + } + } + } + if (useCard != null) { + //使用会员卡入场 + logger.info("用户" + member.getNickname() + "使用" + useCard.getCardType() + "入场"); + log.setMemberCardId(useCard.getId()); + log.setPayType(EnterVenuePayTypeEnum.MEMBER_CARD.value); + String orderSn = orderService.createEnterVenueOrder(venue, member.getId(), PayTypeEnum.MEMBER_CARD, venuePrice.getPrice()); + // 会员卡入场,增加记录 + createMemberMoneyLog(MoneyLogEnum.JOIN.value, venue.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.MEMBER_CARD.value, useCard.getCardType(), + venue.getId(), venue.getType()); + log.setOrderSn(orderSn); + memberEnterVenueLogService.save(log); + result.setStatus(1); + return result; + } + } + //没有会员卡 扣余额 + //判断余额是否够 + if (memberService.isMoneyEnough(member.getId(), venuePrice.getPrice())) { + logger.info("用户" + member.getNickname() + "使用余额进场"); + result.setMoney(venuePrice.getPrice()); + String orderSn = orderService.createEnterVenueOrder(venue, member.getId(), PayTypeEnum.BALANCE, venuePrice.getPrice()); + log.setOrderSn(orderSn); + log.setPayType(EnterVenuePayTypeEnum.WEI_XIN.value); + memberEnterVenueLogService.save(log); + result.setStatus(2); + return result; + } else { + //余额不足 + logger.info("用户" + member.getNickname() + "余额不足进场失败"); + result.setStatus(-2); + return result; + } + } + } /** - * 是否可以成功入场 + * 二维码入场-判断是否成功入场 * * @return 0成功 -1失败 */ diff --git a/settings.gradle b/settings.gradle index f5b5ee3..847f405 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,6 @@ -rootProject.name = 'SmartVenue' +rootProject.name = 'smartvenue' include 'service' include 'api' include 'oms' -include 'entity' \ No newline at end of file +include 'entity' +include 'netty-pad'