nats rpc 服务暴露rest api 的处理

以前我简单说过,就是通过动态注册controller 就可以了,以下是一个演示

具体处理

  • 参考处理

就是自己基于定义nats rpc 的RestApiAbstractServiceHandler,包含一个基本实现,同时对于注册服务基于自定义注解,为了方便处理,可以直接复用spring http request 的一些东西

public abstract class RestApiAbstractServiceHandler<T extends BaseMessage> extends AbstractServiceHandler<T> {

    public <R> R defaultRestApiHandler(T demoMessage,   HttpHeaders httpHeaders){
        return restApiHandler(demoMessage, httpHeaders);
    }
    public <R> R restApiHandler(T baseMessage, HttpHeaders headers) {
        Method actionMethod = actionMethod(baseMessage);
        Headers natsHeaders;
        if (headers != null) {
            natsHeaders = new Headers();
            headers.forEach((key, values) -> {
                for (String value : values) {
                    natsHeaders.add(key, value);
                }
            });
        } else {
            natsHeaders = null;
        }
        boolean continueProcess = beforeHandle(actionMethod, baseMessage, natsHeaders);
        if (continueProcess) {
            Object result = actionMethodExecute(actionMethod, this, baseMessage, natsHeaders);
            afterHandle(actionMethod, result, natsHeaders);
            return (R) result;
        }
        return null;
    }
}

  • 动态注册
public void registerRestApis() {
      serviceHandlers.forEach(serviceHandler -> {
          // 获取实际类,避免动态代理的
          Class<?> targetClass =
                  AopProxyUtils.ultimateTargetClass(serviceHandler);
          Method[] methods = targetClass.getDeclaredMethods();
          Arrays.stream(methods).forEach(method -> {
              // 过滤bridge方法,不然会有重复的问题
              if(method.isBridge()){
                  return;
              }
              ServiceMapping serviceMapping = method.getAnnotation(ServiceMapping.class);
              if (serviceMapping == null) {
                  return;
              }
              if (method.getDeclaringClass() != targetClass) {
                  return;
              }
              // 结合注解,动态注册controller
              RequestMappingInfo mapping = RequestMappingInfo
                      .paths(serviceMapping.path())
                      .methods(Arrays.stream(serviceMapping.method()).map(item -> methodutils.str2RequestMethod(item)).toArray(RequestMethod[]::new))
                      .build();
              Method handlerMethod = method;
              requestMappingHandlerMapping.registerMapping(mapping, serviceHandler, handlerMethod);
          });
      });
}
  • 业务使用

代码截取了部分,核心演示就是可以同时暴露,还可以使用现有的http request 处理

@ResponseBody
@ServiceMapping(
        name = "defaultRestApiHandler",
        path = {"/api/default/rest/"},
        method = {"POST"},
        version = "1.0.0"
)
@Override
public Object defaultRestApiHandler(@RequestBody  DemoMessage demoMessage, @Parameter(hidden = true) HttpHeaders httpHeaders) {
    return super.defaultRestApiHandler(demoMessage, httpHeaders);
}

@ResponseBody
@ServiceMapping(path = {"/appdemo/{id}"},method = {"POST"})
public DemoMessage echoDemo(@RequestBody DemoMessage demoMessage, @PathVariable("id") String id, @RequestHeader(name = "token", required = false) String token){
    return echoDemo(demoMessage, new Headers());
}

@ResponseBody
@ServiceMapping(path = {"/api/gw/{id}"},method = {"POST"})
public DemoMessage apiGateway(@RequestBody DemoMessage demoMessage, @PathVariable("id") String id, @Parameter(hidden = true) @RequestHeader(required = false) HttpHeaders httpHeaders){
    return echoDemo(demoMessage, new Headers());
}

说明

以上代码是我nats-rpc-springboot-starter的内部处理机制,详细代码可以看是实际源码,机制比较简单

参考资料

https://github.com/rongfengliang/nats-rpc-springboot-starter

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.html

posted on 2026-01-14 08:00  荣锋亮  阅读(0)  评论(0)    收藏  举报

导航