实现nats rpc rest api gateway

主要说明下如何实现,具体就是基于现有的框架,实现基于service 提及msg 进行转发,处理比较简单

包装

主要说明下服务的

  • 定义rest 暴露处理 RestApiAbstractServiceHandler 就是转发请求
public <R> R defaultRestApiHandler(String serviceName, String prefix, String serviceEndpoint, T demoMessage, HttpHeaders httpHeaders) {
        return restApiHandler(serviceName, prefix, serviceEndpoint, demoMessage, httpHeaders);
    }

    public boolean beforeRestApiHandler(String serviceName, String prefix, String serviceEndpoint, T baseMessage, HttpHeaders headers) {
        return true;
    }

    public void afterRestApiHandler(String serviceName, String prefix, String serviceEndpoint, T baseMessage, HttpHeaders headers, Object result) {

    }

    public <R> R restApiHandler(String serviceName, String prefix, String serviceEndpoint, T baseMessage, HttpHeaders headers) {
        Headers natsHeaders;
        if (headers != null) {
            natsHeaders = new Headers();
            headers.forEach((key, values) -> {
                for (String value : values) {
                    natsHeaders.add(key, value);
                }
            });
        } else {
            natsHeaders = null;
        }
        String fullServiceEndpoint = String.format("%s.svc.%s.%s", serviceName, prefix, serviceEndpoint);
        if (beforeRestApiHandler(serviceName, prefix, serviceEndpoint, baseMessage, headers)) {
            byte[] payload = serializeMessage(this.getObjectMapper(), baseMessage);
            Object result = NatsRpcCall.call(this.getConnection(), this.getObjectMapper(), fullServiceEndpoint, payload, natsHeaders);
            afterRestApiHandler(serviceName, prefix, serviceEndpoint, baseMessage, headers, result);
            return (R) result;
        }
        return null;
 }
  • 代码

服务格式/api/gw/rest/{servicename}/{prefix}/{serviceendpoint}

@Component
public class NatsRpcServiceHandler extends RestApiAbstractServiceHandler<BaseMessage> {

    private  Connection connection;
    private  ObjectMapper objectMapper;
    public NatsRpcServiceHandler(ObjectMapper objectMapper, Connection connection) {
        this.objectMapper = objectMapper;
        this.connection = connection;
    }
    @Override
    public Connection getConnection() {
        return this.connection;
    }

    @Override
    public ObjectMapper getObjectMapper() {
        return this.objectMapper;
    }

    @Override
    public BaseMessage defaultMessageHandler(BaseMessage demoMessage, Headers headers) {
        return demoMessage;
    }
    @ResponseBody
    @ServiceMapping(
            name = "defaultRestApiHandler",
            path = {"/api/gw/rest/{servicename}/{prefix}/{serviceendpoint}"},
            method = {"POST"},
            version = "1.0.0"
    )
    @Override
    public Object defaultRestApiHandler(@PathVariable(name = "servicename") String serviceName,
                                        @PathVariable(name = "prefix") String prefix,
                                        @PathVariable(name = "serviceendpoint") String serviceEndpoint,
                                        @RequestBody   BaseMessage demoMessage,
                                        @Parameter(hidden = true) @RequestHeader  HttpHeaders httpHeaders) {
        return super.defaultRestApiHandler(serviceName,prefix,serviceEndpoint, demoMessage, httpHeaders);
    }
}
  • 内部处理

因为提供了bean,核心就是对于@ServiceMapping 注解的处理,然后动态注册controller 就可以了

public void registerRestApis() {
    serviceHandlers.forEach(serviceHandler -> {
        Class<?> targetClass =
                AopProxyUtils.ultimateTargetClass(serviceHandler);
        Method[] methods = targetClass.getMethods();
        Arrays.stream(methods).forEach(method -> {
            if(method.isBridge()){
                return;
            }
            ServiceMapping serviceMapping = method.getAnnotation(ServiceMapping.class);
            if (serviceMapping == null) {
                return;
            }
            if (method.getDeclaringClass() != targetClass) {
                return;
            }
            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);
        });
    });
}

参考api 效果

image

说明

整体处理很简单,核心是动态注册,以及自动bena注入(包装为starter),详细代码参考github

参考资料

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

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

导航