从dubbo转到springcloud,觉得springcloud家族组件很全,但是用起来稍微麻烦,每个api 都要写一个控制器来处理http请求 .
于是对相关代码进行抽象,使用统一控制器方法来处理请求,返回结果.
在定义接口的时候,url使用统一的开头 /api/*,将需要调用的类和方法标记到url中.比如
@RequestLine("GET /api/com.fhs.basics.api.rpc.FeignWordBookApiService/getWordBookListByWordBookGroupCode?wordBookGroupCode={wordBookGroupCode}")
然后定义好参数的处理方式,如果是表单参数使用@Param注解标记,如果是@RequestBody 使用 @RequestBody标记.
/**
* 字典公共服务
*/
@FeignClient(value = "basics", configuration = FeignConfiguration.class,primary = false)
public interface FeignWordBookApiService {
/**
* 根据字典编码获取字典信息
* @param wordBookGroupCode 字典编码
* @return HttpResult 角色数据权限
*/
@RequestLine("GET /api/com.fhs.basics.api.rpc.FeignWordBookApiService/getWordBookListByWordBookGroupCode?wordBookGroupCode={wordBookGroupCode}")
HttpResult> getWordBookListByWordBookGroupCode(@Param("wordBookGroupCode") String wordBookGroupCode);
}
这样由统一的控制器拦截处理此请求后就拿到了 类,方法,参数.
首先拿到类名,方法名,然后通过反射拿到方法,解析方法的参数(根据注解来决定从body读取还是通过request.getParameter获取),拿到参数后,调用方法返回返回值.
/**
* 执行RPC方法
*
* @param serviceClass 方法类
* @param methodName 方法名
* @param request req
* @param response res
*/
@RequestMapping("/api/{serviceClass}/{methodName}")
public void doExec(@PathVariable() String serviceClass,@PathVariable() String methodName, HttpServletRequest request, HttpServletResponse response) {
ParamChecker.isNotNullOrEmpty(serviceClass, "serviceClass 不可为空");
ParamChecker.isNotNullOrEmpty(methodName, "methodName 不可为空");
if(!this.apiToken.equals(request.getHeader("apiToken"))){
throw new ParamException("token不正确,非法调用");
}
try {
Class clazz = Class.forName(serviceClass);
if (!clazz.isAnnotationPresent(FeignClient.class)) {
throw new ParamException("调用方法非Feign接口");
}
Method method = ReflectUtils.getMethodd(clazz, methodName);
if (method == null) {
throw new ParamException("方法不存在");
}
Object[] params = new Object[method.getParameterTypes().length];
Annotation[][] annotations = method.getParameterAnnotations();
int index = 0;
outside:
for (Annotation[] oneParamAnnotations : annotations) {
for (Annotation annotation : oneParamAnnotations) {
if (annotation instanceof RequestBody) {
String jsonString = readAsChars(request);
params = new Object[]{JSONObject.parseObject(jsonString, method.getParameters()[0].getType())};
break outside;
} else if (annotation instanceof RequestParam) {
RequestParam tempParam = (RequestParam)annotation;
params[index] = request.getParameter(tempParam.defaultValue());
}
}
index++;
}
Object service = SpringContextUtil.getBeanByClassForApi(clazz);
try {
Object result = method.invoke(service, params);
JsonUtils.outJson(response, JsonUtils.bean2json(result));
} catch (IllegalAccessException e) {
log.error("", e);
} catch (InvocationTargetException e) {
log.error("", e);
}
} catch (ClassNotFoundException e) {
throw new ParamException("serviceClass 名称错误");
}
}
全部源码地址:https://gitee.com/fhs-opensource/fhs-framework/blob/v2.x/fhs_extends/fhs_base/fhs_base_other/src/main/java/com/fhs/core/base/controller/ApiController.java
开源项目地址:https://gitee.com/fhs-opensource/fhs-framework
fhs framework qq群:976278956