tcp是异步通信,如果想同步将响应信息返回给调用者tcp是做不到的。
解决方案:
第一步:新建消息管理器类。
package com.components.driver.netty;
/**
* 消息管理器<br>
* tcp通讯中实现同步返回
**/
public class ResponseMsg {
/** 应答超时时间 */
private final static Long RES_TIMEOUT = 10*1000L;
private Object data;
public Object getResponse() {
try {
//不加锁 抛java.lang.IllegalMonitorStateException
synchronized (this) {
this.wait(RES_TIMEOUT);
}
} catch (InterruptedException ignore) {
return null;
}
return getData();
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
第二步:创建消息发送服务类,在tcp消息发送方法中添加如下代码。
package com.components.driver.netty;
import com.alibaba.fastjson.JSONObject;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentHashMap;
/**
* 消息同步发送服务
*/
public class CommManager {
/**
* TCP推送消息列表,记录消息超时
*/
public static final ConcurrentHashMap<Long, ResponseMsg> PUSH_MSG_MAP_TCP = new ConcurrentHashMap<>();
/**
* 同步发送数据<br>
* 发送成功后等待终端的应答数据
* @param data json数据
*/
public static String sendTcpMessageSync(String data){
// tcp消息发送
NettyClient.sendData(data);
JSONObject jsonObject = JSONObject.parseObject(data);
ResponseMsg responseMsg = new ResponseMsg();
// 等待响应的key.
PUSH_MSG_MAP_TCP.put((Long) jsonObject.get("seqNo"), responseMsg);
//等待responseMsg设置的超时时间内获取响应数据
return (String) responseMsg.getResponse();
}
...
}
第三步:创建消息接收服务类。消息接收的地方处理响应数据,将响应数据放到缓存Map中。
...省略块...
// 请求
if (StringUtils.equals(RequestTypeEnum.request.toString(), requestType)){
responsePacket.setType(RequestTypeEnum.response.toString());
responsePacket.setTraceId(responsePacket.getSeqNo());
issctBusinessAction(responsePacket, businessAction);
}else
// 响应
{
Long requestId = responsePacket.getTraceId() == null ? responsePacket.getSeqNo() : responsePacket.getTraceId();
ResponseMsg responseMsg = CommManager.PUSH_MSG_MAP_TCP.get(requestId);
if (responseMsg != null) {
responseMsg.setData(data);
responseMsg.notify();
CommManager.PUSH_MSG_MAP_TCP.remove(requestId);
}
}
...省略块...