From 25b73b1a135ae75ed50c68e6b5acd694067fd325 Mon Sep 17 00:00:00 2001 From: zhaoyunxing Date: Wed, 27 Dec 2023 23:19:51 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9ADubboService=20annotation=20suppor?= =?UTF-8?q?t=20custom=20serialization=20(#13553)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dubbo/config/annotation/DubboService.java | 29 ++++++++++++- dubbo-config/dubbo-config-api/pom.xml | 7 ++++ .../config/utils/ConfigValidationUtils.java | 9 ++++ .../dubbo/config/AbstractConfigTest.java | 25 +++++++++++ .../config/bootstrap/DubboBootstrapTest.java | 42 ++++++++++++------- .../spring/util/DubboAnnotationUtils.java | 4 +- 6 files changed, 98 insertions(+), 18 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java index a945909edf..905abe718c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java @@ -257,7 +257,17 @@ public @interface DubboService { String[] listener() default {}; /** - * Customized parameter key-value pair, for example: {key1, value1, key2, value2} + * Customized parameter key-value pair, for example: + *
+     *  ["a","b"] ==> {a=b}
+     *  [" a "," b "] ==> {a=b}
+     *  ["a=b"] ==>{a=b}
+     *  ["a:b"] ==>{a=b}
+     *  ["a=b","c","d"] ==>{a=b,c=d}
+     *  ["a","a:b"] ==>{a="a:b"}
+     *  ["a","a,b"] ==>{a="a,b"}
+     * 
+ * @see org.apache.dubbo.config.spring.util.DubboAnnotationUtils#convertParameters(java.lang.String[]) */ String[] parameters() default {}; @@ -327,4 +337,21 @@ public @interface DubboService { * Payload max length. */ String payload() default ""; + + /** + * The serialization type + */ + String serialization() default ""; + + /** + * If the parameter has a value, the consumer will read the parameter first. + * If the Dubbo Sdk you are using contains the serialization type, the serialization method specified by the argument is used. + *

+ * When this parameter is null or the serialization type specified by this parameter does not exist in the Dubbo SDK, the serialization type specified by serialization is used. + * If the Dubbo SDK if still does not exist, the default type of the Dubbo SDK is used. + * For Dubbo SDK >= 3.2, preferSerialization takes precedence over serialization + *

+ * The configuration supports multiple, which are separated by commas.Such as:fastjson2,fastjson,hessian2 + */ + String preferSerialization() default ""; } diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index e0be936386..63ed7f1e4d 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -135,6 +135,13 @@ test + + org.apache.dubbo + dubbo-serialization-jdk + ${project.parent.version} + test + + org.apache.dubbo dubbo-registry-multicast diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java index a37044cdca..728aa21845 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java @@ -132,6 +132,7 @@ import static org.apache.dubbo.remoting.Constants.CLIENT_KEY; import static org.apache.dubbo.remoting.Constants.CODEC_KEY; import static org.apache.dubbo.remoting.Constants.DISPATCHER_KEY; import static org.apache.dubbo.remoting.Constants.EXCHANGER_KEY; +import static org.apache.dubbo.remoting.Constants.PREFER_SERIALIZATION_KEY; import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY; import static org.apache.dubbo.remoting.Constants.SERVER_KEY; import static org.apache.dubbo.remoting.Constants.TELNET_KEY; @@ -602,6 +603,11 @@ public class ConfigValidationUtils { checkMultiExtension(config.getScopeModel(), Codec2.class, CODEC_KEY, config.getCodec()); checkMultiExtension( config.getScopeModel(), Serialization.class, SERIALIZATION_KEY, config.getSerialization()); + checkMultiExtension( + config.getScopeModel(), + Serialization.class, + PREFER_SERIALIZATION_KEY, + config.getPreferSerialization()); checkMultiExtension(config.getScopeModel(), Transporter.class, SERVER_KEY, config.getServer()); checkMultiExtension(config.getScopeModel(), Transporter.class, CLIENT_KEY, config.getClient()); } @@ -623,6 +629,9 @@ public class ConfigValidationUtils { checkMultiExtension(config.getScopeModel(), StatusChecker.class, STATUS_KEY, config.getStatus()); checkExtension(config.getScopeModel(), Transporter.class, TRANSPORTER_KEY, config.getTransporter()); checkExtension(config.getScopeModel(), Exchanger.class, EXCHANGER_KEY, config.getExchanger()); + checkMultiExtension(config.getScopeModel(), Serialization.class, SERIALIZATION_KEY, config.getSerialization()); + checkMultiExtension( + config.getScopeModel(), Serialization.class, PREFER_SERIALIZATION_KEY, config.getPreferSerialization()); } public static void validateConsumerConfig(ConsumerConfig config) { diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java index edaa1955b4..963e44eb28 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java @@ -70,6 +70,31 @@ class AbstractConfigTest { ConfigValidationUtils.validateProtocolConfig(protocolConfig); } + @Test + void testValidateProtocolConfigSerialization() { + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.setCodec("exchange"); + protocolConfig.setName("dubbo"); + protocolConfig.setHost("host"); + protocolConfig.setSerialization("fastjson2"); + protocolConfig.setPreferSerialization("hessian2,java,compactedjava,nativejava"); + ConfigValidationUtils.validateProtocolConfig(protocolConfig); + } + + @Test + void testValidateProtocolConfigViolateSerialization() { + + Assertions.assertThrowsExactly(IllegalStateException.class, () -> { + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.setCodec("exchange"); + protocolConfig.setName("dubbo"); + protocolConfig.setHost("host"); + protocolConfig.setSerialization("violate"); + protocolConfig.setPreferSerialization("violate"); + ConfigValidationUtils.validateProtocolConfig(protocolConfig); + }); + } + @Test void testAppendParameters1() { Map parameters = new HashMap(); diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java index fe791af7c0..df8a81224c 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java @@ -316,21 +316,6 @@ class DubboBootstrapTest { registryConfig.setUseAsMetadataCenter(false); registryConfig.setUseAsConfigCenter(false); - Exception exception = null; - try { - DubboBootstrap.getInstance() - .application(applicationConfig) - .registry(registryConfig) - .protocol(new ProtocolConfig(CommonConstants.DUBBO_PROTOCOL, -1)) - .service(service) - .start(); - } catch (Exception e) { - exception = e; - DubboBootstrap.reset(); - } - - Assertions.assertNotNull(exception); - DubboBootstrap.getInstance() .application(applicationConfig) .registry(registryConfig) @@ -342,6 +327,33 @@ class DubboBootstrapTest { assertMetadataService(DubboBootstrap.getInstance(), availablePort, false); } + @Test + void testRemoteMetadataServiceExporterCheckMetadataType() { + + Assertions.assertThrowsExactly(IllegalStateException.class, () -> { + ServiceConfig service = new ServiceConfig<>(); + service.setInterface(DemoService.class); + service.setRef(new DemoServiceImpl()); + + int availablePort = NetUtils.getAvailablePort(); + + ApplicationConfig applicationConfig = new ApplicationConfig("bootstrap-test"); + applicationConfig.setMetadataServicePort(availablePort); + applicationConfig.setMetadataType(REMOTE_METADATA_STORAGE_TYPE); + + RegistryConfig registryConfig = new RegistryConfig(zkServerAddress); + registryConfig.setUseAsMetadataCenter(false); + registryConfig.setUseAsConfigCenter(false); + + DubboBootstrap.getInstance() + .application(applicationConfig) + .registry(registryConfig) + .protocol(new ProtocolConfig(CommonConstants.DUBBO_PROTOCOL, -1)) + .service(service) + .start(); + }); + } + private ExporterDeployListener getListener(ApplicationModel model) { return (ExporterDeployListener) model.getExtensionLoader(ApplicationDeployListener.class).getExtension("exporter"); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java index 08a46a67f4..a255c1042f 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboAnnotationUtils.java @@ -138,7 +138,7 @@ public class DubboAnnotationUtils { * be split in anytime.It will throw IllegalArgumentException If converted array length isn't * even number. * The convert cases below work in right way,which are best practice. - *

+ *

      * (array->map)
      * ["a","b"] ==> {a=b}
      * [" a "," b "] ==> {a=b}
@@ -147,7 +147,7 @@ public class DubboAnnotationUtils {
      * ["a=b","c","d"] ==>{a=b,c=d}
      * ["a","a:b"] ==>{a="a:b"}
      * ["a","a,b"] ==>{a="a,b"}
-     * 

+ *
* * @param parameters * @return