From 24923ce1663a1c7c4711706b10f097dc181b44d2 Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Tue, 4 Jun 2024 23:47:32 +0800 Subject: [PATCH 1/3] servlet --- .artifacts | 3 +- .../apache/dubbo/common/io/StreamUtils.java | 2 +- .../dubbo/config/context/ConfigManager.java | 5 + .../dubbo/config/nested/TripleConfig.java | 43 +++++ .../dubbo-demo-spring-boot-provider/pom.xml | 5 + .../src/main/resources/application.yml | 14 +- dubbo-demo/dubbo-demo-spring-boot/pom.xml | 10 + dubbo-dependencies-bom/pom.xml | 14 +- .../pom.xml | 6 + dubbo-distribution/dubbo-all-shaded/pom.xml | 9 +- dubbo-distribution/dubbo-all/pom.xml | 8 + dubbo-distribution/dubbo-bom/pom.xml | 10 + dubbo-distribution/pom.xml | 6 + dubbo-plugin/dubbo-triple-servlet/pom.xml | 107 ++++++++++ .../tri/servlet/HttpMetadataAdapter.java | 83 ++++++++ .../tri/servlet/ServletStreamChannel.java | 156 +++++++++++++++ .../protocol/tri/servlet/TripleFilter.java | 182 ++++++++++++++++++ dubbo-plugin/pom.xml | 1 + .../rpc/protocol/tri/ServletExchanger.java | 37 ++++ .../rpc/protocol/tri/TripleProtocol.java | 10 +- .../DefaultRequestMappingRegistry.java | 17 ++ .../tri/rest/mapping/RequestMapping.java | 4 + .../rest/mapping/RequestMappingRegistry.java | 2 + .../mapping/condition/MethodsCondition.java | 4 + .../dubbo-spring-boot-3-autoconfigure/pom.xml | 69 +++++++ .../DubboTriple3AutoConfiguration.java | 52 +++++ .../autoconfigure/SpringBoot3Condition.java | 32 +++ .../main/resources/META-INF/spring.factories | 2 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../dubbo-spring-boot-autoconfigure/pom.xml | 6 + .../DubboTripleAutoConfiguration.java | 52 +++++ .../autoconfigure/SpringBoot12Condition.java | 32 +++ .../main/resources/META-INF/spring.factories | 3 +- ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../dubbo-spring-boot-starter/pom.xml | 5 + dubbo-spring-boot/pom.xml | 1 + dubbo-test/dubbo-dependencies-all/pom.xml | 10 + pom.xml | 6 + 38 files changed, 1002 insertions(+), 8 deletions(-) create mode 100644 dubbo-plugin/dubbo-triple-servlet/pom.xml create mode 100644 dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java create mode 100644 dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java create mode 100644 dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java create mode 100644 dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml create mode 100644 dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java create mode 100644 dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java create mode 100644 dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring.factories create mode 100644 dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java create mode 100644 dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java diff --git a/.artifacts b/.artifacts index 5818a24e9ad..d88cbd4fce2 100644 --- a/.artifacts +++ b/.artifacts @@ -93,6 +93,7 @@ dubbo-spring-boot dubbo-spring-boot-actuator dubbo-spring-boot-actuator-compatible dubbo-spring-boot-autoconfigure +dubbo-spring-boot-3-autoconfigure dubbo-spring-boot-autoconfigure-compatible dubbo-spring-boot-compatible dubbo-observability-spring-boot-starters @@ -116,4 +117,4 @@ dubbo-plugin-loom dubbo-rest-jaxrs dubbo-rest-servlet dubbo-rest-spring - +dubbo-triple-servlet diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/io/StreamUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/io/StreamUtils.java index 9e10135d87b..107b53752b3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/io/StreamUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/io/StreamUtils.java @@ -258,7 +258,7 @@ public static byte[] readBytes(InputStream in) throws IOException { if (in.getClass() == ByteArrayInputStream.class) { return readBytes((ByteArrayInputStream) in); } - ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java index e49bf560bf6..5d4386e9694 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.config.context; +import org.apache.dubbo.common.URL; import org.apache.dubbo.common.context.ApplicationExt; import org.apache.dubbo.common.extension.DisableInject; import org.apache.dubbo.common.logger.Logger; @@ -72,6 +73,10 @@ public ConfigManager(ApplicationModel applicationModel) { TracingConfig.class)); } + public static ProtocolConfig getProtocol(URL url) { + return url.getOrDefaultApplicationModel().getApplicationConfigManager().getOrAddProtocol(url.getProtocol()); + } + // ApplicationConfig correlative methods /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java index 0edaf61c367..df8b88ed5ab 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java @@ -100,6 +100,25 @@ public class TripleConfig implements Serializable { */ private Integer maxHeaderListSize; + /** + * Enable servlet support, requests are transport through the servlet container, + * which only supports unary calls due to protocol limitations + *

The default value is false. + */ + private Boolean enableServlet; + + /** + * The URL patterns that the servlet filter will be registered for. + *

The default value is '/*'. + */ + private String[] servletFilterUrlPatterns; + + /** + * The order of the servlet filter. + *

The default value is -1000000. + */ + private Integer servletFilterOrder; + public Integer getMaxBodySize() { return maxBodySize; } @@ -196,6 +215,30 @@ public void setMaxHeaderListSize(Integer maxHeaderListSize) { this.maxHeaderListSize = maxHeaderListSize; } + public Boolean getEnableServlet() { + return enableServlet; + } + + public void setEnableServlet(Boolean enableServlet) { + this.enableServlet = enableServlet; + } + + public String[] getServletFilterUrlPatterns() { + return servletFilterUrlPatterns; + } + + public void setServletFilterUrlPatterns(String[] servletFilterUrlPatterns) { + this.servletFilterUrlPatterns = servletFilterUrlPatterns; + } + + public Integer getServletFilterOrder() { + return servletFilterOrder; + } + + public void setServletFilterOrder(Integer servletFilterOrder) { + this.servletFilterOrder = servletFilterOrder; + } + public void checkDefault() { if (maxBodySize == null) { maxBodySize = 1 << 23; diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml index 2c0d5234499..88b6160ba4f 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml @@ -92,6 +92,11 @@ ${project.version} + + org.springframework.boot + spring-boot-starter-web + + org.apache.dubbo dubbo-spring-boot-starter diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml index b1789be60fa..b75b8578e99 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/src/main/resources/application.yml @@ -21,9 +21,12 @@ spring: dubbo: application: name: ${spring.application.name} + qos-enable: false protocol: - name: dubbo - port: -1 + name: tri + port: ${server.port} + triple: + enable-servlet: true registry: id: zk-registry address: zookeeper://127.0.0.1:2181 @@ -41,3 +44,10 @@ dubbo: exporter: enabled: true enable-metadata: true + +server: + port: 8081 + http2: + enabled: true + tomcat: + keep-alive-timeout: 180000 diff --git a/dubbo-demo/dubbo-demo-spring-boot/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/pom.xml index 5466f619f8f..2d63b81e5ee 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/pom.xml +++ b/dubbo-demo/dubbo-demo-spring-boot/pom.xml @@ -65,4 +65,14 @@ + + + + spring-boot-3 + + 3.2.1 + 3.2.1 + + + diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 0d2af039594..09511d251f8 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -108,6 +108,7 @@ 3.25.3 1.3.2 3.1.0 + 6.1.0 9.4.54.v20240208 3.1.0 1.1.0.Final @@ -406,7 +407,12 @@ javax.servlet-api ${servlet_version} - + + jakarta.servlet + jakarta.servlet-api + ${servlet6_version} + provided + com.squareup.okhttp3 okhttp @@ -1030,6 +1036,12 @@ + + skip-spotless + + true + + diff --git a/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml b/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml index a850d772318..0577d9d0aef 100644 --- a/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml +++ b/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml @@ -204,5 +204,11 @@ + + skip-spotless + + true + + diff --git a/dubbo-distribution/dubbo-all-shaded/pom.xml b/dubbo-distribution/dubbo-all-shaded/pom.xml index bc7ca34f7f5..c28dd85206a 100644 --- a/dubbo-distribution/dubbo-all-shaded/pom.xml +++ b/dubbo-distribution/dubbo-all-shaded/pom.xml @@ -133,7 +133,13 @@ compile true - + + org.apache.dubbo + dubbo-triple-servlet + ${project.version} + compile + true + org.apache.dubbo @@ -488,6 +494,7 @@ org.apache.dubbo:dubbo-rest-jaxrs org.apache.dubbo:dubbo-rest-servlet org.apache.dubbo:dubbo-rest-spring + org.apache.dubbo:dubbo-triple-servlet org.apache.dubbo:dubbo-serialization-api org.apache.dubbo:dubbo-serialization-hessian2 org.apache.dubbo:dubbo-serialization-fastjson2 diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index db8f34bf76a..9c157fb8163 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -290,6 +290,13 @@ compile true + + org.apache.dubbo + dubbo-triple-servlet + ${project.version} + compile + true + @@ -528,6 +535,7 @@ org.apache.dubbo:dubbo-rest-jaxrs org.apache.dubbo:dubbo-rest-servlet org.apache.dubbo:dubbo-rest-spring + org.apache.dubbo:dubbo-triple-servlet org.apache.dubbo:dubbo-serialization-api org.apache.dubbo:dubbo-serialization-hessian2 org.apache.dubbo:dubbo-serialization-fastjson2 diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml index 47175873452..32665eac9d1 100644 --- a/dubbo-distribution/dubbo-bom/pom.xml +++ b/dubbo-distribution/dubbo-bom/pom.xml @@ -344,6 +344,11 @@ dubbo-rest-spring ${project.version} + + org.apache.dubbo + dubbo-triple-servlet + ${project.version} + @@ -485,6 +490,11 @@ dubbo-spring-boot-autoconfigure ${project.version} + + org.apache.dubbo + dubbo-spring-boot-3-autoconfigure + ${project.version} + org.apache.dubbo dubbo-spring-boot-compatible diff --git a/dubbo-distribution/pom.xml b/dubbo-distribution/pom.xml index e3d4ca1a88a..a61e230e9b8 100644 --- a/dubbo-distribution/pom.xml +++ b/dubbo-distribution/pom.xml @@ -115,5 +115,11 @@ + + skip-spotless + + true + + diff --git a/dubbo-plugin/dubbo-triple-servlet/pom.xml b/dubbo-plugin/dubbo-triple-servlet/pom.xml new file mode 100644 index 00000000000..ee6d22318a2 --- /dev/null +++ b/dubbo-plugin/dubbo-triple-servlet/pom.xml @@ -0,0 +1,107 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-plugin + ${revision} + ../pom.xml + + + dubbo-triple-servlet + + + 4.0.1 + ${project.build.directory}/generated-sources/java/org/apache/dubbo/rpc/protocol/tri/servlet/jakarta + + + + + org.apache.dubbo + dubbo-rpc-triple + ${project.version} + + + javax.servlet + javax.servlet-api + ${servlet4_version} + provided + + + jakarta.servlet + jakarta.servlet-api + provided + + + org.apache.dubbo + dubbo-remoting-netty4 + ${project.version} + test + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + copy-sources + + run + + generate-sources + + + + + + + + + + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-sources + + add-source + + generate-sources + + + ${project.build.directory}/generated-sources/java + + + + + + + + diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java new file mode 100644 index 00000000000..83c46180c7b --- /dev/null +++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.tri.servlet; + +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.h2.Http2Header; + +import javax.servlet.http.HttpServletRequest; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +final class HttpMetadataAdapter implements Http2Header { + + private final HttpServletRequest request; + + private HttpHeaders headers; + + HttpMetadataAdapter(HttpServletRequest request) { + this.request = request; + } + + @Override + public HttpHeaders headers() { + HttpHeaders headers = this.headers; + if (headers == null) { + headers = new HttpHeaders(); + Enumeration en = request.getHeaderNames(); + while (en.hasMoreElements()) { + String key = en.nextElement(); + List values = new ArrayList<>(1); + Enumeration ven = request.getHeaders(key); + while (ven.hasMoreElements()) { + values.add(ven.nextElement()); + } + headers.put(key, values); + } + this.headers = headers; + } + return headers; + } + + @Override + public String method() { + return request.getMethod(); + } + + @Override + public String path() { + String query = request.getQueryString(); + return query == null ? request.getRequestURI() : request.getRequestURI() + '?' + query; + } + + @Override + public String status() { + return null; + } + + @Override + public int id() { + return -1; + } + + @Override + public boolean isEndStream() { + return false; + } +} diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java new file mode 100644 index 00000000000..fc0306a472e --- /dev/null +++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.tri.servlet; + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessageFrame; + +import javax.servlet.AsyncContext; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.ByteArrayOutputStream; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.CompletableFuture; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_IO_EXCEPTION; + +final class ServletStreamChannel implements H2StreamChannel { + + private static final ErrorTypeAwareLogger LOG = LoggerFactory.getErrorTypeAwareLogger(ServletStreamChannel.class); + + private final HttpServletRequest request; + private final HttpServletResponse response; + private final AsyncContext context; + + ServletStreamChannel(HttpServletRequest request, HttpServletResponse response, AsyncContext context) { + this.request = request; + this.response = response; + this.context = context; + } + + @Override + public CompletableFuture writeResetFrame(long errorCode) { + try { + if (errorCode == 0L) { + response.getOutputStream().close(); + } else if (errorCode >= 300 && errorCode < 600) { + response.sendError((int) errorCode); + } else { + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } catch (Throwable t) { + LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to close response", t); + } finally { + context.complete(); + } + return CompletableFuture.completedFuture(null); + } + + @Override + public Http2OutputMessage newOutputMessage(boolean endStream) { + return new Http2OutputMessageFrame(new ByteArrayOutputStream(256), endStream); + } + + @Override + public CompletableFuture writeHeader(HttpMetadata httpMetadata) { + boolean endStream = ((Http2Header) httpMetadata).isEndStream(); + try { + HttpHeaders headers = httpMetadata.headers(); + if (endStream) { + response.setTrailerFields(() -> { + Map map = new HashMap<>(); + for (Entry> entry : headers.entrySet()) { + map.put(entry.getKey(), entry.getValue().get(0)); + } + return map; + }); + } else { + for (Entry> entry : headers.entrySet()) { + String key = entry.getKey(); + List values = entry.getValue(); + if (HttpHeaderNames.STATUS.getName().equals(key)) { + response.setStatus(Integer.parseInt(values.get(0))); + continue; + } + if (values.size() == 1) { + response.setHeader(key, values.get(0)); + } else { + for (int i = 0, size = values.size(); i < size; i++) { + response.addHeader(key, values.get(i)); + } + } + } + } + } catch (Throwable t) { + LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to write header", t); + } finally { + if (endStream) { + context.complete(); + } + } + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) { + boolean endStream = ((Http2OutputMessage) httpOutputMessage).isEndStream(); + try { + ByteArrayOutputStream bos = (ByteArrayOutputStream) httpOutputMessage.getBody(); + ServletOutputStream out = response.getOutputStream(); + if (!"HTTP/2.0".equals(request.getProtocol())) { + response.setContentLength(bos.size()); + } + bos.writeTo(out); + out.flush(); + } catch (Throwable t) { + LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to write message", t); + } finally { + if (endStream) { + context.complete(); + } + } + return CompletableFuture.completedFuture(null); + } + + @Override + public SocketAddress remoteAddress() { + return InetSocketAddress.createUnresolved(request.getRemoteAddr(), request.getRemotePort()); + } + + @Override + public SocketAddress localAddress() { + return InetSocketAddress.createUnresolved(request.getLocalAddr(), request.getLocalPort()); + } + + @Override + public void flush() {} +} diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java new file mode 100644 index 00000000000..ec1f87e3de3 --- /dev/null +++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.tri.servlet; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.io.StreamUtils; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame; +import org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory; +import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.PathResolver; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.protocol.tri.ServletExchanger; +import org.apache.dubbo.rpc.protocol.tri.TripleConstant; +import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum; +import org.apache.dubbo.rpc.protocol.tri.TripleProtocol; +import org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcHeaderNames; +import org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcHttp2ServerTransportListener; +import org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcUtils; +import org.apache.dubbo.rpc.protocol.tri.h12.http2.GenericHttp2ServerTransportListenerFactory; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.DefaultRequestMappingRegistry; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.RequestMappingRegistry; + +import javax.servlet.AsyncContext; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Set; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_IO_EXCEPTION; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR; + +public class TripleFilter implements Filter { + + private static final ErrorTypeAwareLogger LOG = LoggerFactory.getErrorTypeAwareLogger(TripleFilter.class); + + private PathResolver pathResolver; + private RequestMappingRegistry mappingRegistry; + private int defaultTimeout = 30_000; + + @Override + public void init(FilterConfig config) { + FrameworkModel frameworkModel = FrameworkModel.defaultModel(); + pathResolver = frameworkModel.getDefaultExtension(PathResolver.class); + mappingRegistry = frameworkModel.getBeanFactory().getOrRegisterBean(DefaultRequestMappingRegistry.class); + String timeoutString = config.getInitParameter("timeout"); + defaultTimeout = timeoutString == null ? 30000 : Integer.parseInt(timeoutString); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws ServletException, IOException { + HttpServletRequest hRequest = (HttpServletRequest) request; + HttpServletResponse hResponse = (HttpServletResponse) response; + + if (!hasServiceMapping(hRequest) && !mappingRegistry.exists(hRequest.getRequestURI(), hRequest.getMethod())) { + chain.doFilter(request, response); + return; + } + + AsyncContext context = request.startAsync(); + try { + H2StreamChannel streamChannel = new ServletStreamChannel(hRequest, hResponse, context); + Http2TransportListener listener = determineHttp2ServerTransportListenerFactory(request.getContentType()) + .newInstance(streamChannel, ServletExchanger.getUrl(), FrameworkModel.defaultModel()); + + context.setTimeout(resolveTimeout(hRequest, listener instanceof GrpcHttp2ServerTransportListener)); + + listener.onMetadata(new HttpMetadataAdapter(hRequest)); + + ByteArrayOutputStream os; + try { + os = new ByteArrayOutputStream(1024); + StreamUtils.copy(request.getInputStream(), os); + } catch (Throwable t) { + LOG.error(COMMON_IO_EXCEPTION, "", "", "Failed to read input", t); + try { + hResponse.sendError(HttpServletResponse.SC_BAD_REQUEST); + } finally { + context.complete(); + } + return; + } + listener.onData(new Http2InputMessageFrame(new ByteArrayInputStream(os.toByteArray()), true)); + } catch (Throwable t) { + LOG.error(INTERNAL_ERROR, "", "", "Failed to process request", t); + try { + hResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } finally { + context.complete(); + } + } + } + + @Override + public void destroy() {} + + private boolean hasServiceMapping(HttpServletRequest request) { + String uri = request.getRequestURI(); + + int index = uri.indexOf('/', 1); + if (index == -1) { + return false; + } + if (uri.indexOf('/', index + 1) != -1) { + return false; + } + + String serviceName = uri.substring(1, index); + String version = request.getHeader(TripleHeaderEnum.SERVICE_VERSION.getHeader()); + String group = request.getHeader(TripleHeaderEnum.SERVICE_GROUP.getHeader()); + String key = URL.buildKey(serviceName, group, version); + Invoker invoker = pathResolver.resolve(key); + if (invoker == null && TripleProtocol.RESOLVE_FALLBACK_TO_DEFAULT) { + invoker = pathResolver.resolve(URL.buildKey(serviceName, group, TripleConstant.DEFAULT_VERSION)); + if (invoker == null) { + return pathResolver.resolve(serviceName) != null; + } + } + + return true; + } + + private Http2ServerTransportListenerFactory determineHttp2ServerTransportListenerFactory(String contentType) { + Set http2ServerTransportListenerFactories = FrameworkModel.defaultModel() + .getExtensionLoader(Http2ServerTransportListenerFactory.class) + .getSupportedExtensionInstances(); + for (Http2ServerTransportListenerFactory factory : http2ServerTransportListenerFactories) { + if (factory.supportContentType(contentType)) { + return factory; + } + } + return GenericHttp2ServerTransportListenerFactory.INSTANCE; + } + + private int resolveTimeout(HttpServletRequest request, boolean isGrpc) { + try { + if (isGrpc) { + String timeoutString = request.getHeader(GrpcHeaderNames.GRPC_TIMEOUT.getName()); + if (timeoutString != null) { + Long timeout = GrpcUtils.parseTimeoutToMills(timeoutString); + if (timeout != null) { + return timeout.intValue() + 2000; + } + } + } else { + String timeoutString = request.getHeader(TripleHeaderEnum.SERVICE_TIMEOUT.getHeader()); + if (timeoutString != null) { + return Integer.parseInt(timeoutString) + 2000; + } + } + } catch (Throwable ignored) { + } + return defaultTimeout; + } +} diff --git a/dubbo-plugin/pom.xml b/dubbo-plugin/pom.xml index fa1466ef0a2..df9b5dccdeb 100644 --- a/dubbo-plugin/pom.xml +++ b/dubbo-plugin/pom.xml @@ -43,6 +43,7 @@ dubbo-rest-jaxrs dubbo-rest-servlet dubbo-rest-spring + dubbo-triple-servlet false diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java new file mode 100644 index 00000000000..bcb52ffa625 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.tri; + +import org.apache.dubbo.common.URL; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; + +public final class ServletExchanger { + + private static final AtomicReference defaultUrl = new AtomicReference<>(); + + private ServletExchanger() {} + + public static void bind(URL url) { + defaultUrl.compareAndSet(null, url); + } + + public static URL getUrl() { + return Objects.requireNonNull(defaultUrl.get(), "ServletExchanger not bound to triple protocol"); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java index fcc85f391ef..7a190e58c7e 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java @@ -23,6 +23,8 @@ import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.common.utils.ExecutorUtil; +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.nested.TripleConfig; import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.remoting.exchange.PortUnificationExchanger; @@ -159,7 +161,13 @@ public void afterUnExport() { ExecutorRepository.getInstance(url.getOrDefaultApplicationModel()) .createExecutorIfAbsent(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)); - PortUnificationExchanger.bind(url, new DefaultPuHandler()); + TripleConfig tripleConfig = ConfigManager.getProtocol(url).getTriple(); + if (Boolean.TRUE.equals(tripleConfig.getEnableServlet())) { + ServletExchanger.bind(url); + } else { + PortUnificationExchanger.bind(url, new DefaultPuHandler()); + } + optimizeSerialization(url); return exporter; } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java index 81680ac4f24..ffb35027787 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/DefaultRequestMappingRegistry.java @@ -206,6 +206,23 @@ public HandlerMeta lookup(HttpRequest request) { return handler; } + @Override + public boolean exists(String path, String method) { + List> matches = new ArrayList<>(); + lock.readLock().lock(); + try { + tree.match(path, matches); + } finally { + lock.readLock().unlock(); + } + for (int i = 0, size = matches.size(); i < size; i++) { + if (matches.get(i).getValue().mapping.matchMethod(method)) { + return true; + } + } + return false; + } + private static final class Registration { RequestMapping mapping; HandlerMeta meta; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java index 5d00ad8eac3..3dd19f4f2b8 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMapping.java @@ -106,6 +106,10 @@ public RequestMapping match(HttpRequest request, PathExpression path) { return doMatch(request, new PathCondition(path)); } + public boolean matchMethod(String method) { + return methodsCondition == null || methodsCondition.getMethods().contains(method); + } + @Override public RequestMapping match(HttpRequest request) { return doMatch(request, null); diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMappingRegistry.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMappingRegistry.java index b7dfb559946..444854c5e78 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMappingRegistry.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/RequestMappingRegistry.java @@ -31,5 +31,7 @@ public interface RequestMappingRegistry { HandlerMeta lookup(HttpRequest request); + boolean exists(String path, String method); + void destroy(); } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/MethodsCondition.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/MethodsCondition.java index fa01f67194e..96b8eec3c49 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/MethodsCondition.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/condition/MethodsCondition.java @@ -38,6 +38,10 @@ private MethodsCondition(Set methods) { this.methods = methods; } + public Set getMethods() { + return methods; + } + @Override public MethodsCondition combine(MethodsCondition other) { Set set = new HashSet<>(methods); diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml new file mode 100644 index 00000000000..bfaf876099d --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/pom.xml @@ -0,0 +1,69 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-parent + ${revision} + ../../pom.xml + + + dubbo-spring-boot-3-autoconfigure + jar + Apache Dubbo Spring Boot 3 Auto-Configure + + + 3.2.1 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-autoconfigure + true + + + + + org.apache.dubbo + dubbo + ${project.version} + true + + + + jakarta.servlet + jakarta.servlet-api + true + + + diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java new file mode 100644 index 00000000000..82d580a0013 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.spring.boot.autoconfigure; + +import org.apache.dubbo.rpc.protocol.tri.servlet.jakarta.TripleFilter; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +@Conditional(SpringBoot3Condition.class) +public class DubboTriple3AutoConfiguration { + + public static final String PREFIX = "dubbo.protocol.triple"; + + @Configuration(proxyBeanMethods = false) + @ConditionalOnWebApplication(type = Type.SERVLET) + @ConditionalOnProperty(prefix = PREFIX, name = "enable-servlet") + public static class TripleServletConfiguration { + + @Bean + public FilterRegistrationBean tripleProtocolFilter( + @Value("${" + PREFIX + ".servlet-filter-url-patterns:/*}") String[] urlPatterns, + @Value("${" + PREFIX + ".servlet-filter-order:-1000000}") int order) { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new TripleFilter()); + registrationBean.addUrlPatterns(urlPatterns); + registrationBean.setOrder(order); + return registrationBean; + } + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java new file mode 100644 index 00000000000..19e1ecc7209 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.spring.boot.autoconfigure; + +import org.springframework.boot.SpringBootVersion; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class SpringBoot3Condition implements Condition { + + public static boolean IS_SPRING_BOOT_3 = SpringBootVersion.getVersion().charAt(0) >= 3; + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return IS_SPRING_BOOT_3; + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring.factories b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000000..3ee254abc63 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.apache.dubbo.spring.boot.autoconfigure.DubboTriple3AutoConfiguration diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..03e1ef54eca --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.apache.dubbo.spring.boot.autoconfigure.DubboTriple3AutoConfiguration diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml index ddc4a741274..af3d04948da 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/pom.xml @@ -71,6 +71,12 @@ true + + javax.servlet + javax.servlet-api + provided + + org.springframework.boot diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java new file mode 100644 index 00000000000..a3f9ed36ba0 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.spring.boot.autoconfigure; + +import org.apache.dubbo.rpc.protocol.tri.servlet.TripleFilter; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +@Conditional(SpringBoot12Condition.class) +public class DubboTripleAutoConfiguration { + + public static final String PREFIX = "dubbo.protocol.triple"; + + @Configuration(proxyBeanMethods = false) + @ConditionalOnWebApplication(type = Type.SERVLET) + @ConditionalOnProperty(prefix = PREFIX, name = "enable-servlet") + public static class TripleServletConfiguration { + + @Bean + public FilterRegistrationBean tripleProtocolFilter( + @Value("${" + PREFIX + ".servlet-filter-url-patterns:/*}") String[] urlPatterns, + @Value("${" + PREFIX + ".servlet-filter-order:-1000000}") int order) { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new TripleFilter()); + registrationBean.addUrlPatterns(urlPatterns); + registrationBean.setOrder(order); + return registrationBean; + } + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java new file mode 100644 index 00000000000..bcd2b7d1681 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.spring.boot.autoconfigure; + +import org.springframework.boot.SpringBootVersion; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class SpringBoot12Condition implements Condition { + + public static boolean IS_SPRING_BOOT_12 = SpringBootVersion.getVersion().charAt(0) < 3; + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return IS_SPRING_BOOT_12; + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index c88a29b2447..38eb67828f8 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBinding2AutoConfiguration \ No newline at end of file +org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBinding2AutoConfiguration,\ +org.apache.dubbo.spring.boot.autoconfigure.DubboTripleAutoConfiguration diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index be0f66976d4..dd87d13a986 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ org.apache.dubbo.spring.boot.autoconfigure.DubboRelaxedBinding2AutoConfiguration +org.apache.dubbo.spring.boot.autoconfigure.DubboTripleAutoConfiguration diff --git a/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml index 7abb4ce74f6..b21cb786f88 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-starter/pom.xml @@ -41,6 +41,11 @@ dubbo-spring-boot-autoconfigure ${project.version} + + org.apache.dubbo + dubbo-spring-boot-3-autoconfigure + ${project.version} + diff --git a/dubbo-spring-boot/pom.xml b/dubbo-spring-boot/pom.xml index d198c794896..f6ce5403328 100644 --- a/dubbo-spring-boot/pom.xml +++ b/dubbo-spring-boot/pom.xml @@ -32,6 +32,7 @@ dubbo-spring-boot-actuator dubbo-spring-boot-autoconfigure + dubbo-spring-boot-3-autoconfigure dubbo-spring-boot-compatible dubbo-spring-boot-starter dubbo-spring-boot-starters diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index b86a36b8901..7b0774551bb 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -261,6 +261,11 @@ dubbo-rest-spring ${project.version} + + org.apache.dubbo + dubbo-triple-servlet + ${project.version} + @@ -372,6 +377,11 @@ dubbo-spring-boot-autoconfigure ${project.version} + + org.apache.dubbo + dubbo-spring-boot-3-autoconfigure + ${project.version} + org.apache.dubbo dubbo-spring-boot-actuator-compatible diff --git a/pom.xml b/pom.xml index a216e2afd1d..8bfadb1f1c7 100644 --- a/pom.xml +++ b/pom.xml @@ -911,6 +911,12 @@ + + skip-spotless + + true + + From 99623665702e48870433c73c57721dd63352403b Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Sun, 16 Jun 2024 15:17:39 +0800 Subject: [PATCH 2/3] fix(servlet): Some bugfix --- .../servlet/ServletHttpRequestAdaptee.java | 3 +- .../tri/servlet/ServletStreamChannel.java | 3 +- .../protocol/tri/servlet/TripleFilter.java | 4 +- .../dubbo/remoting/http12/HttpVersion.java | 38 +++++++++++++++++++ .../rpc/protocol/tri/ServletExchanger.java | 15 ++++++-- .../rpc/protocol/tri/TripleHttp2Protocol.java | 5 ++- .../rpc/protocol/tri/TripleProtocol.java | 19 ++++++++-- .../tri/h12/TripleProtocolDetector.java | 16 +------- .../DubboTriple3AutoConfiguration.java | 8 +++- .../autoconfigure/SpringBoot3Condition.java | 2 +- .../DubboTripleAutoConfiguration.java | 9 ++++- .../autoconfigure/SpringBoot12Condition.java | 2 +- 12 files changed, 93 insertions(+), 31 deletions(-) create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpVersion.java diff --git a/dubbo-plugin/dubbo-rest-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpRequestAdaptee.java b/dubbo-plugin/dubbo-rest-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpRequestAdaptee.java index 102ae8402b6..6099a6c8d39 100644 --- a/dubbo-plugin/dubbo-rest-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpRequestAdaptee.java +++ b/dubbo-plugin/dubbo-rest-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/servlet/ServletHttpRequestAdaptee.java @@ -19,6 +19,7 @@ import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.remoting.http12.HttpChannel; import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpVersion; import org.apache.dubbo.remoting.http12.message.DefaultHttpRequest; import javax.servlet.AsyncContext; @@ -319,7 +320,7 @@ public Map getParameterMap() { @Override public String getProtocol() { - return isHttp2() ? "HTTP/2.0" : "HTTP/1.1"; + return isHttp2() ? HttpVersion.HTTP2.getProtocol() : HttpVersion.HTTP1.getProtocol(); } @Override diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java index fc0306a472e..d5f0c7d39fd 100644 --- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java +++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/ServletStreamChannel.java @@ -22,6 +22,7 @@ import org.apache.dubbo.remoting.http12.HttpHeaders; import org.apache.dubbo.remoting.http12.HttpMetadata; import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.HttpVersion; import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; import org.apache.dubbo.remoting.http12.h2.Http2Header; import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage; @@ -126,7 +127,7 @@ public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) try { ByteArrayOutputStream bos = (ByteArrayOutputStream) httpOutputMessage.getBody(); ServletOutputStream out = response.getOutputStream(); - if (!"HTTP/2.0".equals(request.getProtocol())) { + if (!HttpVersion.HTTP2.getProtocol().equals(request.getProtocol())) { response.setContentLength(bos.size()); } bos.writeTo(out); diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java index ec1f87e3de3..17f1d107a64 100644 --- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java +++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java @@ -62,7 +62,7 @@ public class TripleFilter implements Filter { private PathResolver pathResolver; private RequestMappingRegistry mappingRegistry; - private int defaultTimeout = 30_000; + private int defaultTimeout; @Override public void init(FilterConfig config) { @@ -70,7 +70,7 @@ public void init(FilterConfig config) { pathResolver = frameworkModel.getDefaultExtension(PathResolver.class); mappingRegistry = frameworkModel.getBeanFactory().getOrRegisterBean(DefaultRequestMappingRegistry.class); String timeoutString = config.getInitParameter("timeout"); - defaultTimeout = timeoutString == null ? 30000 : Integer.parseInt(timeoutString); + defaultTimeout = timeoutString == null ? 180_000 : Integer.parseInt(timeoutString); } @Override diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpVersion.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpVersion.java new file mode 100644 index 00000000000..f7fa9f2375e --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpVersion.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12; + +public enum HttpVersion { + HTTP1("http1", "HTTP/1.1"), + HTTP2("http2", "HTTP/2.0"); + + private final String version; + private final String protocol; + + HttpVersion(String version, String protocol) { + this.version = version; + this.protocol = protocol; + } + + public String getVersion() { + return version; + } + + public String getProtocol() { + return protocol; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java index bcb52ffa625..9e899b66d80 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ServletExchanger.java @@ -23,15 +23,24 @@ public final class ServletExchanger { - private static final AtomicReference defaultUrl = new AtomicReference<>(); + private static final AtomicReference url = new AtomicReference<>(); + private static final AtomicReference serverPort = new AtomicReference<>(); private ServletExchanger() {} public static void bind(URL url) { - defaultUrl.compareAndSet(null, url); + ServletExchanger.url.compareAndSet(null, url); + } + + public static void bindServerPort(int serverPort) { + ServletExchanger.serverPort.compareAndSet(null, serverPort); } public static URL getUrl() { - return Objects.requireNonNull(defaultUrl.get(), "ServletExchanger not bound to triple protocol"); + return Objects.requireNonNull(url.get(), "ServletExchanger not bound to triple protocol"); + } + + public static Integer getServerPort() { + return serverPort.get(); } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java index 7566851c8d6..011881ddc9b 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java @@ -25,6 +25,7 @@ import org.apache.dubbo.remoting.api.pu.ChannelHandlerPretender; import org.apache.dubbo.remoting.api.pu.ChannelOperator; import org.apache.dubbo.remoting.api.ssl.ContextOperator; +import org.apache.dubbo.remoting.http12.HttpVersion; import org.apache.dubbo.remoting.http12.netty4.HttpWriteQueueHandler; import org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1Codec; import org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1ConnectionHandler; @@ -116,13 +117,13 @@ public void configServerProtocolHandler(URL url, ChannelOperator operator) { List channelHandlerPretenders = new ArrayList<>(); try { // h1 - if (TripleProtocolDetector.HttpVersion.HTTP1.getVersion().equals(httpVersion)) { + if (HttpVersion.HTTP1.getVersion().equals(httpVersion)) { configurerHttp1Handlers(url, channelHandlerPretenders); return; } // h2 - if (TripleProtocolDetector.HttpVersion.HTTP2.getVersion().equals(httpVersion)) { + if (HttpVersion.HTTP2.getVersion().equals(httpVersion)) { configurerHttp2Handlers(url, channelHandlerPretenders); } } finally { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java index a399a46d861..80f56d5de1a 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java @@ -23,13 +23,13 @@ import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.common.utils.ExecutorUtil; +import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.nested.TripleConfig; import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.remoting.exchange.Http3Exchanger; import org.apache.dubbo.remoting.exchange.PortUnificationExchanger; -import org.apache.dubbo.rpc.Constants; import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.PathResolver; @@ -55,11 +55,13 @@ import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; import static org.apache.dubbo.config.Constants.CLIENT_THREAD_POOL_NAME; import static org.apache.dubbo.config.Constants.SERVER_THREAD_POOL_NAME; +import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY; import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_IGNORE_1_0_0_KEY; import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_PASS_THROUGH_STANDARD_HTTP_HEADERS; import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_RESOLVE_FALLBACK_TO_DEFAULT_KEY; import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_SUPPORT_NO_LOWER_HEADER_KEY; import static org.apache.dubbo.rpc.Constants.H3_SETTINGS_HTTP3_ENABLE; +import static org.apache.dubbo.rpc.Constants.HTTP3_KEY; public class TripleProtocol extends AbstractProtocol { @@ -169,9 +171,20 @@ public void afterUnExport() { .createExecutorIfAbsent(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)); TripleConfig tripleConfig = ConfigManager.getProtocol(url).getTriple(); + boolean bindPort = true; if (Boolean.TRUE.equals(tripleConfig.getEnableServlet())) { + int port = url.getParameter(BIND_PORT_KEY, url.getPort()); + Integer serverPort = ServletExchanger.getServerPort(); + if (serverPort == null) { + if (NetUtils.isPortInUsed(port)) { + bindPort = false; + } + } else if (serverPort == port) { + bindPort = false; + } ServletExchanger.bind(url); - } else { + } + if (bindPort) { PortUnificationExchanger.bind(url, new DefaultPuHandler()); } @@ -223,6 +236,6 @@ public void destroy() { } public static boolean isHttp3Enabled(URL url) { - return HTTP3_ENABLED || url.getParameter(Constants.HTTP3_KEY, false); + return HTTP3_ENABLED || url.getParameter(HTTP3_KEY, false); } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java index 5fa91a97f7c..213d97624a1 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java @@ -21,6 +21,7 @@ import org.apache.dubbo.remoting.buffer.ChannelBuffer; import org.apache.dubbo.remoting.buffer.ChannelBuffers; import org.apache.dubbo.remoting.http12.HttpMethods; +import org.apache.dubbo.remoting.http12.HttpVersion; import io.netty.handler.codec.http2.Http2CodecUtil; @@ -74,19 +75,4 @@ private static boolean isHttp(byte[] magic) { } return false; } - - public enum HttpVersion { - HTTP1("http1"), - HTTP2("http2"); - - private final String version; - - HttpVersion(String version) { - this.version = version; - } - - public String getVersion() { - return version; - } - } } diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java index 82d580a0013..80fd90ef39f 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java @@ -16,9 +16,12 @@ */ package org.apache.dubbo.spring.boot.autoconfigure; +import org.apache.dubbo.rpc.protocol.tri.ServletExchanger; import org.apache.dubbo.rpc.protocol.tri.servlet.jakarta.TripleFilter; +import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; @@ -34,6 +37,7 @@ public class DubboTriple3AutoConfiguration { public static final String PREFIX = "dubbo.protocol.triple"; @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(Filter.class) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnProperty(prefix = PREFIX, name = "enable-servlet") public static class TripleServletConfiguration { @@ -41,7 +45,9 @@ public static class TripleServletConfiguration { @Bean public FilterRegistrationBean tripleProtocolFilter( @Value("${" + PREFIX + ".servlet-filter-url-patterns:/*}") String[] urlPatterns, - @Value("${" + PREFIX + ".servlet-filter-order:-1000000}") int order) { + @Value("${" + PREFIX + ".servlet-filter-order:-1000000}") int order, + @Value("${server.port:8080}") int serverPort) { + ServletExchanger.bindServerPort(serverPort); FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new TripleFilter()); registrationBean.addUrlPatterns(urlPatterns); diff --git a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java index 19e1ecc7209..489446f1d75 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java +++ b/dubbo-spring-boot/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot3Condition.java @@ -23,7 +23,7 @@ public class SpringBoot3Condition implements Condition { - public static boolean IS_SPRING_BOOT_3 = SpringBootVersion.getVersion().charAt(0) >= 3; + public static boolean IS_SPRING_BOOT_3 = SpringBootVersion.getVersion().charAt(0) >= '3'; @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java index a3f9ed36ba0..114ab7cadf6 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java @@ -16,9 +16,13 @@ */ package org.apache.dubbo.spring.boot.autoconfigure; +import org.apache.dubbo.rpc.protocol.tri.ServletExchanger; import org.apache.dubbo.rpc.protocol.tri.servlet.TripleFilter; +import javax.servlet.Filter; + import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; @@ -34,6 +38,7 @@ public class DubboTripleAutoConfiguration { public static final String PREFIX = "dubbo.protocol.triple"; @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(Filter.class) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnProperty(prefix = PREFIX, name = "enable-servlet") public static class TripleServletConfiguration { @@ -41,7 +46,9 @@ public static class TripleServletConfiguration { @Bean public FilterRegistrationBean tripleProtocolFilter( @Value("${" + PREFIX + ".servlet-filter-url-patterns:/*}") String[] urlPatterns, - @Value("${" + PREFIX + ".servlet-filter-order:-1000000}") int order) { + @Value("${" + PREFIX + ".servlet-filter-order:-1000000}") int order, + @Value("${server.port:8080}") int serverPort) { + ServletExchanger.bindServerPort(serverPort); FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new TripleFilter()); registrationBean.addUrlPatterns(urlPatterns); diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java index bcd2b7d1681..9bf7fdf7609 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java +++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/SpringBoot12Condition.java @@ -23,7 +23,7 @@ public class SpringBoot12Condition implements Condition { - public static boolean IS_SPRING_BOOT_12 = SpringBootVersion.getVersion().charAt(0) < 3; + public static boolean IS_SPRING_BOOT_12 = SpringBootVersion.getVersion().charAt(0) < '3'; @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { From 7a76196c52b9107f517f7288aeaf49b4086f5ca3 Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Sun, 16 Jun 2024 17:08:15 +0800 Subject: [PATCH 3/3] fix(servlet): Some protocol config read bugfix --- .../src/main/java/org/apache/dubbo/rpc/Constants.java | 1 + .../org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java index 0e81a1433b6..0e6100827d2 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java @@ -106,6 +106,7 @@ public interface Constants { String H2_SETTINGS_PASS_THROUGH_STANDARD_HTTP_HEADERS = "dubbo.rpc.tri.pass-through-standard-http-headers"; String H3_SETTINGS_HTTP3_ENABLE = "dubbo.protocol.triple.enable-http3"; + String H3_SETTINGS_SERVLET_ENABLE = "dubbo.protocol.triple.enable-servlet"; String ADAPTIVE_LOADBALANCE_ATTACHMENT_KEY = "lb_adaptive"; String ADAPTIVE_LOADBALANCE_START_TIME = "adaptive_startTime"; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java index 80f56d5de1a..9e5088a25db 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocol.java @@ -24,8 +24,6 @@ import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.common.utils.ExecutorUtil; import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.config.nested.TripleConfig; import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.remoting.exchange.Http3Exchanger; @@ -61,6 +59,7 @@ import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_RESOLVE_FALLBACK_TO_DEFAULT_KEY; import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_SUPPORT_NO_LOWER_HEADER_KEY; import static org.apache.dubbo.rpc.Constants.H3_SETTINGS_HTTP3_ENABLE; +import static org.apache.dubbo.rpc.Constants.H3_SETTINGS_SERVLET_ENABLE; import static org.apache.dubbo.rpc.Constants.HTTP3_KEY; public class TripleProtocol extends AbstractProtocol { @@ -77,6 +76,7 @@ public class TripleProtocol extends AbstractProtocol { public static boolean RESOLVE_FALLBACK_TO_DEFAULT = true; public static boolean PASS_THROUGH_STANDARD_HTTP_HEADERS = false; public static boolean HTTP3_ENABLED = false; + public static boolean SERVLET_ENABLED = false; public TripleProtocol(FrameworkModel frameworkModel) { this.frameworkModel = frameworkModel; @@ -94,6 +94,7 @@ public TripleProtocol(FrameworkModel frameworkModel) { Configuration globalConf = ConfigurationUtils.getGlobalConfiguration(frameworkModel.defaultApplication()); HTTP3_ENABLED = globalConf.getBoolean(H3_SETTINGS_HTTP3_ENABLE, false); + SERVLET_ENABLED = globalConf.getBoolean(H3_SETTINGS_SERVLET_ENABLE, false); } @Override @@ -170,9 +171,8 @@ public void afterUnExport() { ExecutorRepository.getInstance(url.getOrDefaultApplicationModel()) .createExecutorIfAbsent(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)); - TripleConfig tripleConfig = ConfigManager.getProtocol(url).getTriple(); boolean bindPort = true; - if (Boolean.TRUE.equals(tripleConfig.getEnableServlet())) { + if (SERVLET_ENABLED) { int port = url.getParameter(BIND_PORT_KEY, url.getPort()); Integer serverPort = ServletExchanger.getServerPort(); if (serverPort == null) {