服务端请求分发的一点小思路(适用于非http的情况)

  • 当我们使用非http的形式编写服务端的代码时,比如websocket,或者socket的时候,通常使用一个链接来满足所有的请求api,这时候服务端就需要定义一个框架来容纳所有的请求.
  • 接下来,我们借助于spring简单实现一下(非spring也是类似,偷懒一下):
  1. 首先定一个消息接口:

/**
 * 消息处理器
 *
 * @author
 */
public interface RequestMessageHandler {
 
}
  1. 接着创建一个接收api参数的接口类
/**
 * 参数接收接口
 *
 * @author
 */
public interface RequestMessage {

    /**
     * 执行处理消息  ChannelContext 是你业务中用来处理的一个核心类,与框架相关
     *
     * @param cc 
     * @param message 消息
     */
    void execute(ChannelContext cc, T message);
}

  1. 接着创建一个接收所有处理请求的容器
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;

/**
 * 存储所有的接口处理类
 * @author
 */
@Slf4j
@Component
public class RequestMessageHandlerContainer implements InitializingBean {

    /**
     * 消息类型与 MessageHandler 的映射
     */
    private final Map<String, RequestMessageHandler> handlers = new HashMap<>();

    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 获得 MessageHandler 处理的消息类
     *
     * @param handler 处理器
     * @return 消息类
     */
    public static Class<? extends RequestMessage> getMessageClass(RequestMessageHandler handler) {
        // 获得 Bean 对应的 Class 类名。因为有可能被 AOP 代理过。
        Class<?> targetClass = AopProxyUtils.ultimateTargetClass(handler);
        // 获得接口的 Type 数组
        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)) {
            // 遍历 interfaces 数组
            for (Type type : interfaces) {
                // 要求 type 是泛型参数
                if (type instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) type;
                    // 要求是 MessageHandler 接口
                    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 获得所有 MessageHandler Bean
        // 获得所有 MessageHandler Bean
        applicationContext.getBeansOfType(RequestMessageHandler.class).values()
                // 添加到 handlers 中
                .forEach(messageHandler -> handlers.put(messageHandler.getService(), messageHandler));
        log.info("[afterPropertiesSet][接收响应消息处理器数量:{}]", handlers.size());
    }

    /**
     * 获得类型对应的 MessageHandler
     *
     * @param type 类型
     * @return MessageHandler
     */
    public RequestMessageHandler getMessageHandler(String type) {
        RequestMessageHandler handler = handlers.get(type);
        if (handler == null) {
            throw new IllegalArgumentException(String.format("类型(%s) 找不到匹配的 RequestMessageHandler 处理器", type));
        }
        return handler;
    }

}

 
  1. 定义一个接收参数的bean

/**
 * 客户端心跳请求
 *
 * @author
 */
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class HeartBeatRequestMessage implements RequestMessage {
    /**
     * 接口名称
     */
    @NotEmpty(message = "接口名称不能为空")
    private String service;
   

  1. 定义一个相应的处理api的handler

/**
 * 心跳响应结果
 *
 * @author
 */
@Slf4j
@Component
public class HeartBeatRequestMessageHandler implements RequestMessageHandler<HeartBeatRequestMessage> {


    @Override
    public void execute(ChannelContext cc, HeartBeatRequestMessage message) {
        log.info("接收到的客户端心跳结果:{}", message);
        HeartbeatResponseMessage responseMessage = new HeartbeatResponseMessage();
     
    }


}

  1. 在接收消息的入口,先解析消息,如果为json的话,先判断消息的类型,然后传输给响应的处理类即可:
    RequestMessageHandler requestMessageHandler = requestMessageHandlerContainer.getMessageHandler("接口类型");
            // 获得  MessageHandler 处理器 的消息类
            Class<? extends RequestMessage> messageClass = RequestMessageHandlerContainer.getMessageClass(requestMessageHandler);
            // 解析消息
            RequestMessage requestMessage = JacksonUtils.toBean(reqJson, messageClass);
            //线程池执行
            taskExecutor.submit(() -> {
                requestMessageHandler.execute(cc, requestMessage);
            });
  1. 一个小型的case就写完了,下一节,给个具体的样例,顺便引入一个框架,一块学习一下.
  2. 这是我的微信公众号二维码,感谢关注,我会持续分享
    我的公众号
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值