api-fixbug修改数据类型,fix存储links线程问题

This commit is contained in:
limqhz
2020-08-01 21:55:05 +08:00
parent 393ef2ddd5
commit b51398129e
13 changed files with 106 additions and 136 deletions

View File

@@ -1,49 +0,0 @@
package com.sv.netty.config;
import com.enums.DeviceType;
import io.netty.channel.Channel;
import io.netty.util.internal.PlatformDependent;
import java.util.concurrent.ConcurrentMap;
public class ClientChannelCache {
/**
* 存储设备通道类型
* 此处存储客户端的channel 信息key 为 【deviceId + venueId】
* value: 1Tcp 2WebSocket
*/
public static final ConcurrentMap<String, Channel> channel = PlatformDependent.newConcurrentHashMap();
/**
* 缓存通道
*/
public static void putChannelType(String deviceName, Integer venueId, DeviceType deviceType, Channel channel) {
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
ClientChannelCache.channel.put(clientId, channel);
}
/**
* 获取当前通道
*/
public static Channel getCurrentChannel(String deviceName, Integer venueId, DeviceType deviceType){
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
return channel.get(clientId);
}
/**
* 获取通道
*/
public static boolean contains(String deviceName, Integer venueId, DeviceType deviceType) {
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
return channel.containsKey(clientId);
}
/**
* 移除通道
*/
public static void removeChannelType(String deviceName, Integer venueId, DeviceType deviceType) {
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
channel.remove(clientId);
}
}

View File

@@ -34,7 +34,7 @@ public class Constant {
/**
* 哪些接口不需要增加 platform 平台限制
*/
public static final List<String> executeControllerList = Arrays.asList(new String [] {"/qrCode/init"});
public static final List<String> executeControllerList = Arrays.asList(new String [] {"/qrCode/init","/qrCode/enter"});
}

View File

@@ -5,7 +5,6 @@ import com.sv.dto.app.VenueLessonStatus;
import com.sv.entity.Venue;
import com.sv.service.api.VenueLessonService;
import com.sv.service.oms.VenueService;
import com.ydd.framework.core.common.dto.ResponseDTO;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

View File

@@ -1,10 +1,7 @@
package com.sv.netty.controller;
import com.enums.DeviceType;
import com.enums.VenueTypeEnum;
import com.sv.entity.Venue;
import com.sv.entity.VenueType;
import com.sv.netty.config.ClientChannelCache;
import com.sv.netty.config.Constant;
import com.sv.netty.netty.message.MessageDTO;
import com.sv.netty.netty.message.MessageType;
@@ -12,7 +9,6 @@ import com.sv.netty.netty.service.MessageService;
import com.sv.service.api.QRCodeService;
import com.ydd.framework.core.common.dto.ResponseDTO;
import com.ydd.framework.core.controller.BaseApiController;
import com.ydd.framework.core.exception.ServiceException;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,13 +38,12 @@ public class QREnterController extends BaseApiController {
DeviceType enterOrOut = getEnterOrOut(deviceId);
Venue venue = qrCodeService.initEnter(venueId, deviceName,enterOrOut);
if (venue!=null){
Channel channel = ClientChannelCache.getCurrentChannel(deviceName,venueId ,enterOrOut);
if (DeviceType.OUT == enterOrOut){
// 出场
messageService.outVenue(deviceName,venueId,memberId,venue,channel);
messageService.outVenue(deviceName,venueId,memberId,venue);
}else{
// 进场
messageService.enterVenue(deviceName,venueId,memberId,venue,channel);
messageService.enterVenue(deviceName,venueId,memberId,venue);
}
}
return ResponseDTO.ok();
@@ -65,8 +60,7 @@ public class QREnterController extends BaseApiController {
String deviceName = getDeviceName(deviceId);
DeviceType enterOrOut = getEnterOrOut(deviceId);
Venue venue = qrCodeService.initEnter(venueId, deviceName,enterOrOut);
Channel channel = ClientChannelCache.getCurrentChannel(deviceName,venueId ,enterOrOut);
messageService.sendLoading(channel,memberId);
messageService.sendLoading(deviceName,venueId ,enterOrOut,memberId);
return ResponseDTO.ok().addAttribute("venueInit", venue);
}
@@ -122,14 +116,11 @@ public class QREnterController extends BaseApiController {
*/
@RequestMapping("/checkAlive")
public ResponseDTO checkAlive(@RequestParam String id) {
System.out.println(ClientChannelCache.channel.size());
Integer venueId = getVenueId(id);
String deviceName = getDeviceName(id);
DeviceType enterOrOut = getEnterOrOut(id);
Channel channel = ClientChannelCache.getCurrentChannel(deviceName,venueId,enterOrOut);
logger.info("验证设备"+ id + "通讯情况");
MessageDTO messageDTO = new MessageDTO(MessageType.LOAD,"测试信息123");
channel.writeAndFlush(messageDTO);
messageService.testLoad(deviceName,venueId,enterOrOut);
return ResponseDTO.ok();
}

View File

@@ -54,7 +54,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
logger.info("客户端" + hb.getDeviceName() + "&" + hb.getVenueId() + "" + clientIp + "】上报心跳...");
ctx.channel().attr(Constant.CHANNEL_PARAM).get().setVenueId(hb.getVenueId());
ctx.channel().attr(Constant.CHANNEL_PARAM).get().setDeviceName(hb.getDeviceName());
ctx.channel().attr(Constant.CHANNEL_PARAM).get().setDeviceType(hb.getEnterOrOut());
ctx.channel().attr(Constant.CHANNEL_PARAM).get().setDeviceType(DeviceType.valueOf(hb.getDeviceType()));
messageService.online(clientIp,ctx.channel(), hb);
} catch (Exception e) {
logger.error("[" + clientIp + "] host unknown error",e);

View File

@@ -1,9 +1,6 @@
package com.sv.netty.netty.message;
import com.enums.DeviceType;
import java.io.Serializable;
/**
* 客户端心跳数据包
* HeartBeat.java
@@ -17,7 +14,7 @@ public class HeartBeat implements Serializable {
private String deviceName; //设备号
private DeviceType EnterOrOut; //出入标志
private String deviceType; //出入标志
public Integer getVenueId() {
return venueId;
@@ -35,11 +32,11 @@ public class HeartBeat implements Serializable {
this.deviceName = deviceName;
}
public DeviceType getEnterOrOut() {
return EnterOrOut;
public String getDeviceType() {
return deviceType;
}
public void setEnterOrOut(DeviceType enterOrOut) {
EnterOrOut = enterOrOut;
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

View File

@@ -37,7 +37,7 @@ public interface MessageService {
*/
Set<String> countConnection();
boolean sendLoading(Channel channel, Integer memberId);
boolean sendLoading(String deviceName, Integer venueId,DeviceType deviceType, Integer memberId);
/**
* 出场
@@ -46,7 +46,7 @@ public interface MessageService {
* @param memberId
* @param venue
*/
void outVenue(String deviceName, Integer venueId, Integer memberId, Venue venue,Channel channel);
void outVenue(String deviceName, Integer venueId, Integer memberId, Venue venue);
/**
* 进场
@@ -55,5 +55,7 @@ public interface MessageService {
* @param memberId
* @param venue
*/
void enterVenue(String deviceName, Integer venueId, Integer memberId, Venue venue,Channel channel);
void enterVenue(String deviceName, Integer venueId, Integer memberId, Venue venue);
void testLoad(String deviceName, Integer venueId,DeviceType deviceType);
}

View File

@@ -4,7 +4,7 @@ import com.enums.DeviceType;
import com.sv.entity.Member;
import com.sv.entity.MemberEnterVenueLog;
import com.sv.entity.Venue;
import com.sv.netty.config.ClientChannelCache;
import com.sv.netty.config.Constant;
import com.sv.netty.config.ErrorCode;
import com.sv.netty.netty.message.HeartBeat;
import com.sv.netty.netty.message.MessageDTO;
@@ -17,6 +17,7 @@ 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 io.netty.util.internal.PlatformDependent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@@ -25,6 +26,7 @@ import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -40,6 +42,13 @@ public class AppMessageHandlerAdapter implements MessageService {
private Logger logger = LoggerFactory.getLogger(AppMessageHandlerAdapter.class);
/**
* 存储设备通道类型
* 此处存储客户端的channel 信息key 为 【deviceId + venueId】
* value: 1Tcp 2WebSocket
*/
private ConcurrentMap<String, Channel> links = PlatformDependent.newConcurrentHashMap();
@Resource
private MemberService memberService;
@@ -69,15 +78,16 @@ public class AppMessageHandlerAdapter implements MessageService {
*/
@Override
public void online(String clientId, Channel channel, HeartBeat heartBeat) {
DeviceType deviceType = DeviceType.valueOf(heartBeat.getDeviceType());
// 处理心跳信息
if (!ClientChannelCache.contains(heartBeat.getDeviceName(),heartBeat.getVenueId(),heartBeat.getEnterOrOut())){
if (!contains(heartBeat.getDeviceName(),heartBeat.getVenueId(),deviceType)){
// 此处存储客户端的channel 信息key 为 deviceId + venueId
Venue thisVenue = venueService.findById(heartBeat.getVenueId());
if (thisVenue == null ){
logger.error("this client choose venue Error! venueId == " + heartBeat.getVenueId());
} else {
deviceService.online(heartBeat.getDeviceName(),heartBeat.getVenueId(),heartBeat.getEnterOrOut(),thisVenue.getType(),clientId);
ClientChannelCache.putChannelType(heartBeat.getDeviceName(),heartBeat.getVenueId(),heartBeat.getEnterOrOut(),channel);
deviceService.online(heartBeat.getDeviceName(),heartBeat.getVenueId(),deviceType,thisVenue.getType(),clientId);
putChannelType(heartBeat.getDeviceName(),heartBeat.getVenueId(),deviceType,channel);
}
}
}
@@ -90,40 +100,43 @@ public class AppMessageHandlerAdapter implements MessageService {
@Override
public void Offline(String deviceName, Integer venueId,DeviceType deviceType) {
if (deviceName != null && venueId != null){
ClientChannelCache.removeChannelType(deviceName,venueId,deviceType);
removeChannelType(deviceName,venueId,deviceType);
deviceService.offline(deviceName,venueId,deviceType);
}
}
/**
* 统计目前有多少链接数
* @return
*/
@Override
public Set<String> countConnection() {
return ClientChannelCache.channel.keySet();
}
/**
* 通知客户端进入加载页面
* @param memberId
* @return
*/
@Override
public boolean sendLoading(Channel channel, Integer memberId) {
public boolean sendLoading(String deviceName, Integer venueId,DeviceType deviceType, Integer memberId) {
Member thisMember = memberService.findByMember(memberId);
if (thisMember!=null){
String nickname = thisMember.getNickname();
MessageDTO messageDTO = new MessageDTO(MessageType.LOAD,"欢迎光临!" + nickname);
sendMessage(channel,messageDTO);
Channel currentChannel = getCurrentChannel(deviceName, venueId, deviceType);
sendMessage(currentChannel,messageDTO);
return true;
}
return false;
}
/**
* 测试客户端连接
* @return
*/
@Override
public void testLoad(String deviceName, Integer venueId,DeviceType deviceType) {
Channel currentChannel = getCurrentChannel(deviceName, venueId, deviceType);
currentChannel.writeAndFlush("Test Links" + deviceName + venueId + deviceType);
}
@Override
public void outVenue(String deviceName, Integer venueId, Integer memberId, Venue venue,Channel channel) {
public void outVenue(String deviceName, Integer venueId, Integer memberId, Venue venue) {
Channel channel = getCurrentChannel(deviceName,venueId,DeviceType.OUT);
Member member = memberService.findByMember(memberId);
if (member != null) {
//出场 不用判断直接出
@@ -164,9 +177,10 @@ public class AppMessageHandlerAdapter implements MessageService {
* @param venue
*/
@Override
public void enterVenue(String deviceName, Integer venueId, Integer memberId, Venue venue,Channel channel) {
public void enterVenue(String deviceName, Integer venueId, Integer memberId, Venue venue) {
Member member = memberService.findByMember(memberId);
// 校验入场时间是否正常
Channel channel = getCurrentChannel(deviceName, venueId, DeviceType.ENTER);
// 校验入场时间是否正常
if (checkInterval(member,venueId)) {
if(venueService.qrCodeEnterVenue(memberId,deviceName,venueId,venue)){
// 可以进场
@@ -250,4 +264,47 @@ public class AppMessageHandlerAdapter implements MessageService {
// logger.info("灯光结果" + JsonMapper.nonDefaultMapper().toJson(result));
}
/**
* 操作连接
*/
/**
* 缓存通道
*/
public void putChannelType(String deviceName, Integer venueId, DeviceType deviceType, Channel channel) {
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
links.put(clientId, channel);
}
/**
* 获取当前通道
*/
public Channel getCurrentChannel(String deviceName, Integer venueId, DeviceType deviceType){
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
return links.get(clientId);
}
/**
* 获取通道
*/
public boolean contains(String deviceName, Integer venueId, DeviceType deviceType) {
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
return links.containsKey(clientId);
}
/**
* 移除通道
*/
public void removeChannelType(String deviceName, Integer venueId, DeviceType deviceType) {
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD + deviceType;
links.remove(clientId);
}
/**
* 统计目前有多少链接数
* @return
*/
@Override
public Set<String> countConnection() {
return links.keySet();
}
}

View File

@@ -1,7 +1,6 @@
package com.test.netty.client;
import com.sv.netty.utils.JsonUtils;
import com.test.netty.client.message.DeviceType;
import com.test.netty.client.message.HeartBeat;
import com.test.netty.client.message.MessageDTO;
import io.netty.channel.Channel;
@@ -92,7 +91,7 @@ public class ClientHandler extends SimpleChannelInboundHandler<String> {
// hb.setDeviceName("DeviceIdUtil.generateDeviceId(mContext)");
hb.setDeviceName("shebeiweiyishibiehao");
hb.setVenueId(32); // TODO
hb.setEnterOrOut(DeviceType.ENTER);
hb.setDeviceType("ENTER");
return hb;
}

View File

@@ -1,6 +1,7 @@
package com.test.netty.client;
import com.sv.netty.config.Constant;
import com.sv.netty.netty.message.HeartBeat;
import com.sv.netty.utils.JsonUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
@@ -26,5 +27,11 @@ public class MessageEncoder extends MessageToByteEncoder {
byte[] content = message.getBytes(charset.name());
out.writeBytes(content); //发送消息内容
}
public static void main(String[] args) {
String hello = "{\"deviceType\":\"ENTER\",\"deviceName\":\"MGX5T17907001718\",\"venueId\":41}";
HeartBeat hb = JsonUtils.decode(hello,HeartBeat.class);
System.out.println(hb);
}
}

View File

@@ -1,33 +0,0 @@
package com.test.netty.client.message;
/**
* 设备属性,控制入场还是控制出场
*/
public enum DeviceType {
ENTER(0,"进场"),
OUT(1,"出场");
private int code;
private String name;
DeviceType(int code, String name) {
this.code = code;
this.name = name;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -19,7 +19,7 @@ public class HeartBeat implements Serializable {
private String deviceName; //设备号
@Expose
private DeviceType EnterOrOut; //出入标志
private String deviceType; //出入标志
public Integer getVenueId() {
return venueId;
@@ -37,11 +37,11 @@ public class HeartBeat implements Serializable {
this.deviceName = deviceName;
}
public DeviceType getEnterOrOut() {
return EnterOrOut;
public String getDeviceType() {
return deviceType;
}
public void setEnterOrOut(DeviceType enterOrOut) {
EnterOrOut = enterOrOut;
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}