- 项目使用feign进行模块间rpc调用解耦
- RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务,调用本地接口一样调用远程接口的方式,就是RPC
- 而Feign是Spring Cloud全家桶中推荐使用的RPC框架,使用了HTTP作为传输层协议,底层封装的是Spring RestTemplate。
- 是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。
调用方通过创建一个Feign提供者接口(不需要实现),url+requestMapping指向http接口
V2通用接口主要增加了 对象传参的支持,
调用链:
CommonFeignService -->ConsumerController–>SpringBeanInvoker–>SpringBeanInvokerImpl
如用户新增接口
interface UserService{
/**
* 新增数据
* 2020-09-01
* @param user
* @return
* @author yuhui
*/
int addUser(User user);
}
新版本feign接口调用
class SsoLoginServiceImpl{
/**
*部门单点登录
*部分实现
*/
public String deptSsoLogin(String authorization, String uid, String userAccount, String userName, String deptName, String deptCode) throws UnknownHostException {
//创建用户对象。
JSONObject user = new JSONObject();
user.put("userAccount", userAccount);
String password = Md5Crypt.md5Crypt("Qwer123$".getBytes());
user.put("password", password);
user.put("userName", userName);
user.put("enabled", "1");
user.put("userType", "0");
user.put("userDesc", "通过单点登录介入");
//支持对象json传参。
request.setArgs(new Object[]{JSONObject.toJSONString(user)});
String res = iCommonFeignService.autoJson2BeanInvoke(request);
}
}
SpringBeanInvokerImpl核心代码
class SpringBeanInvokerImpl{
/**
* 1 根据入参参数类型与方法名直接查找对应类的方法. 匹配成功,则返回结果<br>
* 2 若1失败, 则遍历目标类方法,找到与入参方法名匹配的目标方法名. 若参数数量与接口参数要求数量一致. 则3 <br>
* 3 进行参数类型判断匹配. 判断接口入参类型, 尝试json转换, 若匹配成功,则返回结果,跳出循环.<br>
* 本方法适应重载方法.即同名不同参的方法.<br>
* 2019年9月5日上午10:05:13
*
* @param springBean
* @param methodName
* @param args
* @return
* @author whx
*/
private Method getBeanMethodByJsonParams(Object springBean, String methodName, Object... args) {
Method method = null;
//根据参数类型精确匹配.
Class<?>[] parameterTypes = null;
if (args != null && args.length > 0) {
parameterTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
parameterTypes[i] = args[i].getClass();
}
}
try {
method = springBean.getClass().getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
log.info("精确参数类型查找方法失败,使用遍历方法进行查找,并判断入参类型是否与原始方法参数类型一致或入参类型是原始方法参数的子类/实现.");
Method[] methods = springBean.getClass().getMethods();
for (int i = 0; i < methods.length; i++) {
Method subMethod = methods[i];
if (subMethod.getName().equals(methodName)) {
Class<?>[] methodParamTypes = subMethod.getParameterTypes();
if (methodParamTypes == null || methodParamTypes.length <= 0) {
method = subMethod;
} else {
//如果参数类型长度不匹配.则直接返回
if (parameterTypes == null || (methodParamTypes.length != parameterTypes.length)) {
method = null;
} else {
//自动参数转换
boolean paramMatch = true;
try {
Object[] params = parameterTypesCheck(methodParamTypes, args, false);
if (params.length == args.length) {
paramMatch = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
if (paramMatch) {
method = subMethod;
break;
}
}
}
}
}
} catch (SecurityException e) {
e.printStackTrace();
}
return method;
}
}