Fegin中使用Fegin的Type模拟Fegin通过接口调用RestTemplate

 获取类中方法相关信息


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;
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值