netty-确定客户端和微信端的沟通方式

This commit is contained in:
2023-08-22 21:35:57 +08:00
parent 86fd226c84
commit 6c0a07331b
24 changed files with 109 additions and 490 deletions

View File

@@ -1,7 +1,6 @@
package com.sv.api.interceptor;
import com.sv.api.context.PlatformContext;
import com.sv.netty.config.Constant;
import com.ydd.framework.core.common.utils.ReflectUtil;
import com.ydd.framework.core.common.utils.RequestUtils;
import org.apache.commons.lang.StringUtils;
@@ -30,6 +29,11 @@ public class PlatformIdInterceptor implements Interceptor {
private static final Logger logger = LoggerFactory.getLogger(PlatformIdInterceptor.class);
/**
* 哪些接口不需要增加 platform 平台限制
*/
public static final List<String> executeControllerList = Arrays.asList(new String [] {"/qrCode/init","/qrCode/enter"});
/**
* 搜索前缀
*/
@@ -97,7 +101,7 @@ public class PlatformIdInterceptor implements Interceptor {
}
private boolean checkUrl(HttpServletRequest request) {
return Constant.executeControllerList.contains(request.getRequestURI());
return executeControllerList.contains(request.getRequestURI());
}

View File

@@ -1,38 +0,0 @@
package com.sv.netty.config;
import com.sv.netty.netty.message.ChannelParam;
import io.netty.util.AttributeKey;
import java.util.Arrays;
import java.util.List;
/**
* 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<ChannelParam> CHANNEL_PARAM = AttributeKey.newInstance("CHANNEL_PARAM");
public final static String SPIT_WORD = "#";
/**
* 哪些接口不需要增加 platform 平台限制
*/
public static final List<String> executeControllerList = Arrays.asList(new String [] {"/qrCode/init","/qrCode/enter"});
}

View File

@@ -1,7 +1,7 @@
package com.sv.netty.controller;
import com.sv.entity.Venue;
import com.sv.netty.config.Constant;
import com.sv.netty.config.NettyConstant;
import com.sv.netty.netty.service.MessageService;
import com.sv.service.api.QRCodeService;
import com.ydd.framework.core.common.dto.ResponseDTO;
@@ -73,8 +73,8 @@ public class QREnterController extends BaseApiController {
*/
private Integer getVenueId(String deviceId){
String venueId = "0";
if (deviceId!=null && deviceId.contains(Constant.SPIT_WORD)){
venueId = deviceId.split(Constant.SPIT_WORD)[1];
if (deviceId!=null && deviceId.contains(NettyConstant.SPIT_WORD)){
venueId = deviceId.split(NettyConstant.SPIT_WORD)[1];
}
try {
return Integer.parseInt(venueId);
@@ -90,7 +90,7 @@ public class QREnterController extends BaseApiController {
*/
private String getDeviceName(String deviceId){
if (deviceId!=null){
return deviceId.split(Constant.SPIT_WORD)[0];
return deviceId.split(NettyConstant.SPIT_WORD)[0];
}
return null;
}

View File

@@ -1,12 +1,14 @@
package com.sv.netty.netty;
import com.sv.netty.config.Constant;
import com.sv.netty.config.ChannelParam;
import com.sv.netty.config.HeartBeat;
import com.sv.netty.config.NettyConstant;
import com.sv.netty.config.SpringContextHolder;
import com.sv.netty.netty.message.ChannelParam;
import com.sv.netty.netty.message.HeartBeat;
import com.sv.netty.netty.service.MessageService;
import com.sv.netty.utils.JsonUtils;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,13 +49,12 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
System.err.println("发送的数据========" + msg);
String clientIp = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getClientIp();
String clientIp = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getClientIp();
try {
HeartBeat hb = JsonUtils.decode(msg,HeartBeat.class);
logger.info("客户端【" + clientIp + "】上报心跳...");
ctx.channel().attr(Constant.CHANNEL_PARAM).get().setVenueId(hb.getVenueId());
ctx.channel().attr(Constant.CHANNEL_PARAM).get().setDeviceName(hb.getDeviceName());
ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().setVenueId(hb.getVenueId());
ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().setDeviceName(hb.getDeviceName());
messageService.online(clientIp,ctx.channel(), hb);
} catch (Exception e) {
logger.error("[" + clientIp + "] host unknown error",e);
@@ -64,7 +65,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
public void channelRegistered(ChannelHandlerContext ctx) {
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));
ctx.channel().attr(NettyConstant.CHANNEL_PARAM).set(new ChannelParam(clientIP));
}
@@ -82,8 +83,8 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
public void channelInactive(ChannelHandlerContext ctx) {
String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
logger.error("Client ip [" + clientIP + "] has inactive");
Integer venueId = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getVenueId();
String deviceName = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getDeviceName();
Integer venueId = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getVenueId();
String deviceName = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getDeviceName();
messageService.Offline(deviceName,venueId);
}
@@ -97,9 +98,9 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
logger.error("ServerHandler exceptionCaught",cause);
Channel channel = ctx.channel();
// Integer venueId = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getVenueId();
// String deviceName = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getDeviceName();
// DeviceType deviceType = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getDeviceType();
// Integer venueId = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getVenueId();
// String deviceName = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getDeviceName();
// DeviceType deviceType = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getDeviceType();
// messageService.Offline(deviceName,venueId,deviceType);
if(channel.isActive()) {
// 错误产生,关闭连接
@@ -113,16 +114,16 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
// 服务器统计现在有的客户端数量, 客户端这个方法用来发心跳
// if (evt instanceof IdleStateEvent){
// IdleState state = ((IdleStateEvent) evt).state();
// if (state == IdleState.READER_IDLE){
// logger.info("IdleStateEvent READER_IDLE 超时");
// Integer venueId = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getVenueId();
// String deviceName = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getDeviceName();
// messageService.Offline(deviceName,venueId);
// ctx.channel().close();
// }
// }
if (evt instanceof IdleStateEvent){
IdleState state = ((IdleStateEvent) evt).state();
if (state == IdleState.READER_IDLE){
logger.info("IdleStateEvent READER_IDLE 超时");
Integer venueId = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getVenueId();
String deviceName = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getDeviceName();
messageService.Offline(deviceName,venueId);
ctx.channel().close();
}
}
Set<String> connections = messageService.countConnection();
logger.info("count connected device ! the count is " + connections.size() + " and they are + [" + connections.toString() + "]" );
}

View File

@@ -1,7 +1,5 @@
package com.sv.netty.netty;
import com.sv.netty.config.Constant;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
@@ -10,7 +8,6 @@ import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.springframework.stereotype.Component;
/**

View File

@@ -1,53 +0,0 @@
package com.sv.netty.netty.message;
/**
* 会话中存储的客户端对象
*
* @author peakren
* @since 16/05/2017 11:09 PM
*/
public class ChannelParam {
/**
* 设备ip
*/
private String clientIp;
/**
* 设备编号
*/
private String deviceName;
/**
* 设备所在场馆
*/
private Integer venueId;
public ChannelParam(String clientIP) {
this.clientIp = clientIP;
}
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public Integer getVenueId() {
return venueId;
}
public void setVenueId(Integer venueId) {
this.venueId = venueId;
}
}

View File

@@ -1,33 +0,0 @@
package com.sv.netty.netty.message;
import java.io.Serializable;
/**
* 客户端心跳数据包
* HeartBeat.java
*
* @author peakren
* @date 07/12/2017 10:23 PM
*/
public class HeartBeat implements Serializable {
private Integer venueId; //场馆号
private String deviceName; //设备号
public Integer getVenueId() {
return venueId;
}
public void setVenueId(Integer venueId) {
this.venueId = venueId;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
}

View File

@@ -1,30 +0,0 @@
package com.sv.netty.netty.message;
import java.io.Serializable;
public class MessageDTO implements Serializable {
private MessageType messageType;
private String message;
public MessageDTO(MessageType messageType, String message) {
this.messageType = messageType;
this.message = message;
}
public MessageType getMessageType() {
return messageType;
}
public void setMessageType(MessageType messageType) {
this.messageType = messageType;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@@ -1,21 +0,0 @@
package com.sv.netty.netty.message;
public enum MessageType {
LINK("连接"),
LOAD("加载"),
OPEN_DOOR("开门"),
FAILED("开门校验失败");
private String message;
MessageType(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@@ -1,39 +0,0 @@
package com.sv.netty.netty.message;
/**
* 请求门禁的灯光管理
*/
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;
}
}

View File

@@ -1,7 +1,7 @@
package com.sv.netty.netty.service;
import com.sv.entity.Venue;
import com.sv.netty.netty.message.HeartBeat;
import com.sv.netty.config.HeartBeat;
import io.netty.channel.Channel;
import java.util.Set;

View File

@@ -3,13 +3,10 @@ package com.sv.netty.netty.service.impl;
import com.sv.entity.Member;
import com.sv.entity.MemberEnterVenueLog;
import com.sv.entity.Venue;
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;
import com.sv.netty.netty.message.MessageType;
import com.sv.netty.config.*;
import com.sv.netty.netty.service.MessageService;
import com.sv.netty.utils.JsonUtils;
import com.sv.netty.utils.ServerMessageUtils;
import com.sv.service.api.MemberEnterVenueLogService;
import com.sv.service.api.MemberService;
import com.sv.service.api.VenueService;
@@ -88,8 +85,8 @@ public class AppMessageHandlerAdapter implements MessageService {
} else {
deviceService.online(heartBeat.getDeviceName(),heartBeat.getVenueId(),thisVenue.getType(),clientId);
putChannelType(heartBeat.getDeviceName(),heartBeat.getVenueId(),channel);
MessageDTO messageDTO = new MessageDTO(MessageType.LINK,"欢迎扫码进场!");
channel.writeAndFlush(messageDTO);
VenueMessage VenueMessage = new VenueMessage(MessageType.LINK,"欢迎扫码进场!");
channel.writeAndFlush(VenueMessage);
}
}
}
@@ -117,9 +114,9 @@ public class AppMessageHandlerAdapter implements MessageService {
Member thisMember = memberService.findByMember(memberId);
if (thisMember!=null){
String nickname = thisMember.getNickname();
MessageDTO messageDTO = new MessageDTO(MessageType.LOAD,"欢迎光临!" + nickname + ",请您60s内操作进场。");
VenueMessage venueMessage = new VenueMessage(MessageType.LOAD,"欢迎光临!" + nickname + ",请您60s内操作进场。");
Channel currentChannel = getCurrentChannel(deviceName, venueId);
sendMessage(currentChannel,messageDTO);
ServerMessageUtils.INSTANCE.sendMsg(currentChannel,venueMessage);
return true;
}
return false;
@@ -159,10 +156,10 @@ public class AppMessageHandlerAdapter implements MessageService {
// 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());
// VenueMessage VenueMessage = new VenueMessage();
// VenueMessage.setCmdId(Cmd.OPEN_DOOR.id);
// VenueMessage.setDoor(2);
// sendOpenMessage(VenueMessage, device.getId());
// 校验玩就可以出场了
// sendMessage(memberMessageDto, device.getId());
// venueService.addNumber(venue.getId(), -1, member.getId());
@@ -187,16 +184,16 @@ public class AppMessageHandlerAdapter implements MessageService {
if(venueService.qrCodeEnterVenue(memberId,deviceName,venueId,venue)){
// 可以进场
scheduledExecutorService.schedule(() -> {
sendMessage(channel,new MessageDTO(MessageType.OPEN_DOOR,"OK"));
ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OPEN_DOOR,"OK"));
}, 5, TimeUnit.SECONDS);
} else {
// 进场失败
sendMessage(channel,new MessageDTO(MessageType.FAILED, ErrorCode.NO_USE_CARD.getMsg()));
ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.FAILED, ErrorCode.NO_USE_CARD.getMsg()));
}
} else {
logger.info(member == null ? "null" : member.getId() + "入场失败:连续入场");
Config config = configService.findById(1);
sendMessage(channel,new MessageDTO(MessageType.OPEN_DOOR, MessageFormat.format(ErrorCode.CHECK_ENTER_INTERVAL.getMsg(),config.getValue())));
ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OPEN_DOOR, MessageFormat.format(ErrorCode.CHECK_ENTER_INTERVAL.getMsg(),config.getValue())));
}
}
@@ -242,30 +239,6 @@ public class AppMessageHandlerAdapter implements MessageService {
}
}
/**
* 给客户端发送信息
* @param channel
* @param messageDTO
*/
private void sendMessage(Channel channel, MessageDTO messageDTO) {
channel.writeAndFlush(messageDTO);
}
/**
* 控制硬件,篮球馆的门禁灯光控制
* @param number
*/
public void sendNumberChange(Integer number) {
// HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
// param.add("LingtekID", "5d14229fcb1f5c1a9046f429");
// param.add("Number", number.toString());
// HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(param, headers);
// ResponseEntity<Result> result = restTemplate.exchange("http://lingtek.jalasmart.com/api/v1/lingtek/number", HttpMethod.PUT, request, Result.class);
// logger.info("灯光结果" + JsonMapper.nonDefaultMapper().toJson(result));
}
/**
* 操作连接
*/
@@ -273,7 +246,7 @@ public class AppMessageHandlerAdapter implements MessageService {
* 缓存通道
*/
public void putChannelType(String deviceName, Integer venueId, Channel channel) {
String clientId = deviceName + Constant.SPIT_WORD + venueId;
String clientId = deviceName + NettyConstant.SPIT_WORD + venueId;
links.put(clientId, channel);
}
@@ -281,7 +254,7 @@ public class AppMessageHandlerAdapter implements MessageService {
* 获取当前通道
*/
public Channel getCurrentChannel(String deviceName, Integer venueId){
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD;
String clientId = deviceName + NettyConstant.SPIT_WORD + venueId + NettyConstant.SPIT_WORD;
return links.get(clientId);
}
@@ -289,7 +262,7 @@ public class AppMessageHandlerAdapter implements MessageService {
* 获取通道
*/
public boolean contains(String deviceName, Integer venueId) {
String clientId = deviceName + Constant.SPIT_WORD + venueId + Constant.SPIT_WORD;
String clientId = deviceName + NettyConstant.SPIT_WORD + venueId + NettyConstant.SPIT_WORD;
return links.containsKey(clientId);
}
@@ -297,7 +270,7 @@ public class AppMessageHandlerAdapter implements MessageService {
* 移除通道
*/
public void removeChannelType(String deviceName, Integer venueId) {
String clientId = deviceName + Constant.SPIT_WORD + venueId ;
String clientId = deviceName + NettyConstant.SPIT_WORD + venueId ;
links.remove(clientId);
}
@@ -309,4 +282,20 @@ public class AppMessageHandlerAdapter implements MessageService {
public Set<String> countConnection() {
return links.keySet();
}
/**
* 控制硬件,篮球馆的门禁灯光控制
* @param number
*/
// public void sendNumberChange(Integer number) {
// HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
// param.add("LingtekID", "5d14229fcb1f5c1a9046f429");
// param.add("Number", number.toString());
// HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(param, headers);
// ResponseEntity<Result> result = restTemplate.exchange("http://lingtek.jalasmart.com/api/v1/lingtek/number", HttpMethod.PUT, request, Result.class);
// logger.info("灯光结果" + JsonMapper.nonDefaultMapper().toJson(result));
// }
}