Skip to content

Commit 1916666

Browse files
fanlobuAlbumenJEarthChen
authored
[Feature][3.3] Triple rest jaxrs ParamConverter support (#14148)
* feat() : add paramconverter support * fix():fix codestyle * add(): add ParamConverterFactory ,fix the rule of get converter * add(): add test , complete JaxrsRestToolKit * fix(): Simplify code writing and fix some logic * fix(): fix log error code --------- Co-authored-by: Albumen Kevin <[email protected]> Co-authored-by: earthchen <[email protected]>
1 parent 2a42f4f commit 1916666

7 files changed

Lines changed: 224 additions & 0 deletions

File tree

dubbo-plugin/dubbo-rest-jaxrs/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/JaxrsRestToolKit.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,23 @@
2525

2626
import javax.ws.rs.core.MultivaluedHashMap;
2727
import javax.ws.rs.core.MultivaluedMap;
28+
import javax.ws.rs.ext.ParamConverter;
29+
30+
import java.util.Optional;
2831

2932
final class JaxrsRestToolKit extends DefaultRestToolKit {
3033

3134
private final BeanArgumentBinder binder;
3235

36+
private final ParamConverterFactory paramConverterFactory;
37+
3338
public JaxrsRestToolKit(FrameworkModel frameworkModel) {
3439
super(frameworkModel);
3540
binder = new BeanArgumentBinder(frameworkModel);
41+
paramConverterFactory = new ParamConverterFactory();
3642
}
3743

44+
@SuppressWarnings({"unchecked", "rawtypes"})
3845
@Override
3946
public Object convert(Object value, ParameterMeta parameter) {
4047
if (MultivaluedMap.class.isAssignableFrom(parameter.getType())) {
@@ -43,6 +50,19 @@ public Object convert(Object value, ParameterMeta parameter) {
4350
}
4451
return typeConverter.convert(value, MultivaluedHashMap.class);
4552
}
53+
54+
Optional<ParamConverter> optional = paramConverterFactory.getParamConverter(
55+
parameter.getType(), parameter.getGenericType(), parameter.getRealAnnotations());
56+
if (optional.isPresent()) {
57+
ParamConverter paramConverter = optional.get();
58+
Object result = value.getClass() == String.class
59+
? paramConverter.fromString((String) value)
60+
: paramConverter.toString(value);
61+
if (result != null) {
62+
return result;
63+
}
64+
}
65+
4666
return super.convert(value, parameter);
4767
}
4868

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs;
18+
19+
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
20+
import org.apache.dubbo.common.logger.LoggerFactory;
21+
import org.apache.dubbo.common.utils.CollectionUtils;
22+
import org.apache.dubbo.common.utils.Pair;
23+
24+
import javax.ws.rs.ext.ParamConverter;
25+
import javax.ws.rs.ext.ParamConverterProvider;
26+
27+
import java.lang.annotation.Annotation;
28+
import java.lang.reflect.Type;
29+
import java.util.ArrayList;
30+
import java.util.Iterator;
31+
import java.util.List;
32+
import java.util.Map;
33+
import java.util.Optional;
34+
import java.util.ServiceLoader;
35+
36+
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_ERROR_LOAD_EXTENSION;
37+
38+
@SuppressWarnings({"rawtypes"})
39+
public class ParamConverterFactory {
40+
41+
private static final ErrorTypeAwareLogger logger =
42+
LoggerFactory.getErrorTypeAwareLogger(ParamConverterFactory.class);
43+
private final Map<Pair<Pair<Class<?>, Type>, Annotation[]>, Optional<ParamConverter>> cache =
44+
CollectionUtils.newConcurrentHashMap();
45+
private final List<ParamConverterProvider> providers = new ArrayList<>();
46+
47+
ParamConverterFactory() {
48+
ServiceLoader<ParamConverterProvider> serviceLoader = ServiceLoader.load(ParamConverterProvider.class);
49+
Iterator<ParamConverterProvider> iterator = serviceLoader.iterator();
50+
while (iterator.hasNext()) {
51+
try {
52+
ParamConverterProvider paramConverterProvider = iterator.next();
53+
providers.add(paramConverterProvider);
54+
} catch (Throwable e) {
55+
logger.error(COMMON_ERROR_LOAD_EXTENSION, "", "", "Spi Fail to load ParamConverterProvider");
56+
}
57+
}
58+
}
59+
60+
public <T> Optional<ParamConverter> getParamConverter(
61+
Class<T> rawType, Type genericType, Annotation[] annotations) {
62+
Pair<Pair<Class<?>, Type>, Annotation[]> pair = Pair.of(Pair.of(rawType, genericType), annotations);
63+
return cache.computeIfAbsent(pair, k -> {
64+
for (ParamConverterProvider provider : providers) {
65+
ParamConverter converter = provider.getConverter(rawType, genericType, annotations);
66+
if (converter != null) {
67+
return Optional.of(converter);
68+
}
69+
}
70+
return Optional.empty();
71+
});
72+
}
73+
}

dubbo-plugin/dubbo-rest-jaxrs/src/test/java/org/apache/dubbo/rpc/protocol/tri/rest/support/jaxrs/compatible/JaxrsRestProtocolTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.AnotherUserRestServiceImpl;
4040
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.HttpMethodService;
4141
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.HttpMethodServiceImpl;
42+
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.ParamConverterService;
43+
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.ParamConverterServiceImpl;
4244
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.RestDemoForTestException;
4345
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.RestDemoService;
4446
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.RestDemoServiceImpl;
@@ -562,4 +564,24 @@ private URL registerProvider(URL url, Object impl, Class<?> interfaceClass) {
562564
repository.registerProvider(providerModel);
563565
return url.setServiceModel(providerModel);
564566
}
567+
568+
@Test
569+
void testParamConverter() {
570+
ParamConverterService service = new ParamConverterServiceImpl();
571+
URL exportUrl = URL.valueOf(
572+
"tri://127.0.0.1:" + availablePort + "/rest?interface=" + ParamConverterService.class.getName());
573+
574+
URL nettyUrl = this.registerProvider(exportUrl, service, ParamConverterService.class);
575+
576+
tProtocol.export(proxy.getInvoker(service, ParamConverterService.class, nettyUrl));
577+
578+
ParamConverterService paramConverterService =
579+
this.proxy.getProxy(protocol.refer(ParamConverterService.class, nettyUrl));
580+
581+
User user = paramConverterService.convert(User.getInstance());
582+
User u = new User();
583+
u.setAge(20);
584+
u.setId(1L);
585+
Assertions.assertEquals(u, user);
586+
}
565587
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest;
18+
19+
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.User;
20+
21+
import javax.ws.rs.ext.ParamConverter;
22+
import javax.ws.rs.ext.ParamConverterProvider;
23+
24+
import java.lang.annotation.Annotation;
25+
import java.lang.reflect.Type;
26+
27+
public class ParamConverterProviderImpl implements ParamConverterProvider {
28+
29+
@Override
30+
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type type, Annotation[] annotations) {
31+
if (rawType.isAssignableFrom(User.class)) {
32+
return (ParamConverter<T>) new UserParamConverter();
33+
}
34+
return null;
35+
}
36+
37+
static class UserParamConverter implements ParamConverter<User> {
38+
@Override
39+
public User fromString(String param) {
40+
User user = new User();
41+
user.setId(1L);
42+
user.setAge(20);
43+
return user;
44+
}
45+
46+
@Override
47+
public String toString(User user) {
48+
return "User{" + "id=" + user.getId() + ", name='" + user.getName() + '\'' + ", age=" + user.getAge() + '}';
49+
}
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest;
18+
19+
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.User;
20+
21+
import javax.ws.rs.GET;
22+
import javax.ws.rs.Path;
23+
import javax.ws.rs.QueryParam;
24+
25+
@Path("/ParamConverterService")
26+
public interface ParamConverterService {
27+
28+
@GET()
29+
@Path("/convert")
30+
User convert(@QueryParam("user") User user);
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest;
18+
19+
import org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.User;
20+
21+
public class ParamConverterServiceImpl implements ParamConverterService {
22+
@Override
23+
public User convert(User user) {
24+
return user;
25+
}
26+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.apache.dubbo.rpc.protocol.tri.rest.support.jaxrs.compatible.rest.ParamConverterProviderImpl

0 commit comments

Comments
 (0)