- 当我们使用非http的形式编写服务端的代码时,比如websocket,或者socket的时候,通常使用一个链接来满足所有的请求api,这时候服务端就需要定义一个框架来容纳所有的请求.
- 接下来,我们借助于spring简单实现一下(非spring也是类似,偷懒一下):
- 首先定一个消息接口:
public interface RequestMessageHandler {
}
- 接着创建一个接收api参数的接口类
public interface RequestMessage {
void execute(ChannelContext cc, T message);
}
- 接着创建一个接收所有处理请求的容器
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
public class RequestMessageHandlerContainer implements InitializingBean {
private final Map<String, RequestMessageHandler> handlers = new HashMap<>();
@Autowired
private ApplicationContext applicationContext;
public static Class<? extends RequestMessage> getMessageClass(RequestMessageHandler handler) {
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(handler);
Type[] interfaces = targetClass.getGenericInterfaces();
Class<?> superclass = targetClass.getSuperclass().getSuperclass();
while ((Objects.isNull(interfaces) || 0 == interfaces.length) && Objects.nonNull(superclass)) {
interfaces = superclass.getGenericInterfaces();
superclass = targetClass.getSuperclass();
}
if (Objects.nonNull(interfaces)) {
for (Type type : interfaces) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
if (Objects.equals(parameterizedType.getRawType(), RequestMessageHandler.class)) {
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) {
return (Class<RequestMessage>) actualTypeArguments[0];
} else {
throw new IllegalStateException(String.format("类型(%s) 获得不到消息类型", handler));
}
}
}
}
}
throw new IllegalStateException(String.format("类型(%s) 获得不到消息类型", handler));
}
@Override
public void afterPropertiesSet() throws Exception {
applicationContext.getBeansOfType(RequestMessageHandler.class).values()
.forEach(messageHandler -> handlers.put(messageHandler.getService(), messageHandler));
log.info("[afterPropertiesSet][接收响应消息处理器数量:{}]", handlers.size());
}
public RequestMessageHandler getMessageHandler(String type) {
RequestMessageHandler handler = handlers.get(type);
if (handler == null) {
throw new IllegalArgumentException(String.format("类型(%s) 找不到匹配的 RequestMessageHandler 处理器", type));
}
return handler;
}
}
- 定义一个接收参数的bean
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class HeartBeatRequestMessage implements RequestMessage {
@NotEmpty(message = "接口名称不能为空")
private String service;
- 定义一个相应的处理api的handler
@Slf4j
@Component
public class HeartBeatRequestMessageHandler implements RequestMessageHandler<HeartBeatRequestMessage> {
@Override
public void execute(ChannelContext cc, HeartBeatRequestMessage message) {
log.info("接收到的客户端心跳结果:{}", message);
HeartbeatResponseMessage responseMessage = new HeartbeatResponseMessage();
}
}
- 在接收消息的入口,先解析消息,如果为json的话,先判断消息的类型,然后传输给响应的处理类即可:
RequestMessageHandler requestMessageHandler = requestMessageHandlerContainer.getMessageHandler("接口类型");
Class<? extends RequestMessage> messageClass = RequestMessageHandlerContainer.getMessageClass(requestMessageHandler);
RequestMessage requestMessage = JacksonUtils.toBean(reqJson, messageClass);
taskExecutor.submit(() -> {
requestMessageHandler.execute(cc, requestMessage);
});
- 一个小型的case就写完了,下一节,给个具体的样例,顺便引入一个框架,一块学习一下.
- 这是我的微信公众号二维码,感谢关注,我会持续分享
![我的公众号](https://i-blog.csdnimg.cn/blog_migrate/a1e79088daa107973b5b673ba66d7ddd.jpeg)