openapi.server.sdk.OpenApiGateway Maven / Gradle / Ivy
package openapi.server.sdk;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.*;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import openapi.sdk.common.enums.AsymmetricCryEnum;
import openapi.sdk.common.enums.SymmetricCryEnum;
import openapi.sdk.common.exception.OpenApiServerException;
import openapi.sdk.common.handler.AsymmetricCryHandler;
import openapi.sdk.common.handler.SymmetricCryHandler;
import openapi.sdk.common.model.*;
import openapi.sdk.common.util.CommonUtil;
import openapi.sdk.common.util.SymmetricCryUtil;
import openapi.server.sdk.model.ApiHandler;
import openapi.server.sdk.annotation.OpenApi;
import openapi.server.sdk.annotation.OpenApiMethod;
import openapi.sdk.common.constant.Constant;
import openapi.sdk.common.util.Base64Util;
import openapi.sdk.common.util.StrObjectConvert;
import openapi.server.sdk.config.OpenApiConfig;
import openapi.server.sdk.model.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.*;
/**
* 对外开放api网关入口
*
* 功能
* 1.负责对外开放接口(基于HTTP对外提供服务)
* 2.实现接口的参数与返回值的加解密(使用非对称加密:RSA/SM2,或对称加密:AES/SM4)
* 3.实现接口的验签(服务端会校验客户端的签名,确保调用者身份以及数据不被篡改)
* 4.实现非对称加密+对称加密联合模式(内容对称加密,对称加密密钥采用非对称加密)
*
*
* @author wanghuidong
*/
@Slf4j
@RestController
public class OpenApiGateway {
/**
* 定义api处理器映射
* key: api_method
* value: ApiHandler
*/
private Map apiHandlerMap = new HashMap<>();
@Autowired
private Context context;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private OpenApiConfig config;
/**
* 日志前缀
*/
private ThreadLocal logPrefix = new ThreadLocal<>();
private AsymmetricCryEnum asymmetricCryEnum;
private String selfPrivateKey;
private boolean retEncrypt;
private boolean enableSymmetricCry;
private SymmetricCryEnum symmetricCryEnum;
/**
* 非对称加密处理器
*/
private AsymmetricCryHandler asymmetricCryHandler;
/**
* 对称加密处理器
*/
private SymmetricCryHandler symmetricCryHandler;
/**
* 初始化
*/
@PostConstruct
public void init() {
//初始化配置信息
initConfig();
//初始化所有的openapi处理器
initApiHandlers();
//打印基本信息
if (log.isDebugEnabled()) {
String handlersStr = getHandlersStr();
log.debug("OpenApiGateway Init: \nSelfPrivateKey:{},\nAsymmetricCry:{},\nretEncrypt:{},\nenableSymmetricCry:{},\nSymmetricCry:{},\nApiHandlers:\n{}",
selfPrivateKey, asymmetricCryEnum, retEncrypt, enableSymmetricCry, symmetricCryEnum, handlersStr);
logCryMode(this.enableSymmetricCry);
}
//重要日志改成info级别
log.info("OpenApiGateway init succeed. path={}", Constant.OPENAPI_PATH);
}
/**
* 获取所有的openapi处理器的字符串表示
*
* @return openapi处理器列表
*/
private String getHandlersStr() {
Collection handlers = apiHandlerMap.values();
String handlersStr = StrUtil.EMPTY;
if (CollUtil.isEmpty(handlers)) {
handlersStr = "未找到ApiHandler,请确保注解@OpenApi所声明的bean可被spring扫描到";
} else {
for (ApiHandler handler : handlers) {
handlersStr += handler + "\n";
}
}
return handlersStr;
}
/**
* 初始化配置信息
*/
private void initConfig() {
this.selfPrivateKey = config.getSelfPrivateKey();
this.asymmetricCryEnum = config.getAsymmetricCry();
this.retEncrypt = config.retEncrypt();
this.enableSymmetricCry = config.enableSymmetricCry();
this.symmetricCryEnum = config.getSymmetricCry();
this.asymmetricCryHandler = AsymmetricCryHandler.handlerMap.get(this.asymmetricCryEnum);
this.symmetricCryHandler = SymmetricCryHandler.handlerMap.get(this.symmetricCryEnum);
}
/**
* 初始化所有的openapi处理器
*/
private void initApiHandlers() {
Map beanMap = applicationContext.getBeansWithAnnotation(OpenApi.class);
for (Map.Entry entry : beanMap.entrySet()) {
String beanName = entry.getKey();
Object bean = entry.getValue();
Class c = bean.getClass();
//获取开放api名称
OpenApi openApi = (OpenApi) c.getAnnotation(OpenApi.class);
String openApiName = openApi.value();
//遍历方法
Method[] methods = c.getDeclaredMethods();
if (ArrayUtil.isNotEmpty(methods)) {
for (Method method : methods) {
if (method.isAnnotationPresent(OpenApiMethod.class)) {
//获取开放api方法名称
OpenApiMethod openApiMethod = method.getAnnotation(OpenApiMethod.class);
String openApiMethodName = openApiMethod.value();
//获取方法参数类型
Type[] types = method.getGenericParameterTypes();
//获取方法参数
Parameter[] parameters = method.getParameters();
//保存处理器到Map中
String handlerKey = getHandlerKey(openApiName, openApiMethodName);
ApiHandler apiHandler = new ApiHandler();
apiHandler.setOpenApiName(openApiName);
apiHandler.setOpenApiMethodName(openApiMethodName);
apiHandler.setBeanName(beanName);
apiHandler.setBean(bean);
apiHandler.setMethod(method);
apiHandler.setParamTypes(types);
apiHandler.setParameters(parameters);
apiHandler.setOpenApiMethod(openApiMethod);
apiHandlerMap.put(handlerKey, apiHandler);
}
}
}
}
//将openapi处理器保存到上下文对象中去
context.setApiHandlers(this.apiHandlerMap.values());
}
/**
* 调用具体的方法
*
* @param inParams 入参
* @return 出参
*/
@PostMapping(value = Constant.OPENAPI_PATH, consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
public OutParams callMethod(@RequestBody InParams inParams) {
//设置日志前缀
logPrefix.set(String.format("uuid=%s:", inParams.getUuid()));
OutParams outParams = null;
try {
log.debug("{}接收到请求:{}", logPrefix.get(), inParams);
//获取openapi处理器
ApiHandler apiHandler = getApiHandler(inParams);
//获取方法参数
List