package com.vci.ubcs.omd.repeater; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.ServiceInfo; import com.vci.ubcs.omd.dto.BtmAndLinkTypeDdlDTO; import com.vci.ubcs.omd.vo.BtmTypeVO; import com.vci.ubcs.omd.vo.LinkTypeVO; import org.springblade.core.launch.constant.AppConstant; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.StringPool; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import javax.annotation.PostConstruct; import java.util.*; import java.util.stream.Collectors; /** * Description: 领域转发器 * * @author LiHang * @date 2023/4/25 */ @Component public class DomainRepeater { /** * 控制器路径 */ public static final String API_PREFIX = "ddl"; /** * 新增或修改的转发路径名称 */ public static final String API_SUBMIT = API_PREFIX + StringPool.SLASH + "submit"; /** * 表名获取表信息 */ public static final String API_GET_TABLE_INFO = API_PREFIX + StringPool.SLASH + "getTableColumnByTableName"; /** * 获取全部表信息 */ public static final String API_GET_ALL_TABLE_INFO = API_PREFIX + StringPool.SLASH + "getAllTableInfo"; /** * 获取数据库和业务类型中的不同的地方 */ public static final String API_CHECK_DIFFERENT_REFLEX = API_PREFIX + StringPool.SLASH + "checkDifferentAndReflex"; /** * 用于构建静态服务类 */ public static DomainRepeater domainRepeater; /** * Nacos服务列表 */ private static NamingService namingService; @Autowired private NacosServiceManager manager; @Autowired private NacosDiscoveryProperties properties; @PostConstruct private void init() { domainRepeater = this; namingService = manager.getNamingService(properties.getNacosProperties()); } /** * 一致性检查 * @param ddlDTO 业务类型、链接类型传输对象 * @param serviceName 服务名 * @return 执行结果,有修改的就会返回。 * @throws NacosException nacos查询服务出错时抛出异常 */ public static R checkDifferent(BtmAndLinkTypeDdlDTO ddlDTO,String serviceName) throws NacosException { try { String url = getUrl(serviceName, API_CHECK_DIFFERENT_REFLEX); ResponseEntity responseEntity = executePost(url, JSONObject.toJSONString(ddlDTO), null); if (responseEntity.getStatusCode().equals(HttpStatus.OK)) { R body = Objects.requireNonNull(responseEntity.getBody()); return body; } return R.fail(String.valueOf(responseEntity.getStatusCode().value())); }catch (HttpClientErrorException e) { if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) { R fail = R.fail("调用服务失败"); fail.setCode(HttpStatus.NOT_FOUND.value()); return fail; } } catch (Exception e) { throw new RuntimeException(e); } return R.fail("未知错误"); } /** * 根据api接口拼接url地址 * @param serviceName 服务名 * @param api 接口地址 * @return url地址 * @throws NacosException nacos查询服务出错时抛出异常 */ public static String getUrl(String serviceName,String api) throws NacosException { Instance service = namingService.selectOneHealthyInstance(AppConstant.APPLICATION_GATEWAY_NAME); return "http://" + service.getIp() + StringPool.COLON + service.getPort() + StringPool.SLASH + serviceName + StringPool.SLASH + api; } /** * 新增或修改业务类型 * @param vo 业务类型传输对象 * @param serviceName 服务名 * @return 执行结果,有修改的就会返回。 */ public static R submitBtmType(String serviceName, BtmTypeVO vo) { try { String url = getUrl(serviceName, API_SUBMIT); BtmAndLinkTypeDdlDTO ddlDTO = new BtmAndLinkTypeDdlDTO(); ddlDTO.setBtmTypeList(new ArrayList<>(Collections.singletonList(vo))); ResponseEntity responseEntity = executePost(url, JSONObject.toJSONString(ddlDTO), null); if (responseEntity.getStatusCode().equals(HttpStatus.OK)) { return responseEntity.getBody(); } return R.fail(String.valueOf(responseEntity.getStatusCode().value())); } catch (HttpClientErrorException e) { if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) { R fail = R.fail("调用服务失败"); fail.setCode(HttpStatus.NOT_FOUND.value()); return fail; } } catch (Exception e) { throw new RuntimeException(e); } return R.fail("未知错误"); } /** * 新增或修改链接类型 * @param vo 业务类型传输对象 * @param serviceName 服务名 * @return 执行结果,有修改的就会返回。 */ public static R submitLinkType(String serviceName, LinkTypeVO vo) { try { String url = getUrl(serviceName, API_SUBMIT); BtmAndLinkTypeDdlDTO ddlDTO = new BtmAndLinkTypeDdlDTO(); ddlDTO.setLinkTypeList(new ArrayList<>(Collections.singletonList(vo))); ResponseEntity responseEntity = executePost(url, JSONObject.toJSONString(ddlDTO), null); if (responseEntity.getStatusCode().equals(HttpStatus.OK)) { return responseEntity.getBody(); } return R.fail(String.valueOf(responseEntity.getStatusCode().value())); } catch (HttpClientErrorException e) { if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) { R fail = R.fail("调用服务失败"); fail.setCode(HttpStatus.NOT_FOUND.value()); return fail; } } catch (Exception e) { throw new RuntimeException(e); } return R.fail("未知错误"); } /** * 执行httpPost接口 * * @param url 地址 * @param body 请求体 * @param extraHeaders 请求头参数 * @return 执行结果 */ private static ResponseEntity executePost(String url, String body, Map extraHeaders) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add("Content-Type", "application/json;charset=UTF-8"); httpHeaders.add("Blade-Auth", AuthUtil.getHeader()); Optional.ofNullable(extraHeaders).orElseGet(HashMap::new).forEach(httpHeaders::add); HttpEntity request = new HttpEntity<>(body, httpHeaders); return restTemplate.postForEntity(url, request, R.class); } /** * 获取所有已注册的服务 * @return 不包含默认服务的其他服务 * @throws NacosException */ public static List getDomain() throws NacosException { List services = namingService.getSubscribeServices(); Set serviceNames = new HashSet<>(); serviceNames.add(AppConstant.APPLICATION_GATEWAY_NAME); serviceNames.add(AppConstant.APPLICATION_ADMIN_NAME); serviceNames.add(AppConstant.APPLICATION_AUTH_NAME); serviceNames.add(AppConstant.APPLICATION_DESK_NAME); serviceNames.add(AppConstant.APPLICATION_DEVELOP_NAME); serviceNames.add(AppConstant.APPLICATION_FLOW_NAME); serviceNames.add(AppConstant.APPLICATION_FLOWDESIGN_NAME); serviceNames.add(AppConstant.APPLICATION_LOG_NAME); serviceNames.add(AppConstant.APPLICATION_REPORT_NAME); serviceNames.add(AppConstant.APPLICATION_SWAGGER_NAME); serviceNames.add(AppConstant.APPLICATION_SYSTEM_NAME); serviceNames.add(AppConstant.APPLICATION_TURBINE_NAME); serviceNames.add(AppConstant.APPLICATION_USER_NAME); serviceNames.add(AppConstant.APPLICATION_WEBSOCKET_NAME); serviceNames.add(AppConstant.APPLICATION_ZIPKIN_NAME); serviceNames.add(AppConstant.APPLICATION_NAME_OMD); return services.stream().map(ServiceInfo::getName).filter(s -> !serviceNames.contains(s)).collect(Collectors.toList()); } }