netty-删除无用的device-socket module

This commit is contained in:
limqhz
2020-07-09 18:08:12 +08:00
parent bb44cfc7eb
commit 53ee0f922f
30 changed files with 81 additions and 1123 deletions

View File

@@ -1,46 +0,0 @@
group 'SmartVenue'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
sourceCompatibility = 1.8
buildscript {
repositories {
//mavenCentral()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.4.RELEASE")
}
}
repositories {
//mavenCentral()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
jar {
baseName = 'sv-socket'
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile project(':service')
compile fileTree(include: '*.jar', dir: 'src/libs')
compile 'mysql:mysql-connector-java:6.0.6'
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'

Binary file not shown.

View File

@@ -1,32 +0,0 @@
package com;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 项目入口
*
* @author xingkong1221
* @since 2017-06-19
*/
@SpringBootApplication
@EnableAutoConfiguration
@EnableScheduling
@EnableAsync
@MapperScan(value = {"com.sv.mapper"})
public class Application {
/**
* 启动项目
*
* @param args 启动参数
*/
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -1,58 +0,0 @@
package com.sv.socket;
import com.common.DeviceDTO;
import com.enums.DeviceStatusEnum;
import com.sv.entity.Device;
import com.sv.service.oms.DeviceService;
import com.ydd.framework.core.common.dto.ResponseDTO;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
@RestController
public class DeviceController {
@Value("${face.url}")
private String faceUrl;
@Resource
private ApplicationContext applicationContext;
@Resource
private DeviceService deviceService;
@RequestMapping("/device/reconnect/{id}")
public ResponseDTO reconnect(@PathVariable("id") Integer deviceId) {
Device device = deviceService.findById(deviceId);
synchronized (device.getStream().intern()) {
if (device != null && DeviceStatusEnum.OFFLINE.value.equals(device.getStatus())) {
deviceService.reconnect(deviceId);
try {
DeviceDTO deviceDTO = new DeviceDTO();
BeanUtils.copyProperties(device, deviceDTO);
URI uri = new URI("ws://" + faceUrl + "/video?url=" + URLEncoder.encode(device.getStream(), "utf-8"));
DeviceSocket client = new DeviceSocket(applicationContext, deviceDTO, uri);
client.connectBlocking();
} catch (Exception e) {
e.printStackTrace();
deviceService.offline(deviceId);
}
}
return ResponseDTO.ok();
}
}
}

View File

@@ -1,78 +0,0 @@
package com.sv.socket;
import com.common.DeviceDTO;
import com.sv.entity.Device;
import com.sv.socket.event.SocketConnectEvent;
import com.sv.socket.event.SocketMessageEvent;
import com.sv.socket.event.SocketReconnectEvent;
import com.ydd.framework.core.common.utils.ValidationUtils;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import javax.annotation.Resource;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
/**
* 设备连接
*/
public class DeviceSocket extends WebSocketClient {
private final Logger logger = LoggerFactory.getLogger(DeviceSocket.class);
private DeviceDTO device;
private CountDownLatch countDownLatch;
@Resource
private ApplicationContext applicationContext;
public DeviceSocket(ApplicationContext applicationContext, DeviceDTO device, URI serverUri) {
super(serverUri);
ValidationUtils.assertNotNull(device);
this.device = device;
this.applicationContext = applicationContext;
countDownLatch = new CountDownLatch(1);
}
@Override
public void onOpen(ServerHandshake handshakedata) {
applicationContext.publishEvent(new SocketConnectEvent(device, countDownLatch, DeviceSocket.this));
}
@Override
public void onMessage(String message) {
logger.info("收到设备" + device.getName() + "消息:" + message);
applicationContext.publishEvent(new SocketMessageEvent(message, device));
}
@Override
public void onClose(int code, String reason, boolean remote) {
logger.info("设备【{}】断开连接code:【{}】,reason:【{}】", device.getStream(), code, reason);
SocketConnections.sockets.remove(device.getStream());
countDownLatch.countDown();
if (device.getLastCloseTime() == null)
device.setLastCloseTime(System.currentTimeMillis());
applicationContext.publishEvent(new SocketReconnectEvent(device));
}
@Override
public void onError(Exception ex) {
SocketConnections.sockets.remove(device.getStream());
}
public DeviceDTO getDevice() {
return device;
}
public String getStreamName() {
return device.getStream();
}
}

View File

@@ -1,31 +0,0 @@
package com.sv.socket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* @author zhaoziyu
* @date 2018-11-12
* http请求工具配置
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
return restTemplate;
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(30000);
factory.setConnectTimeout(30000);
return factory;
}
}

View File

@@ -1,12 +0,0 @@
package com.sv.socket;
import com.google.common.collect.Maps;
import java.util.concurrent.ConcurrentMap;
public class SocketConnections {
public static final ConcurrentMap<String, DeviceSocket> sockets = Maps.newConcurrentMap();
}

View File

@@ -1,51 +0,0 @@
package com.sv.socket;
import com.common.DeviceDTO;
import com.sv.entity.Device;
import com.sv.service.api.AboutUsService;
import com.sv.service.oms.DeviceService;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.net.URI;
import java.net.URLEncoder;
import java.util.List;
@Component
public class SocketStarter implements CommandLineRunner {
private final Logger logger = LoggerFactory.getLogger(SocketStarter.class);
@Resource
private DeviceService deviceService;
@Value("${face.url}")
private String faceUrl;
@Resource
private ApplicationContext applicationContext;
@Override
public void run(String... args) throws Exception {
logger.info("开始连接设备socket");
List<DeviceDTO> devices = deviceService.findAll();
if (devices != null && devices.size() > 0) {
for(DeviceDTO device : devices){
if(SocketConnections.sockets.get(device.getStream()) != null)
continue;
URI uri = new URI( "ws://"+faceUrl+":9000/video?url="+ URLEncoder.encode(device.getStream(),"utf-8"));
DeviceSocket client = new DeviceSocket(applicationContext,device,uri);
client.connectBlocking();
}
}
logger.info("连接设备完毕!");
}
}

View File

@@ -1,51 +0,0 @@
package com.sv.socket.event;
import com.common.DeviceDTO;
import com.sv.entity.Device;
import com.sv.socket.DeviceSocket;
import org.springframework.context.ApplicationEvent;
import java.io.Serializable;
import java.util.concurrent.CountDownLatch;
public class SocketConnectEvent extends ApplicationEvent implements Serializable {
private DeviceDTO device;
private CountDownLatch countDownLatch;
private DeviceSocket deviceSocket;
/**
* Create a new ApplicationEvent.
*
* @param device the object on which the event initially occurred (never {@code null})
*/
public SocketConnectEvent(DeviceDTO device,CountDownLatch countDownLatch,DeviceSocket deviceSocket) {
super(device);
this.device = device;
this.countDownLatch = countDownLatch;
this.deviceSocket = deviceSocket;
}
public DeviceDTO getDevice() {
return device;
}
public CountDownLatch getCountDownLatch() {
return countDownLatch;
}
public void setCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
public DeviceSocket getDeviceSocket() {
return deviceSocket;
}
public void setDeviceSocket(DeviceSocket deviceSocket) {
this.deviceSocket = deviceSocket;
}
}

View File

@@ -1,43 +0,0 @@
package com.sv.socket.event;
import com.common.DeviceDTO;
import com.sv.entity.Device;
import com.sv.service.oms.DeviceService;
import com.sv.socket.DeviceSocket;
import com.sv.socket.SocketConnections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Component
public class SocketConnectListener implements ApplicationListener<SocketConnectEvent> {
private final Logger logger = LoggerFactory.getLogger(SocketConnectListener.class);
@Resource
private DeviceService deviceService;
@Override
@Async
public void onApplicationEvent(SocketConnectEvent event) {
boolean flag = false;
try {
//等待三秒 如果断开连接了 则表示没有连接成功
flag = event.getCountDownLatch().await(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!flag) {
DeviceDTO device = event.getDevice();
SocketConnections.sockets.put(device.getStream(),event.getDeviceSocket());
device.setLastCloseTime(null);
logger.info("设备【{}】连接成功", device.getStream());
deviceService.online(device.getId());
}
}
}

View File

@@ -1,38 +0,0 @@
package com.sv.socket.event;
import com.common.DeviceDTO;
import com.sv.entity.Device;
import org.springframework.context.ApplicationEvent;
import java.io.Serializable;
public class SocketMessageEvent extends ApplicationEvent implements Serializable {
private String message;
private DeviceDTO device;
/**
* Create a new ApplicationEvent.
*
* @param message the object on which the event initially occurred (never {@code null})
*/
public SocketMessageEvent(String message,DeviceDTO device) {
super(message);
this.message = message;
this.device = device;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public DeviceDTO getDevice() {
return device;
}
}

View File

@@ -1,164 +0,0 @@
package com.sv.socket.event;
import Net.PC15.Command.CommandDetial;
import Net.PC15.Connector.ConnectorAllocator;
import Net.PC15.Connector.E_ControllerType;
import Net.PC15.Connector.TCPClient.TCPClientDetial;
import Net.PC15.FC8800.Command.Door.CloseDoor;
import Net.PC15.FC8800.Command.Door.OpenDoor;
import Net.PC15.FC8800.Command.Door.Parameter.OpenDoor_Parameter;
import Net.PC15.FC8800.Command.Door.Parameter.RemoteDoor_Parameter;
import Net.PC15.FC8800.FC8800Identity;
import com.enums.FaceRecognizeEnum;
import com.sv.dto.api.MemberMessageDto;
import com.sv.entity.Device;
import com.sv.entity.Member;
import com.sv.entity.MemberEnterVenueLog;
import com.sv.entity.face.FaceRecognizeResponse;
import com.sv.service.api.MemberEnterVenueLogService;
import com.sv.service.api.MemberService;
import com.sv.service.api.VenueService;
import com.sv.service.common.FaceService;
import com.sv.socket.DeviceSocket;
import com.ydd.framework.core.common.dto.ResponseDTO;
import com.ydd.framework.core.common.utils.JsonMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.Date;
@Component
public class SocketMessageListener implements ApplicationListener<SocketMessageEvent> {
@Resource
private MemberEnterVenueLogService memberEnterVenueLogService;
@Resource
private MemberService memberService;
@Resource
private VenueService venueService;
private final Logger logger = LoggerFactory.getLogger(SocketMessageListener.class);
@Value("${door.ip}")
private String ip;
@Value("${door.port}")
private Integer port;
@Value("${door.sn}")
private String sn;
@Value("${door.pwd}")
private String pwd;
@Value("${nettym.url}")
private String url;
@Resource
private RestTemplate restTemplate;
@Async
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized void onApplicationEvent(SocketMessageEvent event) {
Device device = event.getDevice();
FaceRecognizeResponse response = JsonMapper.nonNullMapper().fromJson(event.getMessage(), FaceRecognizeResponse.class);
if (FaceRecognizeEnum.RECOGNIZED.name.equals(response.getType())) {
//识别成功
if (response.getPerson() != null) {
if (device.getId() == 1) {
//进门
enter(device, response);
} else if (device.getId() == 2) {
//出门
out(device, response);
}
}
}
}
public void enter(Device device, FaceRecognizeResponse response) {
try {
int code = 1;
Member member = memberService.findByFaceId(response.getPerson().getId());
if (member != null) {
//最后进场记录
MemberEnterVenueLog enterVenueLog = memberEnterVenueLogService.findMemberLastLog(member.getId(), device.getVenueId());
if (enterVenueLog != null) {
//有记录 查看 最后一次是否是出场
if (enterVenueLog.getType() == 1) {
//是出场 不用限制
} else {
//是进场 判断上次进场距离现在多久
Date date = new Date();
if (memberEnterVenueLogService.countEnterByDate(member.getId(), device.getVenueId(), date) < 2) {
//当天没有过 第二次的连续入场
} else {
//入场失败
code = -1;
}
}
}
MemberMessageDto memberMessageDto = new MemberMessageDto();
memberMessageDto.setAmount(member.getMoney());
memberMessageDto.setName(member.getName());
memberMessageDto.setAvatar(member.getAvatar());
memberMessageDto.setMobile(member.getMobile());
memberMessageDto.setPlaceName("");
if (code > 0) {
int status = venueService.enterVenue(response.getPerson().getId(), device.getId()).getStatus();
if (status >= 0) {
memberMessageDto.setCode(1);
if (status == 1) {
memberMessageDto.setCardName("会员卡");
}
logger.info(member.getId() + "入场成功:" + member.getMoney().toString());
} else {
logger.info(member.getId() + "入场失败:" + member.getMoney().toString());
memberMessageDto.setCode(0);
}
} else {
logger.info(member.getId() + "入场失败:连续入场");
memberMessageDto.setCode(0);
}
// HttpHeaders headers = new HttpHeaders();
// MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
// headers.setContentType(type);
// HttpEntity<String> jsonEntity = new HttpEntity<>(JsonMapper.nonNullMapper().toJson(memberMessageDto), headers);
// restTemplate.postForObject(url, jsonEntity, ResponseDTO.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void out(Device device, FaceRecognizeResponse response) {
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() + "出场");
}
}
}

View File

@@ -1,27 +0,0 @@
package com.sv.socket.event;
import com.common.DeviceDTO;
import com.sv.entity.Device;
import org.springframework.context.ApplicationEvent;
import java.io.Serializable;
public class SocketReconnectEvent extends ApplicationEvent implements Serializable{
private DeviceDTO device;
/**
* Create a new ApplicationEvent.
*
* @param device the object on which the event initially occurred (never {@code null})
*/
public SocketReconnectEvent(DeviceDTO device) {
super(device);
this.device = device;
}
public DeviceDTO getDevice() {
return device;
}
}

View File

@@ -1,66 +0,0 @@
package com.sv.socket.event;
import com.common.DeviceDTO;
import com.sv.entity.Device;
import com.sv.service.oms.DeviceService;
import com.sv.socket.DeviceSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
@Component
public class SocketReconnectListener implements ApplicationListener<SocketReconnectEvent> {
private final Logger logger = LoggerFactory.getLogger(SocketReconnectListener.class);
@Value("${face.url}")
private String faceUrl;
@Resource
private ApplicationContext applicationContext;
@Resource
private DeviceService deviceService;
@Async
@Override
public void onApplicationEvent(SocketReconnectEvent event) {
Long current = System.currentTimeMillis();
if(current - event.getDevice().getLastCloseTime() > (1000 * 60)){
//重新连接超过一分钟 timeout
logger.info("设备【{}】重新连接超时",event.getDevice().getStream());
deviceService.offline(event.getDevice().getId());
event.getDevice().setLastCloseTime(null);
return;
}
DeviceDTO device = event.getDevice();
logger.info("设备【{}】开始重新连接",device.getStream());
deviceService.setReconnect(device.getId());
if(device != null){
URI uri = null;
try {
uri = new URI( "ws://"+faceUrl+":9000/video?url="+ URLEncoder.encode(device.getStream(),"utf-8"));
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
DeviceSocket client = new DeviceSocket(applicationContext,device,uri);
try {
client.connectBlocking();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -1,23 +0,0 @@
spring:
datasource:
url: jdbc:mysql://yingdiandian.mysql.rds.aliyuncs.com:3306/smart_venue?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&useAffectedRows=true
username: yingdd
password: Yingdd2015
redis:
host: 47.96.15.192
password:
timeout: 6000
port: 6379
jpa:
show-sql: true
nettym:
url: http://192.168.1.200:8021/netty/message/send
door:
ip: 192.168.1.150
port: 8000
sn: MC-5824T28085603
pwd: FFFFFFFF

View File

@@ -1,23 +0,0 @@
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
redis:
host: 127.0.0.1
password:
timeout: 6000
port: 6379
jpa:
show-sql: true
nettym:
url: http://127.0.0.1:8021/netty/message/send
door:
ip: 192.168.1.150
port: 8000
sn: MC-5824T28085603
pwd: FFFFFFFF

View File

@@ -1,13 +0,0 @@
spring:
datasource:
url: jdbc:mysql://yingdiandian.mysql.rds.aliyuncs.com:3306/smart_venue?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8
username: yingdd
password: Yingdd2015
redis:
host: 121.41.101.63
password: yingdiandian2015
timeout: 6000
port: 6379
jpa:
show-sql: true

View File

@@ -1,83 +0,0 @@
server:
# port: 8093
port: 8000
debug: true
app:
accessToken:
expires: 7200
spring:
http:
multipart:
max-file-size: 40MB
max-request-size: 40MB
enabled: true
profiles:
include:
-development
-test
-production
active: development
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据库连接池配置
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
mvc:
log-resolved-exception: false
jackson:
default-property-inclusion: non_null
# MyBatis Configuration
mybatis:
type-aliases-package: com.ydd.oms.entity
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*/*.xml
oss:
accessKeyId: LTAIALhDnclBYATv
accessKeySecret: 4i9zJ5aDljBkFVRbp8pazK1l21XS79
protocol: http
name: yingdd
endPoint: http://oss-cn-hangzhou.aliyuncs.com
url: https://yingdd.oss-cn-hangzhou.aliyuncs.com/
face:
url: 192.168.1.111
account: test@test.com
pwd: 123456

View File

@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF8"?>
<configuration>
<jmxConfigurator />
<property name="LOG_HOME" value="/tmp/log/sv/device"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="webLogFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/api.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/api-sys.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="springLogFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/api-spring.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/api-spring-%d{yyyy-MM-dd_HH}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS},%msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="info" additivity="false">
<appender-ref ref="console" />
<appender-ref ref="webLogFile" />
</logger>
<root level="debug">
<appender-ref ref="console" />
</root>
<!-- root -->
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="webLogFile" />
</root>
</configuration>

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- <settings>
<setting name="cacheEnabled" value="true" />
&lt;!&ndash; 打印sql日志 &ndash;&gt;
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>-->
<!--<settings>-->
<!--<setting name="cacheEnabled" value="true"/>-->
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--<setting name="multipleResultSetsEnabled" value="true"/>-->
<!--<setting name="useColumnLabel" value="true"/>-->
<!--<setting name="useGeneratedKeys" value="false"/>-->
<!--<setting name="autoMappingBehavior" value="PARTIAL"/>-->
<!--<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>-->
<!--<setting name="defaultExecutorType" value="SIMPLE"/>-->
<!--<setting name="defaultStatementTimeout" value="25"/>-->
<!--<setting name="defaultFetchSize" value="100"/>-->
<!--<setting name="safeRowBoundsEnabled" value="false"/>-->
<!--<setting name="mapUnderscoreToCamelCase" value="false"/>-->
<!--<setting name="localCacheScope" value="SESSION"/>-->
<!--<setting name="jdbcTypeForNull" value="OTHER"/>-->
<!--<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>-->
<!--</settings>-->
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer" />
<typeAlias alias="Byte" type="java.lang.Byte"/>
<typeAlias alias="String" type="java.lang.String" />
<typeAlias alias="Long" type="java.lang.Long" />
<typeAlias alias="HashMap" type="java.util.HashMap" />
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
<typeAlias alias="ArrayList" type="java.util.ArrayList" />
<typeAlias alias="LinkedList" type="java.util.LinkedList" />
</typeAliases>
</configuration>

View File

@@ -1,86 +0,0 @@
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.channel.SimpleChannelInboundHandler;
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 SimpleChannelInboundHandler<String> {
private static Logger logger = LoggerFactory.getLogger(ClientHandler.class);
/**
* 当通道就绪就会触发
* @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 channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
super.channelRead(ctx, msg);
logger.info("接收服务器响应msg:[" + msg + "]");
// 安卓写非netty 后台实现
// TODO 安卓获取心跳内容有二维码的唯一识别显示请求小程序的venueId的二维码无需拼接url
// TODO 安卓获取通知加载页面
// TODO 安卓获取通知开门失败消息 (进入一个页面,然后显示倒计时,回到主页(二维码页面))
// TODO 安卓获取通知开门的消息 (无需校验,直接操作开门)
// Message message = JsonMapper.fromJson(msg, Message.class);
// MessageService.getInstance().execute(message);
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.ALL_IDLE) {
ctx.writeAndFlush("getHbMessage()");
}
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
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();
}
}
}

View File

@@ -18,18 +18,18 @@ import java.nio.charset.Charset;
* @Author peakren
* @Date 07/05/2017 10:43 PM
*/
public class MessageEncoder extends MessageToByteEncoder<String> {
public class MessageEncoder extends MessageToByteEncoder {
private static Logger logger = LoggerFactory.getLogger(MessageEncoder.class);
Charset charset = Charset.forName("UTF-8");
@Override
protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) throws Exception {
// String message = JsonUtils.encode(msg);
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
String message = JsonUtils.encode(msg);
logger.info("send message content:" + msg);
msg = msg + Constant.DELIMITER_WORD;
byte[] content = msg.getBytes(charset.name());
message = message + Constant.DELIMITER_WORD;
byte[] content = message.getBytes(charset.name());
out.writeBytes(content); //发送消息内容
}
}

View File

@@ -39,10 +39,9 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
super.channelRead(ctx, msg);
String clientIp = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getClientIp();
try {
messageService.receive(ctx.channel(), msg);
messageService.receive(clientIp,ctx.channel(), msg);
} catch (Exception e) {
logger.error("[" + clientIp + "] host unknown error");
}

View File

@@ -17,7 +17,7 @@ public interface MessageService {
* @param channel
* @param content
*/
void receive(Channel channel, String content);
void receive(String clientId, Channel channel, String content);
void online(Channel channel);

View File

@@ -47,9 +47,9 @@ public class TcpMessageHandlerAdapter implements MessageService {
private Logger logger = LoggerFactory.getLogger(TcpMessageHandlerAdapter.class);
@Value("${nettym.url}")
private String url;
//
// @Value("${nettym.url}")
// private String url;
@Resource
private MemberService memberService;
@@ -106,11 +106,11 @@ public class TcpMessageHandlerAdapter implements MessageService {
* @param content 消息内容
*/
@Override
public void receive(Channel channel, String content) {
public void receive(String clientId, Channel channel, String content) {
try {
//解析数据
Cmd cmd = resolveCmd(content);
logger.info("收到消息" + cmd.text);
logger.info("收到[" + clientId + "]消息" + cmd.text);
switch (cmd) {
case HB:
break;

View File

@@ -1,28 +0,0 @@
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;
}
}

View File

@@ -2,82 +2,68 @@ package com.test.netty.client;
import com.test.netty.client.message.Cmd;
import com.test.netty.client.message.HeartBeat;
import com.test.netty.client.message.Message;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import com.test.netty.client.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 通讯服务器请求处理
* 客户端处理
*
* @author peakren
* @date 05/12/2017 10:27 PM
* @author ranfi
*/
@ChannelHandler.Sharable
public class ClientHandler extends ChannelInboundHandlerAdapter {
public class ClientHandler extends SimpleChannelInboundHandler<String> {
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);
}
private static Logger logger = LoggerFactory.getLogger(ClientHandler.class);
/**
* 当通道就绪就会触发
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
//服务器连上以后立即模拟心跳返回
ctx.writeAndFlush(getHbMessage());
}
/**
* 当通道失效就会触发
* @param ctx
* @throws Exception
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
// GlobalConfig.isConnected =false;
ClientThread.getInstance().clearFuture();
ClientThread.getInstance().restart();
}
/**
* 当通道有读取事件时触发
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
// Message message = JsonMapper.fromJson(msg.toString(), Message.class);
public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
logger.info("接收服务器响应msg:[" + msg + "]");
// 安卓写非netty 后台实现
// TODO 安卓获取心跳内容有二维码的唯一识别显示请求小程序的venueId的二维码无需拼接url
// TODO 安卓获取通知加载页面
// TODO 安卓获取通知开门失败消息 (进入一个页面,然后显示倒计时,回到主页(二维码页面))
// TODO 安卓获取通知开门的消息 (无需校验,直接操作开门)
// Message message = JsonMapper.fromJson(msg, 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()));
hb.setVersionCode(System.currentTimeMillis()+"");
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) {
@@ -89,4 +75,32 @@ public class ClientHandler extends ChannelInboundHandlerAdapter {
}
}
/**
* 封装心跳请求包
* @throws Exception
*/
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 cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
logger.error("ClientHandler exceptionCaught",cause);
Channel channel = ctx.channel();
if(channel.isActive()) {
ctx.close();
}
}
}

View File

@@ -1,6 +1,5 @@
package com.test.netty.client;
import com.sv.netty.netty.MessageEncoder;
import com.test.netty.client.config.Constant;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
@@ -31,7 +30,6 @@ public class ClientInitializer extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("reconnect", reConnectHandler);
pipeline.addLast(new ReadTimeoutHandler(READ_TIMEOUT));
pipeline.addLast(new DelimiterBasedFrameDecoder(2048,
Unpooled.wrappedBuffer(Constant.DELIMITER_WORD.getBytes())));
pipeline.addLast(new StringDecoder());

View File

@@ -108,8 +108,7 @@ public class ClientThread extends Thread{
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("ReConnectHandler inactive");
ctx.channel().eventLoop().schedule(new Runnable() {
@Override

View File

@@ -1,6 +1,7 @@
package com.test.netty.client;
import com.sv.netty.config.Constant;
import com.sv.netty.utils.JsonUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
@@ -11,7 +12,7 @@ import java.nio.charset.Charset;
/**
* 自定义编码器, 1个字节固定头+4个字节长度+内容
*/
public class MessageEncoder extends MessageToByteEncoder<String> {
public class MessageEncoder extends MessageToByteEncoder {
Charset charset = Charset.forName("UTF-8");
/**
@@ -20,10 +21,10 @@ public class MessageEncoder extends MessageToByteEncoder<String> {
private final static String TAG = "MessageEncoder";
@Override
protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) throws Exception {
// Log.i(TAG, "send data:" + msg);
msg = msg + Constant.DELIMITER_WORD;
byte[] content = msg.getBytes(charset.name());
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
String message = JsonUtils.encode(msg);
message = message + Constant.DELIMITER_WORD;
byte[] content = message.getBytes(charset.name());
out.writeBytes(content); //发送消息内容
}
}