Skip to content

Commit 72020df

Browse files
lexburnerralf0131
authored andcommitted
Add JSON-RPC protocol (#3786)
1 parent 288c1a5 commit 72020df

File tree

13 files changed

+415
-1
lines changed

13 files changed

+415
-1
lines changed

dubbo-all/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@
143143
<scope>compile</scope>
144144
<optional>true</optional>
145145
</dependency>
146+
<dependency>
147+
<groupId>org.apache.dubbo</groupId>
148+
<artifactId>dubbo-rpc-jsonrpc</artifactId>
149+
<version>${project.version}</version>
150+
<scope>compile</scope>
151+
<optional>true</optional>
152+
</dependency>
146153
<dependency>
147154
<groupId>org.apache.dubbo</groupId>
148155
<artifactId>dubbo-rpc-rmi</artifactId>
@@ -491,6 +498,7 @@
491498
<include>org.apache.dubbo:dubbo-rpc-api</include>
492499
<include>org.apache.dubbo:dubbo-rpc-dubbo</include>
493500
<include>org.apache.dubbo:dubbo-rpc-injvm</include>
501+
<include>org.apache.dubbo:dubbo-rpc-jsonrpc</include>
494502
<include>org.apache.dubbo:dubbo-rpc-rmi</include>
495503
<include>org.apache.dubbo:dubbo-rpc-hessian</include>
496504
<include>org.apache.dubbo:dubbo-rpc-http</include>

dubbo-bom/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
<artifactId>dubbo-rpc-injvm</artifactId>
174174
<version>${project.version}</version>
175175
</dependency>
176+
<dependency>
177+
<groupId>org.apache.dubbo</groupId>
178+
<artifactId>dubbo-rpc-jsonrpc</artifactId>
179+
<version>${project.version}</version>
180+
</dependency>
176181
<dependency>
177182
<groupId>org.apache.dubbo</groupId>
178183
<artifactId>dubbo-rpc-rmi</artifactId>

dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ public class ApplicationConfig extends AbstractConfig {
124124
private String shutwait;
125125

126126

127+
private Boolean preferPublicIp;
128+
129+
127130
public ApplicationConfig() {
128131
}
129132

@@ -328,4 +331,11 @@ public boolean isValid() {
328331
return !StringUtils.isEmpty(name);
329332
}
330333

334+
public Boolean getPreferPublicIp() {
335+
return preferPublicIp;
336+
}
337+
338+
public void setPreferPublicIp(Boolean preferPublicIp) {
339+
this.preferPublicIp = preferPublicIp;
340+
}
331341
}

dubbo-dependencies-bom/pom.xml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@
143143

144144
<metrics_version>2.0.1</metrics_version>
145145
<gson_version>2.8.5</gson_version>
146+
<jsonrpc_version>1.2.0</jsonrpc_version>
147+
<portlet_version>2.0</portlet_version>
146148
</properties>
147149

148150
<dependencyManagement>
@@ -528,12 +530,21 @@
528530
<version>${spring_test_version}</version>
529531
<scope>test</scope>
530532
</dependency>
531-
532533
<dependency>
533534
<groupId>com.google.code.gson</groupId>
534535
<artifactId>gson</artifactId>
535536
<version>${gson_version}</version>
536537
</dependency>
538+
<dependency>
539+
<groupId>com.github.briandilley.jsonrpc4j</groupId>
540+
<artifactId>jsonrpc4j</artifactId>
541+
<version>${jsonrpc_version}</version>
542+
</dependency>
543+
<dependency>
544+
<groupId>javax.portlet</groupId>
545+
<artifactId>portlet-api</artifactId>
546+
<version>${portlet_version}</version>
547+
</dependency>
537548
</dependencies>
538549
</dependencyManagement>
539550

dubbo-distribution/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@
110110
<artifactId>dubbo-rpc-injvm</artifactId>
111111
<version>${project.version}</version>
112112
</dependency>
113+
<dependency>
114+
<groupId>org.apache.dubbo</groupId>
115+
<artifactId>dubbo-rpc-jsonrpc</artifactId>
116+
<version>${project.version}</version>
117+
</dependency>
113118
<dependency>
114119
<groupId>org.apache.dubbo</groupId>
115120
<artifactId>dubbo-rpc-rmi</artifactId>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
<project xmlns="http://maven.apache.org/POM/4.0.0"
18+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
<parent>
21+
<artifactId>dubbo-rpc</artifactId>
22+
<groupId>org.apache.dubbo</groupId>
23+
<version>2.7.2-SNAPSHOT</version>
24+
</parent>
25+
<modelVersion>4.0.0</modelVersion>
26+
27+
<artifactId>dubbo-rpc-jsonrpc</artifactId>
28+
29+
<description>The JSON-RPC module of dubbo project</description>
30+
31+
<properties>
32+
<skip_maven_deploy>false</skip_maven_deploy>
33+
</properties>
34+
35+
<dependencies>
36+
<dependency>
37+
<groupId>org.apache.dubbo</groupId>
38+
<artifactId>dubbo-rpc-api</artifactId>
39+
<version>${project.parent.version}</version>
40+
</dependency>
41+
<dependency>
42+
<groupId>org.apache.dubbo</groupId>
43+
<artifactId>dubbo-remoting-http</artifactId>
44+
<version>${project.parent.version}</version>
45+
</dependency>
46+
<dependency>
47+
<groupId>org.springframework</groupId>
48+
<artifactId>spring-context</artifactId>
49+
</dependency>
50+
<dependency>
51+
<groupId>com.github.briandilley.jsonrpc4j</groupId>
52+
<artifactId>jsonrpc4j</artifactId>
53+
</dependency>
54+
<dependency>
55+
<groupId>javax.portlet</groupId>
56+
<artifactId>portlet-api</artifactId>
57+
</dependency>
58+
</dependencies>
59+
60+
61+
</project>
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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.jsonrpc;
18+
19+
import org.apache.dubbo.common.URL;
20+
import org.apache.dubbo.remoting.http.HttpBinder;
21+
import org.apache.dubbo.remoting.http.HttpHandler;
22+
import org.apache.dubbo.remoting.http.HttpServer;
23+
import org.apache.dubbo.rpc.RpcContext;
24+
import org.apache.dubbo.rpc.RpcException;
25+
import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
26+
27+
import com.googlecode.jsonrpc4j.HttpException;
28+
import com.googlecode.jsonrpc4j.JsonRpcClientException;
29+
import com.googlecode.jsonrpc4j.JsonRpcServer;
30+
import com.googlecode.jsonrpc4j.spring.JsonProxyFactoryBean;
31+
import org.springframework.remoting.RemoteAccessException;
32+
33+
import javax.servlet.ServletException;
34+
import javax.servlet.http.HttpServletRequest;
35+
import javax.servlet.http.HttpServletResponse;
36+
import java.io.IOException;
37+
import java.net.SocketTimeoutException;
38+
import java.util.ArrayList;
39+
import java.util.Map;
40+
import java.util.concurrent.ConcurrentHashMap;
41+
42+
public class JsonRpcProtocol extends AbstractProxyProtocol {
43+
44+
public static final String ACCESS_CONTROL_ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin";
45+
public static final String ACCESS_CONTROL_ALLOW_METHODS_HEADER = "Access-Control-Allow-Methods";
46+
public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";
47+
48+
private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<>();
49+
50+
private final Map<String, JsonRpcServer> skeletonMap = new ConcurrentHashMap<>();
51+
52+
private HttpBinder httpBinder;
53+
54+
public JsonRpcProtocol() {
55+
super(HttpException.class, JsonRpcClientException.class);
56+
}
57+
58+
public void setHttpBinder(HttpBinder httpBinder) {
59+
this.httpBinder = httpBinder;
60+
}
61+
62+
@Override
63+
public int getDefaultPort() {
64+
return 80;
65+
}
66+
67+
private class InternalHandler implements HttpHandler {
68+
69+
private boolean cors;
70+
71+
public InternalHandler(boolean cors) {
72+
this.cors = cors;
73+
}
74+
75+
@Override
76+
public void handle(HttpServletRequest request, HttpServletResponse response)
77+
throws ServletException {
78+
String uri = request.getRequestURI();
79+
JsonRpcServer skeleton = skeletonMap.get(uri);
80+
if (cors) {
81+
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
82+
response.setHeader(ACCESS_CONTROL_ALLOW_METHODS_HEADER, "POST");
83+
response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_HEADER, "*");
84+
}
85+
if (request.getMethod().equalsIgnoreCase("OPTIONS")) {
86+
response.setStatus(200);
87+
} else if (request.getMethod().equalsIgnoreCase("POST")) {
88+
89+
RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort());
90+
try {
91+
skeleton.handle(request.getInputStream(), response.getOutputStream());
92+
} catch (Throwable e) {
93+
throw new ServletException(e);
94+
}
95+
} else {
96+
response.setStatus(500);
97+
}
98+
}
99+
100+
}
101+
102+
@Override
103+
protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
104+
String addr = url.getIp() + ":" + url.getPort();
105+
HttpServer server = serverMap.get(addr);
106+
if (server == null) {
107+
server = httpBinder.bind(url, new InternalHandler(url.getParameter("cors", false)));
108+
serverMap.put(addr, server);
109+
}
110+
final String path = url.getAbsolutePath();
111+
JsonRpcServer skeleton = new JsonRpcServer(impl, type);
112+
skeletonMap.put(path, skeleton);
113+
return () -> skeletonMap.remove(path);
114+
}
115+
116+
@SuppressWarnings("unchecked")
117+
@Override
118+
protected <T> T doRefer(final Class<T> serviceType, URL url) throws RpcException {
119+
JsonProxyFactoryBean jsonProxyFactoryBean = new JsonProxyFactoryBean();
120+
jsonProxyFactoryBean.setServiceUrl(url.setProtocol("http").toIdentityString());
121+
jsonProxyFactoryBean.setServiceInterface(serviceType);
122+
123+
jsonProxyFactoryBean.afterPropertiesSet();
124+
return (T) jsonProxyFactoryBean.getObject();
125+
}
126+
127+
@Override
128+
protected int getErrorCode(Throwable e) {
129+
if (e instanceof RemoteAccessException) {
130+
e = e.getCause();
131+
}
132+
if (e != null) {
133+
Class<?> cls = e.getClass();
134+
if (SocketTimeoutException.class.equals(cls)) {
135+
return RpcException.TIMEOUT_EXCEPTION;
136+
} else if (IOException.class.isAssignableFrom(cls)) {
137+
return RpcException.NETWORK_EXCEPTION;
138+
} else if (ClassNotFoundException.class.isAssignableFrom(cls)) {
139+
return RpcException.SERIALIZATION_EXCEPTION;
140+
}
141+
}
142+
return super.getErrorCode(e);
143+
}
144+
145+
@Override
146+
public void destroy() {
147+
super.destroy();
148+
for (String key : new ArrayList<>(serverMap.keySet())) {
149+
HttpServer server = serverMap.remove(key);
150+
if (server != null) {
151+
try {
152+
if (logger.isInfoEnabled()) {
153+
logger.info("Close jsonrpc server " + server.getUrl());
154+
}
155+
server.close();
156+
} catch (Throwable t) {
157+
logger.warn(t.getMessage(), t);
158+
}
159+
}
160+
}
161+
}
162+
163+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
jsonrpc=org.apache.dubbo.rpc.protocol.jsonrpc.JsonRpcProtocol

0 commit comments

Comments
 (0)