需求:
- 提供一个统一的对外接口,调用者传入统一格式的json来进行调用到不同的接口并返回统一格式的json
请求url:
127.0.0.1:30072/openapi/api/v1/json
请求示例代码:
{
"method": "system_ping",
"timestamp": "1576565002744",
"sign": "7D57278C74EC01DF33F8F826A8683F83",
"data": "{\"str\":\"测试参数\"}"
}
返回示例代码:
{
"code": 0,
"msg": "成功",
"data": {
"msg": "请求参数str为:测试参数"
}
}
实现
说明:以下很多代码为说明如何一个接口获取不同服务的方法,没做异常处理等其他代码优化,请注意.
controller提供web方法
第一种方式
定义一个枚举RequestEnum,保存method,并根据method获取到对应枚举,来进行switch循环(不推荐)
优点: 小白都看得懂
缺点: 每次加service都需要改controller来加case
具体代码如下:
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hs
* @Description: {枚举}
* @date 2019/12/16 17:19
*/
@Getter
@AllArgsConstructor
public enum RequestEnum {
SYSTEM_PING("system_ping"),
CATEGORY_ONE_QUERY("category_write_query"),
CATEGORY_TWO_QUERY("category_two_query"),
GOODS_QUERY("goods_write_query""),
ORDERS_QUERY("orders_write_query");
private String method;
/**
* 获取对应枚举类型
*
* @param method
* @return
*/
public static RequestEnum getEnum(String method) {
for (RequestEnum requestEnum : RequestEnum.values()) {
if (requestEnum.getMethod().equals(method)) {
return requestEnum;
}
}
return null;
}
}
/**
* controller方法
* service方法统一为map形参
*
/
@PostMapping("/api/v1/json")
@ApiOperation(value = "json", notes = "json")
public ApiResponseResult openapiv1(@RequestBody ApiRequestParam apiRequestParam){
RequestEnum requestEnum = RequestEnum.getEnum(apiRequestParam.getMethod());
if (requestEnum == null) {
return ApiResponseResult.send(ResultEnum.FAILURE_4);
}
Map<String, String> param = JSONUtil.toBean(apiRequestParam.getData(), Map.class);
// 根据method获取对应内容
switch (requestEnum) {
case SYSTEM_PING:
return systemService.ping(param);
case CATEGORY_ONE_QUERY:
return categoryOneService.query(param);
case CATEGORY_TWO_QUERY:
return categoryTwoService.query(param);
case GOODS_QUERY:
return goodsService.query(param);
case ORDERS_QUERY:
return ordersService.query(param);
default:
return ApiResponseResult.send(ResultEnum.OTHER);
}
}
第二种方式
定义一个枚举RequestEnum,保存method,和对应完全限定名和方法名并根据method获取到对应枚举,来进行反射获取对应类(不推荐)
优点: 使用反射不需要每次改controller层
缺点: 直接获取到对应类,没有spring特性了
具体代码如下:
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hs
* @Description: {枚举}
* @date 2019/12/16 17:19
*/
@Getter
@AllArgsConstructor
public enum RequestEnum {
SYSTEM_PING("system_ping","com.handy.xxx.xxx.methodxx","xxx"),
CATEGORY_ONE_QUERY("category_query","com.handy.methodxx","xxx"),
CATEGORY_TQUERY("category_two_query","com.handy.methodxx","xxx"),
GOODS_QUERY("goods_query","com.handy.xxx.xxx.methodxx","xxx"),
ORDERS_QUERY("orders__query","com.handy.xxx.xxx.methodxx","xxx");
private String method;
private String interfaceName;
private String methodName;
/**
* 获取对应枚举类型
*
* @param method
* @return
*/
public static RequestEnum getEnum(String method) {
for (RequestEnum requestEnum : RequestEnum.values()) {
if (requestEnum.getMethod().equals(method)) {
return requestEnum;
}
}
return null;
}
}
/**
* controller方法
* service方法统一为map形参
*
/
@PostMapping("/api/v1/json")
@ApiOperation(value = "json", notes = "json")
public ApiResponseResult openapiv2(@RequestBody ApiRequestParam apiRequestParam) throws Exception {
RequestEnum requestEnum = RequestEnum.getEnum(apiRequestParam.getMethod());
if (requestEnum == null) {
return ApiResponseResult.send(ResultEnum.FAILURE_4);
}
Class<?> mClass = Class.forName(requestEnum.getInterfaceName());
Method method = mClass.getMethod(requestEnum.getMethodName(), Map.class);
return (ApiResponseResult) method.invoke(mClass.newInstance(), JSONUtil.toBean(apiRequestParam.getData(), Map.class));
}
第三种方式
定义一个枚举RequestEnum,保存method,和对应完全限定名和方法名并根据method获取到对应枚举,使用spring的方式获取对应类(推荐)
优点: 使用反射不需要每次改controller层,保留spring特性
缺点: 暂无
具体代码如下:
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hs
* @Description: {枚举}
* @date 2019/12/16 17:19
*/
@Getter
@AllArgsConstructor
public enum RequestEnum {
SYSTEM_PING("system_ping","com.handy.xxx.xxx.methodxx","xxx"),
CATEGORY_ONE_QUERY("category_query","com.handy.methodxx","xxx"),
CATEGORY_TQUERY("category_two_query","com.handy.methodxx","xxx"),
GOODS_QUERY("goods_query","com.handy.xxx.xxx.methodxx","xxx"),
ORDERS_QUERY("orders__query","com.handy.xxx.xxx.methodxx","xxx");
private String method;
private String interfaceName;
private String methodName;
/**
* 获取对应枚举类型
*
* @param method
* @return
*/
public static RequestEnum getEnum(String method) {
for (RequestEnum requestEnum : RequestEnum.values()) {
if (requestEnum.getMethod().equals(method)) {
return requestEnum;
}
}
return null;
}
}
@PostMapping("/v1/json")
@ApiOperation(value = "json", notes = "json")
public ApiResponseResult openapiv3(@RequestBody ApiRequestParam apiRequestParam) throws Exception {
RequestEnum requestEnum = RequestEnum.getEnum(apiRequestParam.getMethod());
if (requestEnum == null) {
return ApiResponseResult.send(ResultEnum.FAILURE_4);
}
Class<?> c = ClassUtils.forName(requestEnum.getInterfaceName(), ClassUtils.getDefaultClassLoader());
Object obj = ContextUtil.getBean(c);
Map map = null;
if (StrUtil.isEmpty(apiRequestParam.getData())) {
map = Maps.newHashMapWithExpectedSize(1);
} else {
map = JSONUtil.toBean(apiRequestParam.getData(), Map.class);
}
return (ApiResponseResult) obj.getClass().getDeclaredMethod(requestEnum.getMethodName(), Map.class).invoke(obj, map);
}