From 5aa43abdeff18232157c9e2dce8bbe975e182f5d Mon Sep 17 00:00:00 2001 From: fanlobu <2840697550@qq.com> Date: Tue, 30 Apr 2024 22:29:54 +0800 Subject: [PATCH 1/6] feat() : add paramconverter support --- .../support/jaxrs/JaxrsParamConverter.java | 90 +++++++++++++++++++ .../rest/support/jaxrs/JaxrsRestToolKit.java | 9 ++ 2 files changed, 99 insertions(+) create mode 100644 dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java new file mode 100644 index 00000000000..3fa5bdaf025 --- /dev/null +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java @@ -0,0 +1,90 @@ +package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs; + +import org.apache.dubbo.common.extension.ExtensionDirector; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.Pair; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.protocol.tri.rest.util.TypeUtils; + +import javax.ws.rs.ext.ParamConverter; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; + +@SuppressWarnings({"rawtypes"}) +public class JaxrsParamConverter { + + private final Map, Class>, ParamConverter> cacheConverter = + CollectionUtils.newConcurrentHashMap(); + + + private final List converters; + + JaxrsParamConverter(FrameworkModel frameworkModel) { + this.converters= getExtensionLoader(ParamConverter.class,frameworkModel).getActivateExtensions(); + } + + + boolean canConvert(Class sourceType, Class targetType) { + return getConvert(sourceType,targetType) != null; + } + + @SuppressWarnings("unchecked") + Object convert(Class sourceType, Class targetType, Object value) { + ParamConverter paramConverter = getConvert(sourceType, targetType); + if(paramConverter == null){ + return null; + } + + Class type = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); + Object result = null; + if (sourceType.isAssignableFrom(String.class) && targetType.isAssignableFrom(type)) { + result = paramConverter.fromString((String) value); + } else if (targetType.isAssignableFrom(String.class) && sourceType.isAssignableFrom(type)) { + result = paramConverter.toString(value); + } + return result; + } + + private ParamConverter getConvert(Class sourceType, Class targetType){ + ParamConverter converter = cacheConverter.get(Pair.of(sourceType, targetType)); + if (converter != null) { + return converter; + } + + return cacheConverter.computeIfAbsent(Pair.of(sourceType,targetType),k->{ + for (ParamConverter paramConverter : converters) { + Class supportType = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); + if (supportType == null) { + continue; + } + if (sourceType == String.class && targetType.isAssignableFrom(supportType)) { + return paramConverter; + } + } + return null; + }); + } + + + private ExtensionLoader getExtensionLoader(Class converterClass,FrameworkModel frameworkModel){ + ExtensionLoader instance = null; + try { + Class clazz = ExtensionLoader.class; + Constructor constructor = clazz.getDeclaredConstructor(Class.class, ExtensionDirector.class, ScopeModel.class); + constructor.setAccessible(true); + instance = constructor.newInstance(converterClass, frameworkModel.getExtensionDirector(), frameworkModel); + + } catch (NoSuchMethodException + | InstantiationException + | IllegalAccessException + | InvocationTargetException e) { + throw new RuntimeException(e); + } + return instance; + } +} diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java index 95ef839b87d..ce6f7087f83 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java @@ -30,9 +30,12 @@ final class JaxrsRestToolKit extends DefaultRestToolKit { private final BeanArgumentBinder binder; + private final JaxrsParamConverter jaxrsParamConverter; + public JaxrsRestToolKit(FrameworkModel frameworkModel) { super(frameworkModel); binder = new BeanArgumentBinder(frameworkModel); + jaxrsParamConverter = new JaxrsParamConverter(frameworkModel); } @Override @@ -43,6 +46,12 @@ public Object convert(Object value, ParameterMeta parameter) { } return typeConverter.convert(value, MultivaluedHashMap.class); } + if (jaxrsParamConverter.canConvert(value.getClass(), parameter.getActualType())) { + Object convertResult = jaxrsParamConverter.convert(value.getClass(), parameter.getType(), value); + if (convertResult != null) { + return convertResult; + } + } return super.convert(value, parameter); } From 60dbdc03d3908593945a92392bcfc5f0f8b59c19 Mon Sep 17 00:00:00 2001 From: fanlobu <2840697550@qq.com> Date: Tue, 30 Apr 2024 23:30:31 +0800 Subject: [PATCH 2/6] fix():fix codestyle --- .../support/jaxrs/JaxrsParamConverter.java | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java index 3fa5bdaf025..00fea90eb03 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java @@ -1,3 +1,19 @@ +/* + * 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.rest.support.jaxrs; import org.apache.dubbo.common.extension.ExtensionDirector; @@ -18,25 +34,23 @@ @SuppressWarnings({"rawtypes"}) public class JaxrsParamConverter { - private final Map, Class>, ParamConverter> cacheConverter = - CollectionUtils.newConcurrentHashMap(); - + private final Map, Class>, ParamConverter> cacheConverter = CollectionUtils.newConcurrentHashMap(); private final List converters; JaxrsParamConverter(FrameworkModel frameworkModel) { - this.converters= getExtensionLoader(ParamConverter.class,frameworkModel).getActivateExtensions(); + this.converters = + getExtensionLoader(ParamConverter.class, frameworkModel).getActivateExtensions(); } - boolean canConvert(Class sourceType, Class targetType) { - return getConvert(sourceType,targetType) != null; + return getConvert(sourceType, targetType) != null; } @SuppressWarnings("unchecked") Object convert(Class sourceType, Class targetType, Object value) { ParamConverter paramConverter = getConvert(sourceType, targetType); - if(paramConverter == null){ + if (paramConverter == null) { return null; } @@ -50,13 +64,13 @@ Object convert(Class sourceType, Class targetType, Object value) { return result; } - private ParamConverter getConvert(Class sourceType, Class targetType){ + private ParamConverter getConvert(Class sourceType, Class targetType) { ParamConverter converter = cacheConverter.get(Pair.of(sourceType, targetType)); if (converter != null) { return converter; } - return cacheConverter.computeIfAbsent(Pair.of(sourceType,targetType),k->{ + return cacheConverter.computeIfAbsent(Pair.of(sourceType, targetType), k -> { for (ParamConverter paramConverter : converters) { Class supportType = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); if (supportType == null) { @@ -70,19 +84,19 @@ private ParamConverter getConvert(Class sourceType, Class targetType){ }); } - - private ExtensionLoader getExtensionLoader(Class converterClass,FrameworkModel frameworkModel){ + private ExtensionLoader getExtensionLoader(Class converterClass, FrameworkModel frameworkModel) { ExtensionLoader instance = null; try { Class clazz = ExtensionLoader.class; - Constructor constructor = clazz.getDeclaredConstructor(Class.class, ExtensionDirector.class, ScopeModel.class); + Constructor constructor = + clazz.getDeclaredConstructor(Class.class, ExtensionDirector.class, ScopeModel.class); constructor.setAccessible(true); instance = constructor.newInstance(converterClass, frameworkModel.getExtensionDirector(), frameworkModel); } catch (NoSuchMethodException - | InstantiationException - | IllegalAccessException - | InvocationTargetException e) { + | InstantiationException + | IllegalAccessException + | InvocationTargetException e) { throw new RuntimeException(e); } return instance; From a0aae0026e4db15dbf0348040d6d2f9b5a8d9152 Mon Sep 17 00:00:00 2001 From: fanlobu <2840697550@qq.com> Date: Thu, 30 May 2024 00:16:10 +0800 Subject: [PATCH 3/6] add(): add ParamConverterFactory ,fix the rule of get converter --- .../support/jaxrs/JaxrsParamConverter.java | 104 ----------------- .../support/jaxrs/ParamConverterFactory.java | 110 ++++++++++++++++++ 2 files changed, 110 insertions(+), 104 deletions(-) delete mode 100644 dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java create mode 100644 dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java deleted file mode 100644 index 00fea90eb03..00000000000 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsParamConverter.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.rest.support.jaxrs; - -import org.apache.dubbo.common.extension.ExtensionDirector; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.Pair; -import org.apache.dubbo.rpc.model.FrameworkModel; -import org.apache.dubbo.rpc.model.ScopeModel; -import org.apache.dubbo.rpc.protocol.tri.rest.util.TypeUtils; - -import javax.ws.rs.ext.ParamConverter; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import java.util.Map; - -@SuppressWarnings({"rawtypes"}) -public class JaxrsParamConverter { - - private final Map, Class>, ParamConverter> cacheConverter = CollectionUtils.newConcurrentHashMap(); - - private final List converters; - - JaxrsParamConverter(FrameworkModel frameworkModel) { - this.converters = - getExtensionLoader(ParamConverter.class, frameworkModel).getActivateExtensions(); - } - - boolean canConvert(Class sourceType, Class targetType) { - return getConvert(sourceType, targetType) != null; - } - - @SuppressWarnings("unchecked") - Object convert(Class sourceType, Class targetType, Object value) { - ParamConverter paramConverter = getConvert(sourceType, targetType); - if (paramConverter == null) { - return null; - } - - Class type = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); - Object result = null; - if (sourceType.isAssignableFrom(String.class) && targetType.isAssignableFrom(type)) { - result = paramConverter.fromString((String) value); - } else if (targetType.isAssignableFrom(String.class) && sourceType.isAssignableFrom(type)) { - result = paramConverter.toString(value); - } - return result; - } - - private ParamConverter getConvert(Class sourceType, Class targetType) { - ParamConverter converter = cacheConverter.get(Pair.of(sourceType, targetType)); - if (converter != null) { - return converter; - } - - return cacheConverter.computeIfAbsent(Pair.of(sourceType, targetType), k -> { - for (ParamConverter paramConverter : converters) { - Class supportType = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); - if (supportType == null) { - continue; - } - if (sourceType == String.class && targetType.isAssignableFrom(supportType)) { - return paramConverter; - } - } - return null; - }); - } - - private ExtensionLoader getExtensionLoader(Class converterClass, FrameworkModel frameworkModel) { - ExtensionLoader instance = null; - try { - Class clazz = ExtensionLoader.class; - Constructor constructor = - clazz.getDeclaredConstructor(Class.class, ExtensionDirector.class, ScopeModel.class); - constructor.setAccessible(true); - instance = constructor.newInstance(converterClass, frameworkModel.getExtensionDirector(), frameworkModel); - - } catch (NoSuchMethodException - | InstantiationException - | IllegalAccessException - | InvocationTargetException e) { - throw new RuntimeException(e); - } - return instance; - } -} diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java new file mode 100644 index 00000000000..7f9225b6e27 --- /dev/null +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java @@ -0,0 +1,110 @@ +/* + * 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.rest.support.jaxrs; + +import org.apache.dubbo.common.extension.ExtensionDirector; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.Pair; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.protocol.tri.rest.util.TypeUtils; + +import javax.ws.rs.ext.ParamConverter; +import javax.ws.rs.ext.ParamConverterProvider; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.ServiceLoader.Provider; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@SuppressWarnings({"rawtypes"}) +public class ParamConverterFatcory { + + private final Map, Class>, ParamConverter> cache = CollectionUtils.newConcurrentHashMap(); + +// private final List converters; + private List providers; + ParamConverterFatcory(FrameworkModel frameworkModel) { + this.providers = ServiceLoader.load(ParamConverterProvider.class) + .stream() + .map(Provider::get) + .collect(Collectors.toList()); + } + +// boolean canConvert(Class sourceType, Class targetType) { +// return getConvert(sourceType, targetType) != null; +// } +// +// @SuppressWarnings("unchecked") +// Object convert(Class sourceType, Class targetType, Object value) { +// ParamConverter paramConverter = getConvert(sourceType, targetType); +// if (paramConverter == null) { +// return null; +// } +// +// Class type = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); +// Object result = null; +// if (sourceType.isAssignableFrom(String.class) && targetType.isAssignableFrom(type)) { +// result = paramConverter.fromString((String) value); +// } else if (targetType.isAssignableFrom(String.class) && sourceType.isAssignableFrom(type)) { +// result = paramConverter.toString(value); +// } +// return result; +// } + + private ParamConverter getParamConverter(Class sourceType, Class targetType) { + ParamConverter converter = cacheConverter.get(Pair.of(sourceType, targetType)); + if (converter != null) { + return converter; + } + + return cacheConverter.computeIfAbsent(Pair.of(sourceType, targetType), k -> { + for (ParamConverter paramConverter : converters) { + Class supportType = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); + if (supportType == null) { + continue; + } + if (sourceType == String.class && targetType.isAssignableFrom(supportType)) { + return paramConverter; + } + } + return null; + }); + } + +// private ExtensionLoader getExtensionLoader(Class converterClass, FrameworkModel frameworkModel) { +// ExtensionLoader instance = null; +// try { +// Class clazz = ExtensionLoader.class; +// Constructor constructor = +// clazz.getDeclaredConstructor(Class.class, ExtensionDirector.class, ScopeModel.class); +// constructor.setAccessible(true); +// instance = constructor.newInstance(converterClass, frameworkModel.getExtensionDirector(), frameworkModel); +// +// } catch (NoSuchMethodException +// | InstantiationException +// | IllegalAccessException +// | InvocationTargetException e) { +// throw new RuntimeException(e); +// } +// return instance; +// } +} From bb5bebba5e42a37653fb5311dd187b9ae9ccff22 Mon Sep 17 00:00:00 2001 From: fanlobu <2840697550@qq.com> Date: Thu, 30 May 2024 00:30:37 +0800 Subject: [PATCH 4/6] add(): add test , complete JaxrsRestToolKit --- .../rest/support/jaxrs/JaxrsRestToolKit.java | 27 ++++-- .../support/jaxrs/ParamConverterFactory.java | 92 ++++--------------- .../compatible/JaxrsRestProtocolTest.java | 22 +++++ .../rest/ParamConverterProviderImpl.java | 51 ++++++++++ .../rest/ParamConverterService.java | 31 +++++++ .../rest/ParamConverterServiceImpl.java | 26 ++++++ .../javax.ws.rs.ext.ParamConverterProvider | 1 + 7 files changed, 172 insertions(+), 78 deletions(-) create mode 100644 dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterProviderImpl.java create mode 100644 dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterService.java create mode 100644 dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterServiceImpl.java create mode 100644 dubbo-plugin/dubbo-rest-jaxrs/src/test/resources/META-INF/services/javax.ws.rs.ext.ParamConverterProvider diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java index ce6f7087f83..c50cc8d99c7 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java @@ -22,22 +22,25 @@ import org.apache.dubbo.rpc.protocol.tri.rest.RestConstants; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; import org.apache.dubbo.rpc.protocol.tri.rest.util.DefaultRestToolKit; +import org.apache.dubbo.rpc.protocol.tri.rest.util.TypeUtils; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.ParamConverter; final class JaxrsRestToolKit extends DefaultRestToolKit { private final BeanArgumentBinder binder; - private final JaxrsParamConverter jaxrsParamConverter; + private final ParamConverterFactory paramConverterFactory; public JaxrsRestToolKit(FrameworkModel frameworkModel) { super(frameworkModel); binder = new BeanArgumentBinder(frameworkModel); - jaxrsParamConverter = new JaxrsParamConverter(frameworkModel); + paramConverterFactory = new ParamConverterFactory(); } + @SuppressWarnings({"unchecked", "rawtypes"}) @Override public Object convert(Object value, ParameterMeta parameter) { if (MultivaluedMap.class.isAssignableFrom(parameter.getType())) { @@ -46,12 +49,24 @@ public Object convert(Object value, ParameterMeta parameter) { } return typeConverter.convert(value, MultivaluedHashMap.class); } - if (jaxrsParamConverter.canConvert(value.getClass(), parameter.getActualType())) { - Object convertResult = jaxrsParamConverter.convert(value.getClass(), parameter.getType(), value); - if (convertResult != null) { - return convertResult; + + ParamConverter paramConverter = paramConverterFactory.getParamConverter( + parameter.getType(), parameter.getGenericType(), parameter.getRealAnnotations()); + if (paramConverter != null) { + Class type = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); + Object result = null; + if (value.getClass().isAssignableFrom(String.class) + && parameter.getType().isAssignableFrom(type)) { + result = paramConverter.fromString((String) value); + } else if (value.getClass().isAssignableFrom(type) + && parameter.getType().isAssignableFrom(String.class)) { + result = paramConverter.toString(value); + } + if (result != null) { + return result; } } + return super.convert(value, parameter); } diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java index 7f9225b6e27..de626d07c92 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java @@ -16,95 +16,43 @@ */ package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs; -import org.apache.dubbo.common.extension.ExtensionDirector; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.Pair; -import org.apache.dubbo.rpc.model.FrameworkModel; -import org.apache.dubbo.rpc.model.ScopeModel; -import org.apache.dubbo.rpc.protocol.tri.rest.util.TypeUtils; import javax.ws.rs.ext.ParamConverter; import javax.ws.rs.ext.ParamConverterProvider; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.ServiceLoader; -import java.util.ServiceLoader.Provider; -import java.util.stream.Collectors; -import java.util.stream.Stream; @SuppressWarnings({"rawtypes"}) -public class ParamConverterFatcory { +public class ParamConverterFactory { - private final Map, Class>, ParamConverter> cache = CollectionUtils.newConcurrentHashMap(); + private final Map, Type>, Annotation[]>, ParamConverter> cache = + CollectionUtils.newConcurrentHashMap(); + private final List providers = new ArrayList<>(); -// private final List converters; - private List providers; - ParamConverterFatcory(FrameworkModel frameworkModel) { - this.providers = ServiceLoader.load(ParamConverterProvider.class) - .stream() - .map(Provider::get) - .collect(Collectors.toList()); + ParamConverterFactory() { + ServiceLoader.load(ParamConverterProvider.class).forEach(providers::add); } -// boolean canConvert(Class sourceType, Class targetType) { -// return getConvert(sourceType, targetType) != null; -// } -// -// @SuppressWarnings("unchecked") -// Object convert(Class sourceType, Class targetType, Object value) { -// ParamConverter paramConverter = getConvert(sourceType, targetType); -// if (paramConverter == null) { -// return null; -// } -// -// Class type = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); -// Object result = null; -// if (sourceType.isAssignableFrom(String.class) && targetType.isAssignableFrom(type)) { -// result = paramConverter.fromString((String) value); -// } else if (targetType.isAssignableFrom(String.class) && sourceType.isAssignableFrom(type)) { -// result = paramConverter.toString(value); -// } -// return result; -// } - - private ParamConverter getParamConverter(Class sourceType, Class targetType) { - ParamConverter converter = cacheConverter.get(Pair.of(sourceType, targetType)); - if (converter != null) { - return converter; + public ParamConverter getParamConverter(Class rawType, Type genericType, Annotation[] annotations) { + Pair, Type>, Annotation[]> pair = Pair.of(Pair.of(rawType, genericType), annotations); + ParamConverter paramConverter = cache.get(pair); + if (paramConverter != null) { + return paramConverter; } - - return cacheConverter.computeIfAbsent(Pair.of(sourceType, targetType), k -> { - for (ParamConverter paramConverter : converters) { - Class supportType = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); - if (supportType == null) { - continue; - } - if (sourceType == String.class && targetType.isAssignableFrom(supportType)) { - return paramConverter; - } + for (ParamConverterProvider provider : providers) { + paramConverter = provider.getConverter(rawType, genericType, annotations); + if (paramConverter != null) { + cache.put(pair, paramConverter); + return paramConverter; } - return null; - }); + } + return null; } - -// private ExtensionLoader getExtensionLoader(Class converterClass, FrameworkModel frameworkModel) { -// ExtensionLoader instance = null; -// try { -// Class clazz = ExtensionLoader.class; -// Constructor constructor = -// clazz.getDeclaredConstructor(Class.class, ExtensionDirector.class, ScopeModel.class); -// constructor.setAccessible(true); -// instance = constructor.newInstance(converterClass, frameworkModel.getExtensionDirector(), frameworkModel); -// -// } catch (NoSuchMethodException -// | InstantiationException -// | IllegalAccessException -// | InvocationTargetException e) { -// throw new RuntimeException(e); -// } -// return instance; -// } } diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/JaxrsRestProtocolTest.java b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/JaxrsRestProtocolTest.java index 9caa0b6a93f..7a4ec91b1e2 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/JaxrsRestProtocolTest.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/JaxrsRestProtocolTest.java @@ -39,6 +39,8 @@ import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.AnotherUserRestServiceImpl; import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.HttpMethodService; import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.HttpMethodServiceImpl; +import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.ParamConverterService; +import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.ParamConverterServiceImpl; import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.RestDemoForTestException; import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.RestDemoService; import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.RestDemoServiceImpl; @@ -560,4 +562,24 @@ private URL registerProvider(URL url, Object impl, Class interfaceClass) { repository.registerProvider(providerModel); return url.setServiceModel(providerModel); } + + @Test + void testParamConverter() { + ParamConverterService service = new ParamConverterServiceImpl(); + URL exportUrl = URL.valueOf( + "tri://127.0.0.1:" + availablePort + "/rest?interface=" + ParamConverterService.class.getName()); + + URL nettyUrl = this.registerProvider(exportUrl, service, ParamConverterService.class); + + tProtocol.export(proxy.getInvoker(service, ParamConverterService.class, nettyUrl)); + + ParamConverterService paramConverterService = + this.proxy.getProxy(protocol.refer(ParamConverterService.class, nettyUrl)); + + User user = paramConverterService.convert(User.getInstance()); + User u = new User(); + u.setAge(20); + u.setId(1L); + Assertions.assertEquals(u, user); + } } diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterProviderImpl.java b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterProviderImpl.java new file mode 100644 index 00000000000..24d0a472cb2 --- /dev/null +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterProviderImpl.java @@ -0,0 +1,51 @@ +/* + * 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.rest.support.jaxrs.compatible.rest; + +import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.User; + +import javax.ws.rs.ext.ParamConverter; +import javax.ws.rs.ext.ParamConverterProvider; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +public class ParamConverterProviderImpl implements ParamConverterProvider { + + @Override + public ParamConverter getConverter(Class rawType, Type type, Annotation[] annotations) { + if (rawType.isAssignableFrom(User.class)) { + return (ParamConverter) new UserParamConverter(); + } + return null; + } + + static class UserParamConverter implements ParamConverter { + @Override + public User fromString(String param) { + User user = new User(); + user.setId(1L); + user.setAge(20); + return user; + } + + @Override + public String toString(User user) { + return "User{" + "id=" + user.getId() + ", name='" + user.getName() + '\'' + ", age=" + user.getAge() + '}'; + } + } +} diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterService.java b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterService.java new file mode 100644 index 00000000000..fa1c20c12de --- /dev/null +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterService.java @@ -0,0 +1,31 @@ +/* + * 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.rest.support.jaxrs.compatible.rest; + +import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.User; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; + +@Path("/ParamConverterService") +public interface ParamConverterService { + + @GET() + @Path("/convert") + User convert(@QueryParam("user") User user); +} diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterServiceImpl.java b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterServiceImpl.java new file mode 100644 index 00000000000..2b0bedfd213 --- /dev/null +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/rest/ParamConverterServiceImpl.java @@ -0,0 +1,26 @@ +/* + * 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.rest.support.jaxrs.compatible.rest; + +import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.User; + +public class ParamConverterServiceImpl implements ParamConverterService { + @Override + public User convert(User user) { + return user; + } +} diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/test/resources/META-INF/services/javax.ws.rs.ext.ParamConverterProvider b/dubbo-plugin/dubbo-rest-jaxrs/src/test/resources/META-INF/services/javax.ws.rs.ext.ParamConverterProvider new file mode 100644 index 00000000000..b794deb1582 --- /dev/null +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/test/resources/META-INF/services/javax.ws.rs.ext.ParamConverterProvider @@ -0,0 +1 @@ +org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.ParamConverterProviderImpl From 23137bd07860295e62e688df71e8c4a8d2f7cc12 Mon Sep 17 00:00:00 2001 From: fanlobu <2840697550@qq.com> Date: Sat, 8 Jun 2024 03:05:38 +0800 Subject: [PATCH 5/6] fix(): Simplify code writing and fix some logic --- .../rest/support/jaxrs/JaxrsRestToolKit.java | 20 ++++------ .../support/jaxrs/ParamConverterFactory.java | 40 ++++++++++++------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java index c50cc8d99c7..89d1861dc5c 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java @@ -22,12 +22,13 @@ import org.apache.dubbo.rpc.protocol.tri.rest.RestConstants; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; import org.apache.dubbo.rpc.protocol.tri.rest.util.DefaultRestToolKit; -import org.apache.dubbo.rpc.protocol.tri.rest.util.TypeUtils; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.ParamConverter; +import java.util.Optional; + final class JaxrsRestToolKit extends DefaultRestToolKit { private final BeanArgumentBinder binder; @@ -50,18 +51,13 @@ public Object convert(Object value, ParameterMeta parameter) { return typeConverter.convert(value, MultivaluedHashMap.class); } - ParamConverter paramConverter = paramConverterFactory.getParamConverter( + Optional optional = paramConverterFactory.getParamConverter( parameter.getType(), parameter.getGenericType(), parameter.getRealAnnotations()); - if (paramConverter != null) { - Class type = TypeUtils.getSuperGenericType(paramConverter.getClass(), 0); - Object result = null; - if (value.getClass().isAssignableFrom(String.class) - && parameter.getType().isAssignableFrom(type)) { - result = paramConverter.fromString((String) value); - } else if (value.getClass().isAssignableFrom(type) - && parameter.getType().isAssignableFrom(String.class)) { - result = paramConverter.toString(value); - } + if (optional.isPresent()) { + ParamConverter paramConverter = optional.get(); + Object result = value.getClass() == String.class + ? paramConverter.fromString((String) value) + : paramConverter.toString(value); if (result != null) { return result; } diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java index de626d07c92..074bca8d0f6 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java @@ -16,6 +16,8 @@ */ package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.Pair; @@ -25,34 +27,44 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.ServiceLoader; @SuppressWarnings({"rawtypes"}) public class ParamConverterFactory { - private final Map, Type>, Annotation[]>, ParamConverter> cache = + public static final Logger logger = LoggerFactory.getLogger(ParamConverterFactory.class); + private final Map, Type>, Annotation[]>, Optional> cache = CollectionUtils.newConcurrentHashMap(); private final List providers = new ArrayList<>(); ParamConverterFactory() { - ServiceLoader.load(ParamConverterProvider.class).forEach(providers::add); + ServiceLoader serviceLoader = ServiceLoader.load(ParamConverterProvider.class); + Iterator iterator = serviceLoader.iterator(); + while (iterator.hasNext()) { + try { + ParamConverterProvider paramConverterProvider = iterator.next(); + providers.add(paramConverterProvider); + } catch (Throwable e) { + logger.error("Spi Fail to load :" + e.getMessage()); + } + } } - public ParamConverter getParamConverter(Class rawType, Type genericType, Annotation[] annotations) { + public Optional getParamConverter( + Class rawType, Type genericType, Annotation[] annotations) { Pair, Type>, Annotation[]> pair = Pair.of(Pair.of(rawType, genericType), annotations); - ParamConverter paramConverter = cache.get(pair); - if (paramConverter != null) { - return paramConverter; - } - for (ParamConverterProvider provider : providers) { - paramConverter = provider.getConverter(rawType, genericType, annotations); - if (paramConverter != null) { - cache.put(pair, paramConverter); - return paramConverter; + return cache.computeIfAbsent(pair, k -> { + for (ParamConverterProvider provider : providers) { + ParamConverter converter = provider.getConverter(rawType, genericType, annotations); + if (converter != null) { + return Optional.of(converter); + } } - } - return null; + return Optional.empty(); + }); } } From 27d617da9bfaf0449c05423524ae80a11b4f5e73 Mon Sep 17 00:00:00 2001 From: fanlobu <2840697550@qq.com> Date: Sun, 9 Jun 2024 23:58:25 +0800 Subject: [PATCH 6/6] fix(): fix log error code --- .../tri/rest/support/jaxrs/ParamConverterFactory.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java index 074bca8d0f6..bef0a63b909 100644 --- a/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java +++ b/dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/ParamConverterFactory.java @@ -16,7 +16,7 @@ */ package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs; -import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.Pair; @@ -33,10 +33,13 @@ import java.util.Optional; import java.util.ServiceLoader; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_ERROR_LOAD_EXTENSION; + @SuppressWarnings({"rawtypes"}) public class ParamConverterFactory { - public static final Logger logger = LoggerFactory.getLogger(ParamConverterFactory.class); + private static final ErrorTypeAwareLogger logger = + LoggerFactory.getErrorTypeAwareLogger(ParamConverterFactory.class); private final Map, Type>, Annotation[]>, Optional> cache = CollectionUtils.newConcurrentHashMap(); private final List providers = new ArrayList<>(); @@ -49,7 +52,7 @@ public class ParamConverterFactory { ParamConverterProvider paramConverterProvider = iterator.next(); providers.add(paramConverterProvider); } catch (Throwable e) { - logger.error("Spi Fail to load :" + e.getMessage()); + logger.error(COMMON_ERROR_LOAD_EXTENSION, "", "", "Spi Fail to load ParamConverterProvider"); } } }