package com.example.demo.client.proxy;
import com.example.demo.client.annotation.APIServer;
import com.example.demo.client.beans.MethodInfo;
import com.example.demo.client.beans.ServerInfo;
import com.example.demo.client.client.RestHandler;
import com.example.demo.client.client.WebClientRestHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* jdk动态代理类对象
*/
@Slf4j
public class JdkDynamicAopProxy implements ProxyCreator {
RestHandler restHandler = new WebClientRestHandler();
@Override
public Object createProxy(Class<?> type) {
// 抽取服务器信息
ServerInfo serverInfo = extractServerInfo(type);
log.info("serverInfo :{}", serverInfo);
// 初始化服务器信息(webClient)
restHandler.init(serverInfo);
return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{type}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 抽取所有请求信息封装到 MethodInfo 对象
MethodInfo methodInfo = extractMethodInfo(method, args);
log.info("methodInfo :{}", methodInfo);
// 调用Rest客户端 处理请求
return restHandler.invokeRest(methodInfo);
}
private MethodInfo extractMethodInfo(Method method, Object[] args) {
MethodInfo methodInfo = new MethodInfo();
// 封装url和请求方式
extractRequsetUrlAndMethod(method, methodInfo);
// 封装请求参数和body
extractRequestParamsAndBody(method, args, methodInfo);
// 封装返回信息
extractReturnInfo(method, methodInfo);
return methodInfo;
}
/**
* 抽取返回的是Mono还是Flux和返回对象的类型
* @param method
* @param methodInfo
*/
private void extractReturnInfo(Method method, MethodInfo methodInfo) {
// 返回Mono还是Flux
// isAssignableFrom() 判断类型是否是某个类的子类 vs instanceof 判断实例是否是某个的子类
boolean isFlux = method.getReturnType().isAssignableFrom(Flux.class);
methodInfo.setReturnFlux(isFlux);
// 得到返回对象的实际类型
Class<?> elementType = extractElementType(method.getGenericReturnType());
methodInfo.setReturnElementType(elementType);
}
/**
*得到泛型的实际类型
* @param genericReturnType
* @return
*/
private Class<?> extractElementType(Type genericReturnType) {
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
return (Class<?>) actualTypeArguments[0];
}
/**
* 抽取请求参数和请求body
* @param method
* @param args
* @param methodInfo
*/
private void extractRequestParamsAndBody(Method method, Object[] args, MethodInfo methodInfo) {
Map<String, Object> params = new LinkedHashMap<>();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
// 参数信息
PathVariable annotation = parameters[i].getAnnotation(PathVariable.class);
if (annotation != null) {
params.put(annotation.value(), args[i]);
methodInfo.setParams(params);
}
// 请求body和body类型
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
if (requestBody != null) {
methodInfo.setBody((Mono<?>) args[i]);
methodInfo.setBodyElementType(extractElementType(parameters[i].getParameterizedType()));
}
}
}
/**
* 抽取请求url 和请求方式
* @param method
* @param methodInfo
*/
private void extractRequsetUrlAndMethod(Method method, MethodInfo methodInfo) {
Annotation[] annotations = method.getAnnotations();
Arrays.stream(annotations).forEach(annotation -> {
if (annotation instanceof GetMapping) {
GetMapping getMethod = (GetMapping) annotation;
methodInfo.setUrl(getMethod.value()[0]);
methodInfo.setHttpMethod(HttpMethod.GET);
} else if (annotation instanceof PostMapping) {
PostMapping postMethod = (PostMapping) annotation;
methodInfo.setUrl(postMethod.value()[0]);
methodInfo.setHttpMethod(HttpMethod.POST);
} else if (annotation instanceof DeleteMapping) {
DeleteMapping deleteMethod = (DeleteMapping) annotation;
methodInfo.setUrl(deleteMethod.value()[0]);
methodInfo.setHttpMethod(HttpMethod.DELETE);
} else if (annotation instanceof PutMapping) {
PutMapping putMethod = (PutMapping) annotation;
methodInfo.setUrl(putMethod.value()[0]);
methodInfo.setHttpMethod(HttpMethod.PUT);
}
});
}
});
}
/**
* 封装服务器信息
*
* @param type
* @return
*/
private ServerInfo extractServerInfo(Class<?> type) {
String url = type.getAnnotation(APIServer.class).value();
return ServerInfo.builder().url(url).build();
}
}
Spring5 webFIux Demo
需积分: 0 84 浏览量
2023-10-17
16:03:36
上传
评论
收藏 28KB ZIP 举报
Qz1997
- 粉丝: 36
- 资源: 5
最新资源
- 基于GUI+MYSQL+JAVA图书管理系统文档说明+源码(高分大作业项目).zip
- 基于Qt使用C++实现图书管理系统源码+数据库(95分以上).zip
- 基于GUI+MYSQL+JAVA票务管理系统文档介绍+源码+数据库(高分大作业).zip
- 优先编码器除法电微分运算电路 全加器函数发生电路等电路经典Multisim仿真实验源文件合集(25个).zip
- 2331308JS课堂案例.zip
- STM32H750VBT6单片机最小系统开发板AD设计硬件(原理图+PCB+3D封装库)工程文件.zip
- 基于74LS161+ 74LS192芯片实现倒计时定时器Multisim仿真源文件,Multisim10以上版本可打开运行
- 科大讯飞语音引擎 jar包 demo,科大讯飞语音合成引擎3.0,支持4.0系统以上,文字转语音输出.zip
- Java架构面试笔试专题资料及经验(含答案)SpringBoot面试Linux面试专题及答案 合集.zip
- 头歌c语言实验答案tion-model-for-ne开发笔记
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈