chengf
2025-07-14 fb8580a155be1aee12be78e424e78678c18012ad
service-api/src/main/java/com/java110/api/smo/impl/ApiServiceSMOImpl.java
old mode 100755 new mode 100644
@@ -2,10 +2,12 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.utils.StringUtils;
import com.java110.api.smo.IApiServiceSMO;
import com.java110.core.client.RestTemplate;
import com.java110.core.context.ApiDataFlow;
import com.java110.core.context.DataFlow;
import com.java110.core.context.Environment;
import com.java110.core.event.service.api.ServiceDataFlowEventPublishing;
import com.java110.core.factory.AuthenticationFactory;
import com.java110.core.factory.DataFlowFactory;
@@ -13,25 +15,31 @@
import com.java110.core.log.LoggerFactory;
import com.java110.core.smo.ISaveTransactionLogSMO;
import com.java110.core.trace.Java110TraceLog;
import com.java110.entity.center.AppRoute;
import com.java110.entity.center.AppService;
import com.java110.entity.center.DataFlowLinksCost;
import com.java110.po.transactionLog.TransactionLogPo;
import com.java110.dto.order.OrderDto;
import com.java110.dto.system.AppRoute;
import com.java110.dto.system.AppService;
import com.java110.dto.system.DataFlowLinksCost;
import com.java110.po.log.TransactionLogPo;
import com.java110.utils.cache.AppRouteCache;
import com.java110.utils.cache.MappingCache;
import com.java110.utils.constant.*;
import com.java110.utils.constant.CommonConstant;
import com.java110.utils.constant.KafkaConstant;
import com.java110.utils.constant.MappingConstant;
import com.java110.utils.constant.ResponseConstant;
import com.java110.utils.exception.*;
import com.java110.utils.factory.ApplicationContextFactory;
import com.java110.utils.kafka.KafkaFactory;
import com.java110.utils.log.LoggerEngine;
import com.java110.utils.util.BootReplaceUtil;
import com.java110.utils.util.DateUtil;
import com.java110.utils.util.StringUtil;
import com.java110.vo.ResultVo;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;
import java.util.Date;
import java.util.List;
@@ -79,21 +87,21 @@
        String resJson = "";
        try {
            //在post和 put 时才存在报文加密的情况
            //todo 在post和 put 时才存在报文加密的情况
            if ("POST,PUT".contains(headers.get(CommonConstant.HTTP_METHOD))) {
                reqJson = decrypt(reqJson, headers);
            }
            //1.0 创建数据流 appId serviceCode
            //todo 1.0 创建数据流 appId serviceCode
            dataFlow = DataFlowFactory.newInstance(ApiDataFlow.class).builder(reqJson, headers);
            //2.0 加载配置信息
            //todo 2.0 加载配置信息
            initConfigData(dataFlow);
            //3.0 校验 APPID是否有权限操作serviceCode
            //todo 3.0 校验 APPID是否有权限操作serviceCode
            judgeAuthority(dataFlow);
            //6.0 调用下游系统
            //todo 6.0 调用下游系统
            invokeBusinessSystem(dataFlow);
            responseEntity = dataFlow.getResponseEntity();
@@ -148,7 +156,7 @@
        String serviceCode = dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE);
        String logServiceCode = MappingCache.getValue(MappingConstant.DOMAIN_SYSTEM_SWITCH,MappingCache.LOG_SERVICE_CODE);
        String logServiceCode = MappingCache.getValue(MappingConstant.DOMAIN_SYSTEM_SWITCH, MappingCache.LOG_SERVICE_CODE);
        //日志查询不记录
        if ("/transactionLog/queryTransactionLog".equals(serviceCode)
@@ -310,25 +318,25 @@
            throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "TRANSACTION_ID 不能为空");
        }
        if (!StringUtil.isNullOrNone(dataFlow.getAppRoutes().get(0).getSecurityCode())) {
            String sign = AuthenticationFactory.apiDataFlowMd5(dataFlow);
            if (!sign.equals(dataFlow.getReqSign().toLowerCase())) {
                throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "签名失败");
            }
        }
//        if (!StringUtil.isNullOrNone(dataFlow.getAppRoutes().get(0).getSecurityCode())) {
//            String sign = AuthenticationFactory.apiDataFlowMd5(dataFlow);
//            if (StringUtil.isEmpty(dataFlow.getReqSign()) || !sign.equals(dataFlow.getReqSign().toLowerCase())) {
//                throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "签名失败");
//            }
//        }
        if (StringUtil.isNullOrNone(dataFlow.getRequestTime()) || !DateUtil.judgeDate(dataFlow.getRequestTime(), DateUtil.DATE_FORMATE_STRING_DEFAULT)) {
            //添加耗时
            DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
            throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "requestTime 格式不对,遵循yyyyMMddHHmmss格式");
        }
        //用户ID校验
        //todo 用户ID校验
        if (StringUtil.isNullOrNone(dataFlow.getUserId())) {
            throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "USER_ID 不能为空");
        }
        //判断 AppId 是否有权限操作相应的服务
        //todo 判断 AppId 是否有权限操作相应的服务
        AppService appService = DataFlowFactory.getService(dataFlow, dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
        //这里调用缓存 查询缓存信息
@@ -367,9 +375,9 @@
     */
    private void invokeBusinessSystem(ApiDataFlow dataFlow) throws BusinessException {
        Date startDate = DateUtil.getCurrentDate();
        //拿到当前服务
        //todo 拿到当前服务
        AppService appService = DataFlowFactory.getService(dataFlow, dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
        //这里对透传类处理
        //todo 这里对透传类处理,目前很少用到,可以不用关注
        if ("NT".equals(appService.getIsInstance())) {
            //如果是透传类 请求方式必须与接口提供方调用方式一致
            String httpMethod = dataFlow.getRequestCurrentHeaders().get(CommonConstant.HTTP_METHOD);
@@ -377,28 +385,277 @@
                throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR,
                        "服务【" + appService.getServiceCode() + "】调用方式不对请检查,当前请求方式为:" + httpMethod);
            }
            dataFlow.setApiCurrentService(ServiceCodeConstant.SERVICE_CODE_DO_SERVICE_TRANSFER);
        } else if ("T".equals(appService.getIsInstance())) {
            //dataFlow.setApiCurrentService(ServiceCodeConstant.SERVICE_CODE_DO_SERVICE_TRANSFER);
            doNT(appService, dataFlow, dataFlow.getReqJson());
            return;
        } else if ("T".equals(appService.getIsInstance())) { // todo 通过透传方式 调用 目前很少用到,可以不用关注
            //todo 如果是透传类 请求方式必须与接口提供方调用方式一致
            String httpMethod = dataFlow.getRequestCurrentHeaders().get(CommonConstant.HTTP_METHOD);
            if (!appService.getMethod().equals(httpMethod)) {
                throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR,
                        "服务【" + appService.getServiceCode() + "】调用方式不对请检查,当前请求方式为:" + httpMethod);
            }
            doTransfer(appService, dataFlow, dataFlow.getReqJson());
            return;
        } else if ("CMD".equals(appService.getIsInstance())) { // todo 微服务调用方式,目前主要用这种方式调度分发 到不同的微服务,这里是通过c_service 中配置 调用到不同的微服务
            //如果是透传类 请求方式必须与接口提供方调用方式一致
            String httpMethod = dataFlow.getRequestCurrentHeaders().get(CommonConstant.HTTP_METHOD);
            if (!appService.getMethod().equals(httpMethod)) {
                throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR,
                        "服务【" + appService.getServiceCode() + "】调用方式不对请检查,当前请求方式为:" + httpMethod);
            }
            dataFlow.setApiCurrentService(ServiceCodeConstant.SERVICE_CODE_SYSTEM_TRANSFER);
        } else if ("CMD".equals(appService.getIsInstance())) {
            //如果是透传类 请求方式必须与接口提供方调用方式一致
            String httpMethod = dataFlow.getRequestCurrentHeaders().get(CommonConstant.HTTP_METHOD);
            if (!appService.getMethod().equals(httpMethod)) {
                throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR,
                        "服务【" + appService.getServiceCode() + "】调用方式不对请检查,当前请求方式为:" + httpMethod);
            }
            dataFlow.setApiCurrentService(ServiceCodeConstant.SERVICE_CODE_SYSTEM_CMD);
            // todo 根据接口编码找到 appService 也就是c_service 表中的内容
            dealCmd(appService, dataFlow, dataFlow.getReqJson());
            return;
        } else {
            dataFlow.setApiCurrentService(dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
        }
        ServiceDataFlowEventPublishing.multicastEvent(dataFlow, appService);
        DataFlowFactory.addCostTime(dataFlow, "invokeBusinessSystem", "调用下游系统耗时", startDate);
    }
    private void doNT(AppService service, ApiDataFlow dataFlow, JSONObject reqJson) {
        HttpHeaders header = new HttpHeaders();
        for (String key : dataFlow.getRequestCurrentHeaders().keySet()) {
            header.add(key, dataFlow.getRequestCurrentHeaders().get(key));
        }
        HttpEntity<String> httpEntity = new HttpEntity<String>(reqJson.toJSONString(), header);
        //http://user-service/test/sayHello
        ResponseEntity responseEntity = null;
        //配置c_service 时请注意 如果是以out 开头的调用外部的地址
        RestTemplate restTemplate;
        if (Environment.isStartBootWay()) {
            restTemplate = ApplicationContextFactory.getBean("outRestTemplate", RestTemplate.class);
        } else {
            restTemplate = ApplicationContextFactory.getBean("restTemplate", RestTemplate.class);
        }
        try {
            if (CommonConstant.HTTP_METHOD_GET.equals(service.getMethod())) {
                String requestUrl = dataFlow.getRequestHeaders().get("REQUEST_URL");
                if (!StringUtil.isNullOrNone(requestUrl)) {
                    String param = requestUrl.contains("?") ? requestUrl.substring(requestUrl.indexOf("?") + 1, requestUrl.length()) : "";
                    if (service.getUrl().contains("?")) {
                        requestUrl = service.getUrl() + "&" + param;
                    } else {
                        requestUrl = service.getUrl() + "?" + param;
                    }
                }
                if (Environment.isStartBootWay()) {
                    requestUrl = BootReplaceUtil.replaceServiceName(requestUrl);
                }
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.GET, httpEntity, String.class);
            } else if (CommonConstant.HTTP_METHOD_PUT.equals(service.getMethod())) {
                responseEntity = restTemplate.exchange(service.getUrl(), HttpMethod.PUT, httpEntity, String.class);
            } else if (CommonConstant.HTTP_METHOD_DELETE.equals(service.getMethod())) {
                String requestUrl = dataFlow.getRequestHeaders().get("REQUEST_URL");
                if (!StringUtil.isNullOrNone(requestUrl)) {
                    String param = requestUrl.contains("?") ? requestUrl.substring(requestUrl.indexOf("?"), requestUrl.length()) : "";
                    if (service.getUrl().contains("?")) {
                        requestUrl = service.getUrl() + "&" + param;
                    } else {
                        requestUrl = service.getUrl() + "?" + param;
                    }
                }
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.DELETE, httpEntity, String.class);
            } else {
                String requestUrl = BootReplaceUtil.replaceServiceName(service.getUrl());
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);
            }
        } catch (HttpStatusCodeException e) { //这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下
            responseEntity = new ResponseEntity<String>(e.getResponseBodyAsString(), e.getStatusCode());
        }
        logger.debug("API 服务调用下游服务请求:{},返回为:{}", httpEntity, responseEntity);
        dataFlow.setResponseEntity(responseEntity);
    }
    private void doTransfer(AppService appService, ApiDataFlow dataFlow, JSONObject reqJson) {
        Map<String, String> reqHeader = dataFlow.getRequestCurrentHeaders();
        HttpHeaders header = new HttpHeaders();
        for (String key : dataFlow.getRequestCurrentHeaders().keySet()) {
            header.add(key, reqHeader.get(key));
        }
        HttpEntity<String> httpEntity = new HttpEntity<String>(reqJson.toJSONString(), header);
        String orgRequestUrl = dataFlow.getRequestHeaders().get("REQUEST_URL");
        //String serviceCode = "/" + reqHeader.get(CommonConstant.HTTP_RESOURCE) + "/" + reqHeader.get(CommonConstant.HTTP_ACTION);
        String serviceCode = appService.getServiceCode();
        serviceCode = serviceCode.startsWith("/") ? serviceCode : ("/" + serviceCode);
        //String requestUrl = "http://127.0.0.1:8008" + serviceCode;
        String requestUrl = serviceCode;
        RestTemplate restTemplate;
        if (Environment.isStartBootWay()) {
            requestUrl = Environment.BOOT_PATH + requestUrl;
            restTemplate = ApplicationContextFactory.getBean("outRestTemplate", RestTemplate.class);
        } else {
            requestUrl = appService.getUrl() + requestUrl;
            restTemplate = ApplicationContextFactory.getBean("restTemplate", RestTemplate.class);
        }
        ResponseEntity responseEntity = null;
        if (!StringUtil.isNullOrNone(orgRequestUrl)) {
            String param = orgRequestUrl.contains("?") ? orgRequestUrl.substring(orgRequestUrl.indexOf("?") + 1, orgRequestUrl.length()) : "";
            requestUrl += ("?" + param);
        }
        try {
            if (CommonConstant.HTTP_METHOD_GET.equals(appService.getMethod())) {
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.GET, httpEntity, String.class);
            } else if (CommonConstant.HTTP_METHOD_PUT.equals(appService.getMethod())) {
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.PUT, httpEntity, String.class);
            } else if (CommonConstant.HTTP_METHOD_DELETE.equals(appService.getMethod())) {
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.DELETE, httpEntity, String.class);
            } else {
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);
            }
            HttpHeaders headers = responseEntity.getHeaders();
            String oId = "-1";
            if (headers.containsKey(OrderDto.O_ID)) {
                oId = headers.get(OrderDto.O_ID).get(0);
            }
//            //进入databus
//            if (!CommonConstant.HTTP_METHOD_GET.equals(appService.getMethod())) {
//
//                // dealDatabus(serviceCode, reqJson, oId);
//            }
        } catch (HttpStatusCodeException e) { //这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下
            logger.error("请求下游服务【" + requestUrl + "】异常,参数为" + httpEntity + e.getResponseBodyAsString(), e);
            String body = e.getResponseBodyAsString();
            if (StringUtil.isJsonObject(body)) {
                JSONObject bodyObj = JSONObject.parseObject(body);
                if (bodyObj.containsKey("message") && !StringUtil.isEmpty(bodyObj.getString("message"))) {
                    body = bodyObj.getString("message");
                }
            }
            responseEntity = new ResponseEntity<String>(body, e.getStatusCode());
        }
        logger.debug("API 服务调用下游服务请求:{},返回为:{}", httpEntity, responseEntity);
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            responseEntity = ResultVo.createResponseEntity(ResultVo.CODE_ERROR, String.valueOf(responseEntity.getBody()));
            dataFlow.setResponseEntity(responseEntity);
            return;
        }
        if (StringUtils.isEmpty(responseEntity.getBody() + "")) {
            responseEntity = ResultVo.createResponseEntity(ResultVo.CODE_ERROR, "处理失败");
            dataFlow.setResponseEntity(responseEntity);
            return;
        }
        JSONObject resParam = JSONObject.parseObject(responseEntity.getBody() + "");
        if (resParam.containsKey("code") && resParam.containsKey("msg")) { // 说明微服务返回的是 resultVo 对象直接返回就可以
            dataFlow.setResponseEntity(responseEntity);
            return;
        }
        responseEntity = ResultVo.createResponseEntity(resParam);
        dataFlow.setResponseEntity(responseEntity);
    }
    /**
     * 开始调度微服务
     *
     * @param appService
     * @param dataFlow
     * @param reqJson
     */
    private void dealCmd(AppService appService, ApiDataFlow dataFlow, JSONObject reqJson) {
        Map<String, String> reqHeader = dataFlow.getRequestCurrentHeaders();
        HttpHeaders header = new HttpHeaders();
        //todo 对头信息重新包装
        for (String key : dataFlow.getRequestCurrentHeaders().keySet()) {
            if ("userName".equals(key) || "user-name".equals(key)) {
                header.add(key, "-");
                continue;
            }
            header.add(key, reqHeader.get(key));
        }
        //todo 用户信息再次包装
        if (reqHeader.containsKey(CommonConstant.USER_ID)
                && (!reqJson.containsKey("userId") || StringUtil.isEmpty(reqJson.getString("userId")))) {
            reqJson.put("userId", reqHeader.get(CommonConstant.USER_ID));
        }
        if (reqHeader.containsKey(CommonConstant.USER_ID)
                && (!reqJson.containsKey("loginUserId") || StringUtil.isEmpty(reqJson.getString("loginUserId")))) {
            reqJson.put("loginUserId", reqHeader.get(CommonConstant.LOGIN_U_ID));
        }
        if (reqHeader.containsKey(CommonConstant.STORE_ID)
                && (!reqJson.containsKey("storeId") || StringUtil.isEmpty(reqJson.getString("storeId")))) {
            reqJson.put("storeId", reqHeader.get(CommonConstant.STORE_ID));
        }
        HttpEntity<String> httpEntity = new HttpEntity<String>(reqJson.toJSONString(), header);
        String orgRequestUrl = dataFlow.getRequestHeaders().get("REQUEST_URL");
        String serviceCode = appService.getServiceCode();
        serviceCode = serviceCode.startsWith("/") ? serviceCode : ("/" + serviceCode);
        //todo 组装调用微服务的地址
        //String requestUrl = "http://127.0.0.1:8008/cmd" + serviceCode;
        String requestUrl = "/cmd" + serviceCode;
        //
        ResponseEntity responseEntity = null;
        //todo url 带了地址这里 拼接
        if (!StringUtil.isNullOrNone(orgRequestUrl)) {
            String param = orgRequestUrl.contains("?") ? orgRequestUrl.substring(orgRequestUrl.indexOf("?") + 1, orgRequestUrl.length()) : "";
            requestUrl += ("?" + param);
        }
        try {
            //todo http的方式调用微服务,相应的java类可以到相应微服务下的cmd下根据serviceCode 的寻找
            //todo 这里会调用到 java110-service 模块下的 CmdApi 类,这个类各个微服务都会集成
            if (Environment.isStartBootWay()) {
                requestUrl = Environment.BOOT_PATH + requestUrl;
                restTemplate = ApplicationContextFactory.getBean("outRestTemplate", RestTemplate.class);
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);
            } else {
                requestUrl = appService.getUrl() + requestUrl;
                restTemplate = ApplicationContextFactory.getBean("restTemplate", RestTemplate.class);
                responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);
            }
            HttpHeaders headers = responseEntity.getHeaders();
            String oId = "-1";
            if (headers.containsKey(OrderDto.O_ID)) {
                oId = headers.get(OrderDto.O_ID).get(0);
            }
        } catch (HttpStatusCodeException e) { //todo 这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下
            logger.error("请求下游服务【" + requestUrl + "】异常,参数为" + httpEntity + e.getResponseBodyAsString(), e);
            String body = e.getResponseBodyAsString();
            if (StringUtil.isJsonObject(body)) {
                JSONObject bodyObj = JSONObject.parseObject(body);
                if (bodyObj != null && bodyObj.containsKey("message") && !StringUtil.isEmpty(bodyObj.getString("message"))) {
                    body = bodyObj.getString("message");
                }
            }
            responseEntity = new ResponseEntity<String>(body, e.getStatusCode());
        }
        logger.debug("API 服务调用下游服务请求:{},返回为:{}", httpEntity, responseEntity);
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            responseEntity = ResultVo.createResponseEntity(ResultVo.CODE_ERROR, String.valueOf(responseEntity.getBody()));
            dataFlow.setResponseEntity(responseEntity);
            return;
        }
        if (StringUtils.isEmpty(responseEntity.getBody() + "")) {
            responseEntity = ResultVo.createResponseEntity(ResultVo.CODE_ERROR, "处理失败");
            dataFlow.setResponseEntity(responseEntity);
            return;
        }
        dataFlow.setResponseEntity(responseEntity);
    }
@@ -410,7 +667,7 @@
    private void saveLogMessage(String requestJson, String responseJson) {
        try {
            if (MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.DOMAIN_SYSTEM_SWITCH,MappingConstant.KEY_LOG_ON_OFF))) {
            if (MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.DOMAIN_SYSTEM_SWITCH, MappingConstant.KEY_LOG_ON_OFF))) {
                JSONObject log = new JSONObject();
                log.put("request", requestJson);
                log.put("response", responseJson);
@@ -428,7 +685,7 @@
     */
    private void saveCostTimeLogMessage(DataFlow dataFlow) {
        try {
            if (MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.DOMAIN_SYSTEM_SWITCH,MappingConstant.KEY_COST_TIME_ON_OFF))) {
            if (MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.DOMAIN_SYSTEM_SWITCH, MappingConstant.KEY_COST_TIME_ON_OFF))) {
                List<DataFlowLinksCost> dataFlowLinksCosts = dataFlow.getLinksCostDates();
                JSONObject costDate = new JSONObject();
                JSONArray costDates = new JSONArray();