From a50324c43ab66c47c83f4ff21dcf5ad4f04c5a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=A9=AC=E5=93=A5?= Date: Fri, 29 Mar 2019 20:08:50 +0800 Subject: [PATCH] To add Gateway demo --- .../pom.xml | 1 + .../pom.xml | 39 ++++ ...bboSpringCloudServletGatewayBootstrap.java | 23 +++ .../dubbo/gateway/DubboGatewayServlet.java | 188 ++++++++++++++++++ .../src/main/resources/application.yaml | 12 ++ .../src/main/resources/bootstrap.yaml | 70 +++++++ 6 files changed, 333 insertions(+) create mode 100644 spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml create mode 100644 spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java create mode 100644 spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/gateway/DubboGatewayServlet.java create mode 100644 spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/application.yaml create mode 100644 spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/bootstrap.yaml diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/pom.xml index 6a96eb0d..b393fddb 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/pom.xml @@ -20,6 +20,7 @@ spring-cloud-dubbo-provider-sample spring-cloud-dubbo-consumer-sample spring-cloud-dubbo-provider-web-sample + spring-cloud-dubbo-servlet-gateway-sample diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml new file mode 100644 index 00000000..75b6d18e --- /dev/null +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/pom.xml @@ -0,0 +1,39 @@ + + + + spring-cloud-alibaba-dubbo-examples + org.springframework.cloud + 0.2.2.BUILD-SNAPSHOT + ../pom.xml + + 4.0.0 + + org.springframework.cloud + spring-cloud-dubbo-servlet-gateway-sample + Spring Cloud Dubbo Servlet Gateway Sample + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.cloud + spring-cloud-dubbo-sample-api + ${project.version} + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java new file mode 100644 index 00000000..0ad4d68e --- /dev/null +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudServletGatewayBootstrap.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.alibaba.dubbo.bootstrap; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * Dubbo Spring Cloud Servlet Gateway Bootstrap + */ +@EnableDiscoveryClient +@EnableAutoConfiguration +@EnableFeignClients +@ServletComponentScan(basePackages = "org.springframework.cloud.alibaba.dubbo.gateway") +public class DubboSpringCloudServletGatewayBootstrap { + + public static void main(String[] args) { + new SpringApplicationBuilder(DubboSpringCloudServletGatewayBootstrap.class) + .properties("spring.profiles.active=nacos") + .run(args); + } +} diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/gateway/DubboGatewayServlet.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/gateway/DubboGatewayServlet.java new file mode 100644 index 00000000..46fcf5e2 --- /dev/null +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/gateway/DubboGatewayServlet.java @@ -0,0 +1,188 @@ +package org.springframework.cloud.alibaba.dubbo.gateway; + +import org.apache.commons.lang.StringUtils; +import org.apache.dubbo.rpc.service.GenericException; +import org.apache.dubbo.rpc.service.GenericService; +import org.springframework.cloud.alibaba.dubbo.http.MutableHttpServerRequest; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; +import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContext; +import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory; +import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpRequest; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.CollectionUtils; +import org.springframework.util.PathMatcher; +import org.springframework.util.StreamUtils; +import org.springframework.web.util.UriComponents; + +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; + +import static org.springframework.web.util.UriComponentsBuilder.fromUriString; + +@WebServlet(urlPatterns = "/dsc/*") +public class DubboGatewayServlet extends HttpServlet { + + private final DubboServiceMetadataRepository repository; + + private final DubboTransportedMetadata dubboTransportedMetadata; + + private final DubboGenericServiceFactory serviceFactory; + + private final DubboGenericServiceExecutionContextFactory contextFactory; + + private final PathMatcher pathMatcher = new AntPathMatcher(); + + public DubboGatewayServlet(DubboServiceMetadataRepository repository, + DubboGenericServiceFactory serviceFactory, + DubboGenericServiceExecutionContextFactory contextFactory) { + this.repository = repository; + this.dubboTransportedMetadata = new DubboTransportedMetadata(); + dubboTransportedMetadata.setProtocol("dubbo"); + dubboTransportedMetadata.setCluster("failover"); + this.serviceFactory = serviceFactory; + this.contextFactory = contextFactory; + } + + public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + + // /g/{app-name}/{rest-path} + String requestURI = request.getRequestURI(); + // /g/ + String servletPath = request.getServletPath(); + + String part = StringUtils.substringAfter(requestURI, servletPath); + + String serviceName = StringUtils.substringBetween(part, "/", "/"); + + // App name= spring-cloud-alibaba-dubbo-web-provider (127.0.0.1:8080) + + String restPath = StringUtils.substringAfter(part, serviceName); + + // 初始化 serviceName 的 REST 请求元数据 + repository.initialize(serviceName); + // 将 HttpServletRequest 转化为 RequestMetadata + RequestMetadata clientMetadata = buildRequestMetadata(request, restPath); + + DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, clientMetadata); + + if (dubboServiceMetadata == null) { + // if DubboServiceMetadata is not found, executes next + throw new ServletException("DubboServiceMetadata can't be found!"); + } + + RestMethodMetadata dubboRestMethodMetadata = dubboServiceMetadata.getRestMethodMetadata(); + + GenericService genericService = serviceFactory.create(dubboServiceMetadata, dubboTransportedMetadata); + + // TODO: Get the Request Body from HttpServletRequest + byte[] body = getRequestBody(request); + + MutableHttpServerRequest httpServerRequest = new MutableHttpServerRequest(new HttpRequestAdapter(request), body); + +// customizeRequest(httpServerRequest, dubboRestMethodMetadata, clientMetadata); + + DubboGenericServiceExecutionContext context = contextFactory.create(dubboRestMethodMetadata, httpServerRequest); + + Object result = null; + GenericException exception = null; + + try { + result = genericService.$invoke(context.getMethodName(), context.getParameterTypes(), context.getParameters()); + } catch (GenericException e) { + exception = e; + } + response.getWriter().println(result); + } + + private byte[] getRequestBody(HttpServletRequest request) throws IOException { + ServletInputStream inputStream = request.getInputStream(); + return StreamUtils.copyToByteArray(inputStream); + } + + private static class HttpRequestAdapter implements HttpRequest { + + private final HttpServletRequest request; + + private HttpRequestAdapter(HttpServletRequest request) { + this.request = request; + } + + @Override + public String getMethodValue() { + return request.getMethod(); + } + + @Override + public URI getURI() { + try { + return new URI(request.getRequestURL().toString() + "?" + request.getQueryString()); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + throw new RuntimeException(); + } + + @Override + public HttpHeaders getHeaders() { + return new HttpHeaders(); + } + } + +// protected void customizeRequest(MutableHttpServerRequest httpServerRequest, +// RestMethodMetadata dubboRestMethodMetadata, RequestMetadata clientMetadata) { +// +// RequestMetadata dubboRequestMetadata = dubboRestMethodMetadata.getRequest(); +// String pathPattern = dubboRequestMetadata.getPath(); +// +// Map pathVariables = pathMatcher.extractUriTemplateVariables(pathPattern, httpServerRequest.getPath()); +// +// if (!CollectionUtils.isEmpty(pathVariables)) { +// // Put path variables Map into query parameters Map +// httpServerRequest.params(pathVariables); +// } +// +// } + + private RequestMetadata buildRequestMetadata(HttpServletRequest request, String restPath) { + UriComponents uriComponents = fromUriString(request.getRequestURI()).build(true); + RequestMetadata requestMetadata = new RequestMetadata(); + requestMetadata.setPath(restPath); + requestMetadata.setMethod(request.getMethod()); + requestMetadata.setParams(getParams(request)); + requestMetadata.setHeaders(getHeaders(request)); + return requestMetadata; + } + + private Map> getHeaders(HttpServletRequest request) { + Map> map = new LinkedHashMap<>(); + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + Enumeration headerValues = request.getHeaders(headerName); + map.put(headerName, Collections.list(headerValues)); + } + return map; + } + + private Map> getParams(HttpServletRequest request) { + Map> map = new LinkedHashMap<>(); + for (Map.Entry entry : request.getParameterMap().entrySet()) { + map.put(entry.getKey(), Arrays.asList(entry.getValue())); + } + return map; + } +} diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/application.yaml new file mode 100644 index 00000000..263a5699 --- /dev/null +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/application.yaml @@ -0,0 +1,12 @@ +dubbo: + registry: + # The Spring Cloud Dubbo's registry extension + address: spring-cloud://localhost +# The traditional Dubbo's registry +# address: zookeeper://127.0.0.1:2181 +server: + port: 0 + +provider: + application: + name: spring-cloud-alibaba-dubbo-web-provider \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/bootstrap.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/bootstrap.yaml new file mode 100644 index 00000000..a86acd15 --- /dev/null +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-servlet-gateway-sample/src/main/resources/bootstrap.yaml @@ -0,0 +1,70 @@ +spring: + application: + name: spring-cloud-alibaba-dubbo-servlet-gateway + main: + allow-bean-definition-overriding: true + + + # default disable all + cloud: + nacos: + discovery: + enabled: false + register-enabled: false + zookeeper: + enabled: false + consul: + enabled: false + +eureka: + client: + enabled: false + +ribbon: + nacos: + enabled: false + +--- +spring: + profiles: nacos + + cloud: + nacos: + discovery: + enabled: true + register-enabled: true + server-addr: 127.0.0.1:8848 + +ribbon: + nacos: + enabled: true + +--- +spring: + profiles: eureka + +eureka: + client: + enabled: true + service-url: + defaultZone: http://127.0.0.1:8761/eureka/ + + +--- +spring: + profiles: zookeeper + cloud: + zookeeper: + enabled: true + connect-string: 127.0.0.1:2181 + + +--- +spring: + profiles: consul + + cloud: + consul: + enabled: true + host: 127.0.0.1 + port: 8500 \ No newline at end of file