Skip to content

Commit 6186f94

Browse files
committed
1
1 parent b25e413 commit 6186f94

12 files changed

Lines changed: 296 additions & 53 deletions

File tree

07rpc/rpc01/rpcfx-core/pom.xml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@
2323
<artifactId>fastjson</artifactId>
2424
<version>1.2.70</version>
2525
</dependency>
26-
26+
<dependency>
27+
<groupId>org.apache.httpcomponents</groupId>
28+
<artifactId>httpclient</artifactId>
29+
<version>4.5.2</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>net.bytebuddy</groupId>
33+
<artifactId>byte-buddy</artifactId>
34+
</dependency>
2735
<dependency>
2836
<groupId>com.squareup.okhttp3</groupId>
2937
<artifactId>okhttp</artifactId>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.kimmking.rpcfx.annotation;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Inherited;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
@Documented
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Target({ElementType.TYPE})
13+
@Inherited
14+
public @interface RpcfxService {
15+
Class<?> interfaceClass() default void.class;
16+
String interfaceName() default "";
17+
}

07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/api/RpcfxResolver.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ public interface RpcfxResolver {
44

55
Object resolve(String serviceClass);
66

7+
void initService(String servicePath);
8+
79
}

07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,49 @@
33

44
import com.alibaba.fastjson.JSON;
55
import com.alibaba.fastjson.parser.ParserConfig;
6+
import io.kimmking.rpcfx.utils.HttpUtils;
7+
import io.kimmking.rpcfx.exception.RpcException;
68
import io.kimmking.rpcfx.api.RpcfxRequest;
79
import io.kimmking.rpcfx.api.RpcfxResponse;
10+
import net.bytebuddy.ByteBuddy;
11+
import net.bytebuddy.implementation.InvocationHandlerAdapter;
12+
import net.bytebuddy.matcher.ElementMatchers;
813
import okhttp3.MediaType;
9-
import okhttp3.OkHttpClient;
10-
import okhttp3.Request;
11-
import okhttp3.RequestBody;
14+
import okhttp3.internal.http2.ErrorCode;
1215

1316
import java.io.IOException;
1417
import java.lang.reflect.InvocationHandler;
18+
import java.lang.reflect.InvocationTargetException;
1519
import java.lang.reflect.Method;
1620
import java.lang.reflect.Proxy;
21+
import java.util.HashMap;
22+
import java.util.Map;
1723

1824
public final class Rpcfx {
1925

2026
static {
2127
ParserConfig.getGlobalInstance().addAccept("io.kimmking");
2228
}
2329

24-
public static <T> T create(final Class<T> serviceClass, final String url) {
25-
26-
// 0. 替换动态代理 -> AOP
27-
return (T) Proxy.newProxyInstance(Rpcfx.class.getClassLoader(), new Class[]{serviceClass}, new RpcfxInvocationHandler(serviceClass, url));
30+
public static <T> T create(final Class<T> serviceClass, final String url)
31+
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
2832

33+
// 0. 替换动态代理 -> 字节码增强
34+
return serviceClass.cast(getByteBuddyProxy(serviceClass, url));
35+
}
36+
private static <T> Object getByteBuddyProxy(Class<T> serviceClass, String url)
37+
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
38+
return new ByteBuddy()
39+
.subclass(Object.class)
40+
.name(serviceClass.getCanonicalName() + "$ByteBuddyProxy")
41+
.implement(serviceClass)
42+
.method(ElementMatchers.any())
43+
.intercept(InvocationHandlerAdapter.of(new RpcfxInvocationHandler(serviceClass, url)))
44+
.make()
45+
.load(Rpcfx.class.getClassLoader())
46+
.getLoaded()
47+
.getDeclaredConstructor()
48+
.newInstance();
2949
}
3050

3151
public static class RpcfxInvocationHandler implements InvocationHandler {
@@ -39,10 +59,9 @@ public <T> RpcfxInvocationHandler(Class<T> serviceClass, String url) {
3959
this.url = url;
4060
}
4161

42-
// 可以尝试,自己去写对象序列化,二进制还是文本的,,,rpcfx是xml自定义序列化、反序列化,json: code.google.com/p/rpcfx
43-
// int byte char float double long bool
62+
// TODO: 2020/12/17 可以尝试,自己去写对象序列化,二进制还是文本的,,,rpcfx是xml自定义序列化、反序列化,json: code.google.com/p/rpcfx
63+
// int byte char float double long bool
4464
// [], data class
45-
4665
@Override
4766
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
4867
RpcfxRequest request = new RpcfxRequest();
@@ -51,10 +70,12 @@ public Object invoke(Object proxy, Method method, Object[] params) throws Throwa
5170
request.setParams(params);
5271

5372
RpcfxResponse response = post(request, url);
54-
5573
// 这里判断response.status,处理异常
5674
// 考虑封装一个全局的RpcfxException
57-
75+
if(!response.isStatus()){
76+
System.out.println("error" + response);
77+
throw new RpcException(ErrorCode.CONNECT_ERROR);
78+
}
5879
return JSON.parse(response.getResult().toString());
5980
}
6081

@@ -64,12 +85,7 @@ private RpcfxResponse post(RpcfxRequest req, String url) throws IOException {
6485

6586
// 1.可以复用client
6687
// 2.尝试使用httpclient或者netty client
67-
OkHttpClient client = new OkHttpClient();
68-
final Request request = new Request.Builder()
69-
.url(url)
70-
.post(RequestBody.create(JSONTYPE, reqJson))
71-
.build();
72-
String respJson = client.newCall(request).execute().body().string();
88+
String respJson = HttpUtils.httpPostJson(reqJson,url);
7389
System.out.println("resp json: "+respJson);
7490
return JSON.parseObject(respJson, RpcfxResponse.class);
7591
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package io.kimmking.rpcfx.exception;
2+
3+
import okhttp3.internal.http2.ErrorCode;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
7+
import static okhttp3.internal.http2.ErrorCode.PROTOCOL_ERROR;
8+
9+
/**
10+
* @author tangtian
11+
* @version 1.0
12+
* @className RpcException
13+
* @description
14+
* @date 2020/12/16 8:21 PM
15+
**/
16+
public class RpcException extends RuntimeException {
17+
private static final Logger LOG = LoggerFactory.getLogger(RpcException.class);
18+
private static final long serialVersionUID = -7864604160297181941L;
19+
20+
/** 错误码 */
21+
protected final ErrorCode errorCode;
22+
// NO_ERROR(0),
23+
// PROTOCOL_ERROR(1),
24+
// INTERNAL_ERROR(2),
25+
// FLOW_CONTROL_ERROR(3),
26+
// REFUSED_STREAM(7),
27+
// CANCEL(8),
28+
// COMPRESSION_ERROR(9),
29+
// CONNECT_ERROR(10),
30+
// ENHANCE_YOUR_CALM(11),
31+
// INADEQUATE_SECURITY(12),
32+
// HTTP_1_1_REQUIRED(13);
33+
34+
/**
35+
* 这个是和谐一些不必要的地方,冗余的字段
36+
* 尽量不要用
37+
*/
38+
private String code;
39+
40+
/**
41+
* 无参默认构造UNSPECIFIED
42+
*/
43+
public RpcException() {
44+
super("");
45+
this.errorCode = PROTOCOL_ERROR;
46+
}
47+
48+
/**
49+
* 指定错误码构造通用异常
50+
* @param errorCode 错误码
51+
*/
52+
public RpcException(final ErrorCode errorCode) {
53+
super("");
54+
this.errorCode = errorCode;
55+
}
56+
57+
/**
58+
* 构造通用异常
59+
* @param errorCode 错误码
60+
* @param detailedMessage 详细描述
61+
* @param t 导火索
62+
*/
63+
public RpcException(final ErrorCode errorCode, final String detailedMessage,
64+
final Throwable t) {
65+
super(detailedMessage, t);
66+
this.errorCode = errorCode;
67+
}
68+
69+
/**
70+
* Getter method for property <tt>errorCode</tt>.
71+
*
72+
* @return property value of errorCode
73+
*/
74+
public ErrorCode getErrorCode() {
75+
return errorCode;
76+
}
77+
78+
}

07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/server/RpcfxInvoker.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.alibaba.fastjson.JSON;
44
import com.alibaba.fastjson.serializer.SerializerFeature;
5+
import io.kimmking.rpcfx.exception.RpcException;
56
import io.kimmking.rpcfx.api.RpcfxRequest;
67
import io.kimmking.rpcfx.api.RpcfxResolver;
78
import io.kimmking.rpcfx.api.RpcfxResponse;
@@ -13,9 +14,10 @@
1314
public class RpcfxInvoker {
1415

1516
private RpcfxResolver resolver;
16-
17-
public RpcfxInvoker(RpcfxResolver resolver){
17+
public RpcfxInvoker(RpcfxResolver resolver, String servicePath){
1818
this.resolver = resolver;
19+
// 初始化服务
20+
resolver.initService(servicePath);
1921
}
2022

2123
public RpcfxResponse invoke(RpcfxRequest request) {
@@ -24,25 +26,21 @@ public RpcfxResponse invoke(RpcfxRequest request) {
2426

2527
// 作业1:改成泛型和反射
2628
Object service = resolver.resolve(serviceClass);//this.applicationContext.getBean(serviceClass);
27-
2829
try {
2930
Method method = resolveMethodFromClass(service.getClass(), request.getMethod());
30-
Object result = method.invoke(service, request.getParams()); // dubbo, fastjson,
31-
// 两次json序列化能否合并成一个
32-
response.setResult(JSON.toJSONString(result, SerializerFeature.WriteClassName));
31+
Object result = method.invoke(service, request.getParams());
32+
// 两次json序列化合并成一个
33+
response.setResult(result);
3334
response.setStatus(true);
34-
return response;
35-
} catch ( IllegalAccessException | InvocationTargetException e) {
36-
35+
} catch (IllegalAccessException | InvocationTargetException e) {
3736
// 3.Xstream
38-
3937
// 2.封装一个统一的RpcfxException
4038
// 客户端也需要判断异常
4139
e.printStackTrace();
42-
response.setException(e);
40+
response.setException(new RpcException());
4341
response.setStatus(false);
44-
return response;
4542
}
43+
return response;
4644
}
4745

4846
private Method resolveMethodFromClass(Class<?> klass, String methodName) {
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package io.kimmking.rpcfx.utils;
2+
3+
import org.apache.http.NameValuePair;
4+
import org.apache.http.client.config.RequestConfig;
5+
import org.apache.http.client.entity.UrlEncodedFormEntity;
6+
import org.apache.http.client.methods.CloseableHttpResponse;
7+
import org.apache.http.client.methods.HttpGet;
8+
import org.apache.http.client.methods.HttpPost;
9+
import org.apache.http.client.utils.URIBuilder;
10+
import org.apache.http.entity.ContentType;
11+
import org.apache.http.entity.StringEntity;
12+
import org.apache.http.impl.client.CloseableHttpClient;
13+
import org.apache.http.impl.client.HttpClients;
14+
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
15+
import org.apache.http.message.BasicNameValuePair;
16+
import org.apache.http.protocol.HTTP;
17+
import org.apache.http.util.EntityUtils;
18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
20+
21+
import java.io.IOException;
22+
import java.net.URI;
23+
import java.nio.charset.StandardCharsets;
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
import java.util.Map;
27+
28+
/**
29+
* @author tangtian
30+
* @version 1.0
31+
* @className HttpUtils
32+
* @description
33+
* @date 2020/12/16 8:06 PM
34+
**/
35+
public class HttpUtils {
36+
private final static CloseableHttpClient httpClient;
37+
private final static int CONNECT_TIMEOUT = 5000;
38+
private final static RequestConfig requestConfig;
39+
40+
static {
41+
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
42+
connectionManager.setMaxTotal(500);
43+
connectionManager.setDefaultMaxPerRoute(50);
44+
requestConfig = RequestConfig.custom()
45+
.setConnectionRequestTimeout(CONNECT_TIMEOUT)
46+
.setConnectTimeout(CONNECT_TIMEOUT)
47+
.setSocketTimeout(CONNECT_TIMEOUT).build();
48+
49+
httpClient = HttpClients.custom()
50+
.setConnectionManager(connectionManager)
51+
.setDefaultRequestConfig(requestConfig)
52+
.build();
53+
}
54+
55+
public static String httpPostJson(final String json, final String url) {
56+
final HttpPost httpPost = new HttpPost(url);
57+
httpPost.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
58+
httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json;charset=utf-8");
59+
StringEntity requestEntity = new StringEntity(json, StandardCharsets.UTF_8);
60+
httpPost.setEntity(requestEntity);
61+
try {
62+
CloseableHttpResponse response = httpClient.execute(httpPost);
63+
return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
64+
} catch (Exception e) {
65+
throw new RuntimeException("httpclient请求失败!");
66+
}
67+
}
68+
}

07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import io.kimmking.rpcfx.demo.api.UserService;
88
import org.springframework.boot.autoconfigure.SpringBootApplication;
99

10+
import java.lang.reflect.InvocationTargetException;
11+
1012
@SpringBootApplication
1113
public class RpcfxClientApplication {
1214

@@ -15,7 +17,7 @@ public class RpcfxClientApplication {
1517
// nexus, userserivce -> userdao -> user
1618
//
1719

18-
public static void main(String[] args) {
20+
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
1921

2022
// UserService service = new xxx();
2123
// service.findById

07rpc/rpc01/rpcfx-demo-provider/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@
3737
<groupId>org.springframework.boot</groupId>
3838
<artifactId>spring-boot-starter-web</artifactId>
3939
</dependency>
40-
40+
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
41+
<dependency>
42+
<groupId>org.reflections</groupId>
43+
<artifactId>reflections</artifactId>
44+
<version>0.9.12</version>
45+
</dependency>
4146
<dependency>
4247
<groupId>org.springframework.boot</groupId>
4348
<artifactId>spring-boot-starter-test</artifactId>

0 commit comments

Comments
 (0)