获取类中方法相关信息
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.thx4cloud.thx.admin.api.constant.BizException;
import feign.Types;
import lombok.Data;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
public class RemoteMethodInfo {
String url;
Integer parameterCount = 0;
HttpMethod httpMethod;
Type returnType;
Map<Integer, String> uriIndexMap = new HashMap<>();
Map<Integer, String> paramIndexMap = new HashMap<>();
Map<Integer, String> paramMapIndexMap = new HashMap<>();
Map<Integer, String> headerIndexMap = new HashMap<>();
Integer bodyIndex = -1;
public RemoteMethodInfo(Method method, String url, HttpMethod httpMethod) {
this.url = url;
this.httpMethod = httpMethod;
this.returnType = getMethodReturnType(method);
this.parameterCount = method.getParameterCount();
Parameter[] parameters = method.getParameters();
if (parameters.length == 0) {
return;
}
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
Annotation[] annotations = parameter.getAnnotations();
if (annotations.length == 0) {
paramMapIndexMap.put(i, parameter.getName());
} else {
for (Annotation annotation : annotations) {
if (annotation instanceof RequestHeader) {
RequestHeader requestHeader = (RequestHeader) annotation;
headerIndexMap.put(i, requestHeader.value());
}
if (annotation instanceof RequestParam) {
RequestParam requestHeader = (RequestParam) annotation;
if (StrUtil.isBlank(requestHeader.value())) {
paramMapIndexMap.put(i, requestHeader.value());
} else {
paramIndexMap.put(i, requestHeader.value());
}
}
if (annotation instanceof PathVariable) {
PathVariable requestHeader = (PathVariable) annotation;
uriIndexMap.put(i, requestHeader.value());
}
if (annotation instanceof ResponseBody) {
ResponseBody requestHeader = (ResponseBody) annotation;
bodyIndex = -1;
}
}
}
}
}
static Method typesResolve = null;
static synchronized void iniTypesResolve() {
if (typesResolve == null) {
Method[] methods = Types.class.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("resolve")) {
typesResolve = method;
typesResolve.setAccessible(true);
return;
}
}
throw new BizException("Types中找不到resolve方法");
}
}
static Type getMethodReturnType(Method method) {
if (typesResolve == null) {
iniTypesResolve();
}
try {
Object type = typesResolve.invoke(null, method.getClass(), method.getClass(), method.getGenericReturnType());
return (Type) type;
} catch (Exception e) {
throw new BizException("获取返回值类型错误");
}
}
public Map<String, ?> uriVariables(Object... argv) {
if (argv.length != parameterCount) {
throw new BizException("远程调用参数不匹配");
}
Map<String, Object> map = new HashMap<>();
if (CollUtil.isNotEmpty(uriIndexMap)) {
for (Integer key : uriIndexMap.keySet()) {
map.put(uriIndexMap.get(key), argv[key]);
}
}
return map;
}
public HttpHeaders headers(Object... argv) {
if (argv.length != parameterCount) {
throw new BizException("远程调用参数不匹配");
}
HttpHeaders requestHeaders = new HttpHeaders();
if (CollUtil.isNotEmpty(headerIndexMap)) {
for (Integer key : headerIndexMap.keySet()) {
String header = argv[key].toString();
requestHeaders.add(headerIndexMap.get(key), header);
}
}
return requestHeaders;
}
public Object body(Object... argv) {
if (argv.length != parameterCount) {
throw new BizException("远程调用参数不匹配");
}
if (bodyIndex != -1) {
return argv[bodyIndex];
}
return null;
}
public String urlParameters(Object... argv) {
if (argv.length != parameterCount) {
throw new BizException("远程调用参数不匹配");
}
Map<String, Object> map = new HashMap<>();
if (CollUtil.isNotEmpty(paramIndexMap)) {
for (Integer key : paramIndexMap.keySet()) {
map.put(paramIndexMap.get(key), argv[key]);
}
}
if (CollUtil.isNotEmpty(paramMapIndexMap)) {
for (Integer key : paramMapIndexMap.keySet()) {
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(argv[key]);
if (jsonObject != null) {
for (String jsonKey : jsonObject.keySet()) {
if (jsonObject.get(jsonKey) != null) {
map.put(jsonKey, jsonObject.getString(jsonKey));
}
}
}
}
}
String str = "";
if (CollUtil.isNotEmpty(map)) {
List<String> strList = new ArrayList<>();
for (String key : map.keySet()) {
strList.add(key + "=" + map.get(key));
}
str = String.join("&", strList);
}
return str;
}
}
调用基础类,最后通过invoke进行方法调用
import cn.hutool.core.util.StrUtil;
import com.thx4cloud.thx.admin.api.constant.BizException;
import com.thx4cloud.thx.admin.api.entity.DeptModule;
import com.thx4cloud.thx.admin.dept.service.DeptModuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
/**
* 远程服务调用封装的基础类
*/
public abstract class BaseRemoteService {
@Autowired
DeptModuleService deptModuleService;
/**
* 方法名称与url映射
*/
Map<String, RemoteMethodInfo> methodUrlMap = null;
/**
* 服务名称
*/
String serviceName;
//Object remoteService;
/**
* 初始化一个方法Url映射
*
* @param cls
*/
protected synchronized void iniMethodUrlMap(Class cls) {
methodUrlMap = new HashMap<>();
FeignClient feignClient = AnnotationUtils.findAnnotation(cls, FeignClient.class);
if (feignClient == null) {
return;
}
serviceName = feignClient.value();
Method[] methods = cls.getMethods();
for (Method method : methods) {
PostMapping postMapping = AnnotationUtils.findAnnotation(method, PostMapping.class);
if (postMapping != null) {
putMethodInfo(method, postMapping.value(), HttpMethod.POST);
}
DeleteMapping deleteMapping = AnnotationUtils.findAnnotation(method, DeleteMapping.class);
if (deleteMapping != null) {
putMethodInfo(method, deleteMapping.value(), HttpMethod.DELETE);
}
PutMapping putMapping = AnnotationUtils.findAnnotation(method, PutMapping.class);
if (putMapping != null) {
putMethodInfo(method, putMapping.value(), HttpMethod.PUT);
}
GetMapping getMapping = AnnotationUtils.findAnnotation(method, GetMapping.class);
if (getMapping != null) {
putMethodInfo(method, getMapping.value(), HttpMethod.GET);
continue;
}
}
}
/**
* 得到一个部门的私服Url
*
* @param deptId
* @return
*/
protected String getPrivateServerUrl(Integer deptId) {
DeptModule deptModule = deptModuleService.getDeptModule(deptId, serviceName);
return deptModule == null ? "" : deptModule.getPrivateServerUrl();
}
protected Object invoke(String serviceUrl, String methodName, Object... argv) {
RemoteMethodInfo methodInfo = methodUrlMap.get(methodName);
if (methodInfo == null) {
throw new BizException("找不到需要调用的方法“" + methodName + "”");
}
return invoke(serviceUrl, methodInfo, argv);
}
private void putMethodInfo(Method method, String[] urls, HttpMethod httpMethod) {
String methodName = method.getName();
if (methodUrlMap.containsKey(methodName)) {
throw new BizException("远程调用服务类“" + method.getClass().getName() + "”中存在相同方法名“" + methodName + "“");
}
if (urls.length != 1) {
throw new BizException("远程调用服务类“" + method.getClass().getName() + "”方法“" + methodName + "“地址配置错误");
}
methodUrlMap.put(methodName, new RemoteMethodInfo(method, urls[0], httpMethod));
}
private Object invoke(String serviceUrl, RemoteMethodInfo methodInfo, Object... argv) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new AllEncompassingFormHttpMessageConverter());
Map<String, ?> uriVariables = methodInfo.uriVariables(argv);
String url = serviceUrl + methodInfo.getUrl();
HttpHeaders headers = methodInfo.headers(argv);
Object body = methodInfo.body(argv);
String parameterStr = methodInfo.urlParameters(argv);
if (StrUtil.isNotBlank(parameterStr)) {
url = url + (url.indexOf("?") > -1 ? "&" : "?") + parameterStr;
}
HttpEntity httpEntity = new HttpEntity(body, headers);
Type responseType = methodInfo.getReturnType();
RequestCallback requestCallback = restTemplate.httpEntityCallback(httpEntity, responseType);
ResponseExtractor<ResponseEntity<Object>> responseExtractor = restTemplate.responseEntityExtractor(responseType);
ResponseEntity<?> forEntity = restTemplate.execute(url, methodInfo.getHttpMethod(), requestCallback, responseExtractor, uriVariables);
if (forEntity.hasBody()) {
return forEntity.getBody();
} else {
return null;
}
}
}