diff --git a/ruoyi-auth/src/main/java/cc/mrbird/febs/auth/configure/TransportClient.java b/ruoyi-auth/src/main/java/cc/mrbird/febs/auth/configure/TransportClient.java new file mode 100644 index 0000000..6c53045 --- /dev/null +++ b/ruoyi-auth/src/main/java/cc/mrbird/febs/auth/configure/TransportClient.java @@ -0,0 +1,204 @@ +package cc.mrbird.febs.auth.configure; + + +import cn.cttic.crypto.bean.DecryptCodeBean; +import cn.cttic.crypto.bean.EncryptCodeBean; +import cn.cttic.crypto.bean.EncryptCrcBean; +import cn.cttic.crypto.service.SMCryptoService; +import cn.cttic.crypto.service.impl.SMCryptoServiceImpl; +import com.google.gson.Gson; +import com.ruoyi.common.core.domain.vo.TransportHeader; +import com.ruoyi.common.core.domain.vo.TransportRequest; +import com.ruoyi.common.core.domain.vo.TransportResponse; +import com.ruoyi.common.core.exception.TransportException; +import okhttp3.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + + +public class TransportClient { + + private static final Logger logger = LoggerFactory.getLogger(TransportClient.class); + + // 配置参数 + private static final String API_ENDPOINT = "https://xcx.12328.cn:8086/min12328"; + private static final String PROVINCE_AREA_CODE = "500000"; // 行政区划代码 + private static final String BASE_AREA_CODE = "999999"; // 基础系统标识 + private static final DateTimeFormatter DATE_FORMATTER = + DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + private static final String encrypt_key = "8iot1blDJgNK36Do"; // 行政区划代码 + private static final String decrypt_key = "QLdQIASYMlT9SUUg"; + private final OkHttpClient httpClient = new OkHttpClient(); + private final Gson gson = new Gson(); + private final AtomicLong sequence = new AtomicLong(1); + // 新增字段 + private long tokenExpirationTime; + private static final long TOKEN_TTL = 24 * 60 * 60 * 1000; // 24小时毫秒数 + // 新增加密服务实例(在类顶部) + private final SMCryptoService smCryptoService = new SMCryptoServiceImpl(); + + + public String sendRequest(String urlSuffix, String ipcType, Object bodyData) throws TransportException { + try { + + // 1. 构建请求报文 + TransportRequest request = buildRequest(ipcType, bodyData); + // 新增请求日志输出 + logger.info("完整请求报文:\n{}", gson.toJson(request)); + // 2. 发送HTTP请求 + String responseJson = postRequest(request, urlSuffix); + System.out.println(responseJson); + // 3. 处理响应 + TransportResponse response = parseResponse(responseJson); + return handleResponse(response, urlSuffix); + + } catch (Exception e) { + throw new TransportException("API请求失败: " + e.getMessage(), e); + } + } + + + // 构建请求报文结构 + private TransportRequest buildRequest(String ipcType, Object bodyData) throws Exception { + String plainBody = gson.toJson(bodyData); + + return new TransportRequest( + new TransportHeader( + generateSerialNumber(), + PROVINCE_AREA_CODE, // 省级标识 + PROVINCE_AREA_CODE, // 部级标识+省级标识 + BASE_AREA_CODE, // 部级标识 + "V1", + ipcType, + LocalDateTime.now().format(DATE_FORMATTER), + calculateSM3(plainBody), + "0", + "", + null, + null + ), + encryptBody(plainBody) + ); + } + + // 生成流水号(符合文档规范) + private String generateSerialNumber() { + + // 2. 当前日期(必须8位) + String datePart = LocalDateTime.now() + .format(DateTimeFormatter.BASIC_ISO_DATE); + + // 3. 12位序列号(使用原子计数器示例) + AtomicLong counter = new AtomicLong(1); // 实际应从数据库获取 + String sequence = String.format("%012d", counter.getAndIncrement() % 1000000000000L); + + return PROVINCE_AREA_CODE + datePart + sequence; + } + + // SM3哈希计算 + private String calculateSM3(String data) { + EncryptCrcBean encryptCrcBean = new EncryptCrcBean(); + encryptCrcBean.setPass(data); + String cipherText_crc = smCryptoService.encryptCrc(encryptCrcBean); + return cipherText_crc; + } + + // SM4加密(ECB模式) + private String encryptBody(String plainText) throws Exception { + EncryptCodeBean encryptCodeBean = new EncryptCodeBean(); + encryptCodeBean.setSecretKey(encrypt_key); + encryptCodeBean.setPass(plainText); + String cipherText = smCryptoService.encrypt_Body(encryptCodeBean); + return cipherText; + } + + // SM4解密(ECB模式) + private String decryptBody(String plainText) throws Exception { + DecryptCodeBean encrypt2 = new DecryptCodeBean(); + encrypt2.setSecretKey(decrypt_key); + encrypt2.setPass(plainText); + String cipherText = smCryptoService.decrypt_Body(encrypt2); + return cipherText; + } + + // 发送HTTP请求 + private String postRequest(TransportRequest request, String urlSuffix) throws Exception { + String json = gson.toJson(request); + + RequestBody body = RequestBody.create(json, MediaType.get("application/json")); + Request httpRequest = new Request.Builder() + .url(API_ENDPOINT + urlSuffix) + .post(body) + .build(); + + try (Response response = httpClient.newCall(httpRequest).execute()) { + if (!response.isSuccessful()) { + throw new TransportException("HTTP错误: " + response.code()); + } + return response.body().string(); + } + } + + // 解析响应 + private TransportResponse parseResponse(String json) { + return gson.fromJson(json, TransportResponse.class); + } + + // 处理业务响应 + private String handleResponse(TransportResponse response, String urlSuffix) throws TransportException { + TransportHeader header = response.getHeader(); + String currentToken = ""; + if (!"0000".equals(header.getCode())) { + throw new TransportException("业务错误[" + header.getCode() + "]: " + + header.getMessage()); + } + // 更新Token + if (response.getBody() != null && response.getBody() != "") { + try { + TokenResponse tokenResponse = gson.fromJson(decryptBody(String.valueOf(response.getBody())), TokenResponse.class); + currentToken = tokenResponse.getToken(); + logger.info(currentToken); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return currentToken; + } + + // 新增TokenResponse类 + public class TokenResponse { + private String token; + // getter/setter + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + } + + // 初始化及使用示例 + public String getToken() { + String token = ""; + TransportClient client = new TransportClient(); + Map paramsMap = new HashMap<>(); + paramsMap.put("user", "admin"); + paramsMap.put("password", "ZDg3NDA5NjUyYmNk"); + // 1. 获取Token + try { + token = client.sendRequest("/sys/login", "YZ1001", paramsMap); + + } catch (TransportException e) { + logger.info("身份验证失败: " + e.getMessage()); + throw new RuntimeException(e); + } + return token; + } +} \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/TransportException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/TransportException.java new file mode 100644 index 0000000..8b40ef2 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/TransportException.java @@ -0,0 +1,6 @@ +package com.ruoyi.common.core.exception; + +public class TransportException extends Exception { + public TransportException(String message) { super(message); } + public TransportException(String message, Throwable cause) { super(message, cause); } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/controller/InBusinessController.java b/ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/controller/InBusinessController.java new file mode 100644 index 0000000..5bf7693 --- /dev/null +++ b/ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/controller/InBusinessController.java @@ -0,0 +1,587 @@ +package com.ruoyi.business.controller; + +import cn.cttic.crypto.bean.DecryptCodeBean; +import cn.cttic.crypto.bean.EncryptCodeBean; +import cn.cttic.crypto.bean.EncryptCrcBean; +import cn.cttic.crypto.service.SMCryptoService; +import cn.cttic.crypto.service.impl.SMCryptoServiceImpl; +import cn.hutool.core.date.StopWatch; +import com.google.gson.Gson; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ruoyi.business.constant.BusinessServiceEnum; +import com.ruoyi.business.domain.*; +import com.ruoyi.business.domain.vo.*; +import com.ruoyi.business.service.IAdapterService; +import com.ruoyi.business.service.IServiceBusinessService; +import com.ruoyi.common.core.domain.vo.TransportHeader; +import com.ruoyi.common.core.domain.vo.TransportRequest; +import com.ruoyi.common.core.domain.vo.TransportRequestInfo; +import com.ruoyi.common.core.domain.vo.TransportResponse; +import com.ruoyi.common.core.exception.BusinessException; +import com.ruoyi.common.core.exception.TransportException; +import com.ruoyi.common.core.utils.ServletUtils; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.system.service.ISysDictDataService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.*; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.sql.DataSource; +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicLong; +import com.alibaba.fastjson.*; + +import static com.ruoyi.common.core.constant.Constants.DELETE_NO; +import static com.ruoyi.common.core.constant.HttpStatus.UNAUTHORIZED; +import static com.ruoyi.common.core.web.domain.AjaxResult.success; + +@Slf4j +@Validated +@RestController +@RequestMapping("/inBusiness") +@RequiredArgsConstructor +public class InBusinessController { + + private static final Logger logger = LoggerFactory.getLogger(InBusinessController.class); + + // 配置参数 + private static final String API_ENDPOINT = "https://xcx.12328.cn:8086/min12328"; + private static final String PROVINCE_AREA_CODE = "500000"; // 行政区划代码 + private static final String BASE_AREA_CODE = "999999"; // 基础系统标识 + private static final DateTimeFormatter DATE_FORMATTER = + DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + private static final String encrypt_key = "8iot1blDJgNK36Do"; // 行政区划代码 + private static final String decrypt_key = "QLdQIASYMlT9SUUg"; + private final OkHttpClient httpClient = new OkHttpClient(); + private final Gson gson = new Gson(); + private final AtomicLong sequence = new AtomicLong(1); + // 新增字段 + private long tokenExpirationTime; + private static final long TOKEN_TTL = 24 * 60 * 60 * 1000; // 24小时毫秒数 + // 新增加密服务实例(在类顶部) + private final SMCryptoService smCryptoService = new SMCryptoServiceImpl(); + + private final DataSource dataSource; + private final ISysDictDataService sysDictDataService; + private final IAdapterService adapterService; + private final IServiceBusinessService serviceBusinessService; + + // @InnerAuth + @GetMapping + public AjaxResult inBusiness(@RequestParam("exchangeResolveId") Long id) throws Exception { + StopWatch sw = StopWatch.create("sw"); + sw.start(); + + // 获取请求头中的currentToken字段 + HttpHeaders reqHeaders = new HttpHeaders(); + reqHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + String auth = ServletUtils.getHeader(HttpHeaders.AUTHORIZATION); + String currentToken = ""; + if (auth == null) { + throw new BusinessException("认证失败", UNAUTHORIZED); + } else { + String prefix = "data_exchange_feign_"; + currentToken = StringUtils.substringAfter(auth, prefix); + } + // 新增final副本用于lambda + final String finalToken = currentToken; + // 校验业务配置 + ServiceBusiness serviceBusiness = serviceBusinessService.selectServiceBusinessById(id); + if (serviceBusiness == null) { + return AjaxResult.error("未找到对应的业务配置"); + } + // 调用数据库查询 + AjaxResult ajaxResult = this.outQuery(id, serviceBusiness); + if (!ajaxResult.isSuccess()) { + return ajaxResult; + } + Object bodyData = ajaxResult.get("data"); + if (bodyData == null) { + return ajaxResult; + } + if (!(bodyData instanceof Map)) { + return AjaxResult.error("响应数据格式异常"); + } + Map dataMap = (Map) bodyData; + Object rows = dataMap.get("rows"); + if (!(rows instanceof List)) { + return AjaxResult.error("缺少有效的业务数据"); + } + List rowsList = (List) rows; + + // 获取remark信息 + String urlSuffix = ""; + JSONObject remarkJson = null; + if (serviceBusiness.getRemark() != null) { + try { + // 解析 JSON 字符串 + remarkJson = JSONObject.parseObject(serviceBusiness.getRemark()); + // 提取 url 字段 + urlSuffix = remarkJson.getString("url"); + } catch (Exception e) { + logger.error("解析 remark 字段失败", e); + return AjaxResult.error("解析 remark 字段失败"); + } + } + // 新增final副本用于lambda + final String finalUrlSuffix = urlSuffix; + // 分批处理逻辑 + int batchSize = 50; + List> batches = new ArrayList<>(); + for (int i = 0; i < rowsList.size(); i += batchSize) { + int end = Math.min(i + batchSize, rowsList.size()); + batches.add(rowsList.subList(i, end)); + } + String[] tableParts = serviceBusiness.getTableName().split("_"); + if (tableParts.length < 3) { + return AjaxResult.error("表名格式不符合规范: " + serviceBusiness.getTableName()); + } + String ipcType = tableParts[1].toUpperCase(); // 提取中间部分并转为大写 + // 替换为固定线程池(根据CPU核心数配置) + int coreCount = Runtime.getRuntime().availableProcessors(); + ExecutorService executor = Executors.newFixedThreadPool(coreCount * 2); + + List> futures = new ArrayList<>(); + + for (List batch : batches) { + futures.add(executor.submit(() -> { + try { + Map reqMap = new HashMap<>(); + reqMap.put("recordInfo", batch); + + TransportRequest request = buildRequest(ipcType, reqMap, finalToken); + logger.info("线程[{}] 请求报文:\n{}", Thread.currentThread().getId(), gson.toJson(request)); + + String responseJson = postRequest(request, finalUrlSuffix); + TransportResponse response = parseResponse(responseJson); + handleResponse(response, finalUrlSuffix); + } catch (Exception e) { + logger.error("线程处理异常", e); + } + })); + } + // 等待所有任务完成 + for (Future future : futures) { + future.get(); + } + executor.shutdown(); + return success(); + } + + // 发送HTTP请求 + private String postRequest(TransportRequest request, String urlSuffix) throws Exception { + String json = gson.toJson(request); + + RequestBody body = RequestBody.create(json, okhttp3.MediaType.get("application/json")); + Request httpRequest = new Request.Builder() + .url(API_ENDPOINT + urlSuffix) + .post(body) + .build(); + + try (Response response = httpClient.newCall(httpRequest).execute()) { + if (!response.isSuccessful()) { + throw new TransportException("HTTP错误: " + response.code()); + } + return response.body().string(); + } + } + + // 解析响应 + private TransportResponse parseResponse(String json) { + return gson.fromJson(json, TransportResponse.class); + } + + // 处理业务响应 + private void handleResponse(TransportResponse response, String urlSuffix) throws TransportException { + TransportHeader header = response.getHeader(); + if (!"0000".equals(header.getCode())) { + throw new TransportException("业务错误[" + header.getCode() + "]: " + + header.getMessage()); + } + // 更新Token + if (response.getBody() != null && response.getBody() != "") { + try { + logger.info("返回的Body: {}", response.getBody()); + logger.info("返回的Code: {}", header.getCode()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + public AjaxResult outQuery(Long id, ServiceBusiness serviceBusiness) throws SQLException, IOException { + + JSONObject jsonObject = null; + Map res = new HashMap<>(); + List> list; + if (BusinessServiceEnum.custom.getCode().equals(serviceBusiness.getType())) { + String queryField = serviceBusiness.getResultSql(); + StringBuilder sb = new StringBuilder(); + sb.append(queryField); + + String tableName = serviceBusiness.getTableName(); + String lowerCaseQueryField = queryField.toLowerCase(); + String lowerCaseTableName = tableName.toLowerCase(); + + String conditions = ""; + int tableNameIndex = lowerCaseQueryField.indexOf(lowerCaseTableName); + if (tableNameIndex != -1) { + // Extract the part after the table name + int startIndex = tableNameIndex + lowerCaseTableName.length(); + conditions = queryField.substring(startIndex).trim(); + } + + String sbCount = "select count(1) from " + tableName + " " + conditions; +// String sbCount = "select count(1) from" + serviceBusiness.getTableName()+" "+queryField.toLowerCase().split(serviceBusiness.getTableName())[1]; + //默认排序 +// if (!queryField.toLowerCase().contains("order by")) { +// sb.append(" order by id desc"); +// } + //分页 +// sb.append(" limit ?,?"); + log.debug("sb=" + sb); + // ps:目前写死从mybatis-plus多数据源master取,后续匹配对应数据源 +// Connection conn = databaseService.getConnection(serviceBusiness.getDatabaseId(), null); + Connection conn = dataSource.getConnection(); + PreparedStatement ps = conn.prepareStatement(sb.toString()); + PreparedStatement psCount = conn.prepareStatement(sbCount); + list = queryData(ps, 1, serviceBusiness, jsonObject); + res.put("rows", list); + int total = queryCount(psCount); + res.put("total", total); + ps.close(); + conn.close(); + } else if (BusinessServiceEnum.select.getCode().equals(serviceBusiness.getType())) { + String queryField = serviceBusiness.getQueryField(); + if (!StringUtils.isEmpty(queryField)) { + ObjectMapper objectMapper = new ObjectMapper(); + List queryFieldList = objectMapper.readValue(queryField, new TypeReference>() { + }); + Map queryFieldMap = new HashMap<>(); + for (OutQueryType queryType : queryFieldList) { + queryFieldMap.put(queryType.getField(), queryType); + } + } + StringBuilder sb = new StringBuilder(); + StringBuilder sbCount = new StringBuilder(); + sb.append("select "); + sbCount.append("select count(1) from "); + String resultField = serviceBusiness.getResultField(); + if (!StringUtils.isEmpty(resultField)) { + String[] split = resultField.split(","); + Set resFieldSet = new HashSet<>(Arrays.asList(split)); + for (String resField : resFieldSet) { + sb.append(resField); + sb.append(","); + } + sb.deleteCharAt(sb.length() - 1); + } else { + sb.append("*"); + } + sb.append(" from "); + sb.append(serviceBusiness.getTableName()); + sbCount.append(serviceBusiness.getTableName()); +// boolean hasWhere = false; +// for (Map.Entry entry : queryFieldMap.entrySet()) { +// if(jsonObject != null && StringUtils.isNotEmpty(jsonObject.getString(entry.getKey()))) { +// if(hasWhere) { +// sb.append(" and "); +// sbCount.append(" and "); +// } else { +// sb.append(" where "); +// sbCount.append(" where "); +// hasWhere = true; +// } +// sb.append(entry.getKey()); +// sbCount.append(entry.getKey()); +// if(FieldTypeEnum.eq.getCode().equals(entry.getValue().getType())) { +// sb.append(" = ?"); +// sbCount.append(" = ?"); +// } else if(FieldTypeEnum.like.getCode().equals(entry.getValue().getType())) { +// sb.append(" like ?"); +// sbCount.append(" like ?"); +// } else if(FieldTypeEnum.dataRange.getCode().equals(entry.getValue().getType())) { +// sb.append(" between ? and ?"); +// sbCount.append(" between ? and ?"); +// } +// } +// } +// sb.append(" order by id desc limit ?,?"); + log.debug("sb=" + sb); + // ps:目前写死从mybatis-plus多数据源master取,后续匹配对应数据源 +// Connection conn = databaseService.getConnection(serviceBusiness.getDatabaseId(), null); + Connection conn = dataSource.getConnection(); + PreparedStatement ps = conn.prepareStatement(sb.toString()); + PreparedStatement psCount = conn.prepareStatement(sbCount.toString()); + int index = 1; +// for (Map.Entry entry : queryFieldMap.entrySet()) { +// if(jsonObject != null && StringUtils.isNotEmpty(jsonObject.getString(entry.getKey()))) { +// if(FieldTypeEnum.eq.getCode().equals(entry.getValue().getType())) { +// ps.setObject(index, jsonObject.get(entry.getKey())); +// psCount.setObject(index, jsonObject.get(entry.getKey())); +// index++; +// } else if(FieldTypeEnum.like.getCode().equals(entry.getValue().getType())) { +// ps.setObject(index, "%" + jsonObject.get(entry.getKey()) + "%"); +// psCount.setObject(index, "%" + jsonObject.get(entry.getKey()) + "%"); +// index++; +// } else if(FieldTypeEnum.dataRange.getCode().equals(entry.getValue().getType())) { +// String[] dateRangeSplit = jsonObject.getString(entry.getKey()).split(","); +// ps.setObject(index, dateRangeSplit[0] + " 00:00:00"); +// psCount.setObject(index, dateRangeSplit[0] + " 00:00:00"); +// index++; +// ps.setObject(index, dateRangeSplit[1] + " 23:59:59"); +// psCount.setObject(index, dateRangeSplit[1] + " 23:59:59"); +// index++; +// } +// } +// } + list = queryData(ps, index, serviceBusiness, jsonObject); + res.put("rows", list); + int total = queryCount(psCount); + res.put("total", total); + ps.close(); + conn.close(); + } + return success(res); + } + + /** + * 调用查询,返回数据 + * + * @param ps PreparedStatement + * @param index ps顺序 + * @param serviceBusiness 业务服务 + * @return List + */ + private List> queryData(PreparedStatement ps, int index, ServiceBusiness serviceBusiness, JSONObject jsonObject) throws SQLException { + List> list = new ArrayList<>(); + DateTimeFormatter dfClock = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); +// +// convertSqlToPage(ps, index, jsonObject); +// System.out.println("ps=" + transSql(ps)); + // 处理JSONArray和JSONObject + JSONObject remarkJson = null; +// List jsonArrayColumnList = new ArrayList<>(); + List jsonObjectColumnList = new ArrayList<>(); + Map jsonArrayColumnMap = new HashMap<>(); + if (serviceBusiness.getRemark() != null) { + try { + // 解析 JSON 字符串 + remarkJson = JSONObject.parseObject(serviceBusiness.getRemark()); + // 提取 url 字段 + // 提取 JSONArray 字段 + String jsonArrayColumnStr = remarkJson.getString("JSONArray"); + if (jsonArrayColumnStr != null && !jsonArrayColumnStr.isEmpty()) { + String[] items = jsonArrayColumnStr.split(","); + for (String item : items) { + if (item.contains(":")) { + String[] parts = item.split(":"); + if (parts.length == 2) { + jsonArrayColumnMap.put(parts[0], parts[1]); + } + } else { + // 没有冒号时,使用默认字段名 value + jsonArrayColumnMap.put(item, "value"); + } + } + } + // 提取 JSONObject 字段 + String jsonObjectColumnStr = remarkJson.getString("JSONObject"); + if (jsonObjectColumnStr != null && !jsonObjectColumnStr.isEmpty()) { + jsonObjectColumnList = Arrays.asList(jsonObjectColumnStr.split(",")); + } + } catch (Exception e) { + logger.error("解析 remark 字段失败", e); + } + } + + ResultSet rs = ps.executeQuery(); + Adapter queryAdapter = new Adapter(); + queryAdapter.setServiceBusinessId(serviceBusiness.getId()); + queryAdapter.setStatus(DELETE_NO); + List adapters = adapterService.selectAdapterList(queryAdapter); + while (rs.next()) { + int columnCount = rs.getMetaData().getColumnCount(); + Map rowData = new HashMap<>(); + for (int i = 1; i <= columnCount; i++) { + String columnName = rs.getMetaData().getColumnLabel(i); + if (columnName != null && !columnName.isEmpty()) { + String camelCaseName = com.ruoyi.common.core.utils.StringUtils.toCamelCase(columnName); + Object value = rs.getObject(i); + if (value instanceof LocalDateTime) { + LocalDateTime timeTmp = (LocalDateTime) value; + value = timeTmp.format(dfClock); + } + value = dealAdapter(adapters, camelCaseName, value); // 使用转换后的字段名 + + // 处理 JSONArray 和 JSONObject 列 + // 处理 JSONArray 列 + if (jsonArrayColumnMap.containsKey(camelCaseName) && value instanceof String) { + if (!StringUtils.isEmpty((String) value)) { + String fieldName = jsonArrayColumnMap.get(camelCaseName); + JSONArray originalArray = JSONArray.parseArray((String.valueOf(value))); + JSONArray newArray = new JSONArray(); + for (int j = 0; j < originalArray.size(); j++) { + if ("value".equals(fieldName)) { + // 若 fieldName 为 value,直接添加元素 + newArray.add(originalArray.get(j)); + } else { + String item = originalArray.getString(j); + JSONObject obj = new JSONObject(); + obj.put(fieldName, item); + newArray.add(obj); + } + } + value = newArray; + } + } + // 处理 JSONObject 列 + else if (jsonObjectColumnList.contains(camelCaseName) && value instanceof String) { + if (!StringUtils.isEmpty((String) value)) { + value = JSONObject.parseObject((String.valueOf(value))); + } + } + + rowData.put(camelCaseName, value); + } + } + list.add(rowData); + } + return list; + } + + /** + * 处理适配器 + * + * @param adapters 适配器 + * @param columnName 字段名 + * @param o 字段值 + * @return 结果 + */ + private Object dealAdapter(List adapters, String columnName, Object o) { + if (!adapters.isEmpty()) { + for (Adapter a : adapters) { + if (columnName.equals(a.getServiceBusinessField())) { + if (a.getType().equals("1")) { + //系统字典 + o = sysDictDataService.selectDictLabel(a.getContent(), (String) o); + } + } + } + } + return o; + } + + /** + * 调用查询,返回数据 + * + * @param ps PreparedStatement + * @return List + */ + private int queryCount(PreparedStatement ps) throws SQLException { +// System.out.println("ps=" + transSql(ps)); + int total = 0; + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + total = rs.getInt(1); + } + return total; + } + + + // 构建请求报文结构 + private TransportRequest buildRequest(String ipcType, Object bodyData, String currentToken) throws Exception { + + // 类型检查和转换 + if (!(bodyData instanceof Map)) { + throw new IllegalArgumentException("请求体数据必须是Map类型"); + } + + // 包装为符合接口要求的格式 + TransportRequestInfo requestInfo = new TransportRequestInfo(bodyData); + + String plainBody = gson.toJson(requestInfo); + + logger.info("完整请求体(未加密):\n{}", plainBody); + return new TransportRequest( + new TransportHeader( + generateSerialNumber(), + PROVINCE_AREA_CODE, // 省级标识 + PROVINCE_AREA_CODE, // 部级标识+省级标识 + BASE_AREA_CODE, // 部级标识 + "V1", + ipcType, + LocalDateTime.now().format(DATE_FORMATTER), + calculateSM3(plainBody), + "0", + currentToken, + null, + null + ), + encryptBody(plainBody) + ); + } + + // 生成流水号(符合文档规范) + private String generateSerialNumber() { + + // 2. 当前日期(必须8位) + String datePart = LocalDateTime.now() + .format(DateTimeFormatter.BASIC_ISO_DATE); + + // 3. 12位序列号(使用原子计数器示例) + AtomicLong counter = new AtomicLong(1); // 实际应从数据库获取 + String sequence = String.format("%012d", counter.getAndIncrement() % 1000000000000L); + + return PROVINCE_AREA_CODE + datePart + sequence; + } + + // SM3哈希计算 + private String calculateSM3(String data) { + EncryptCrcBean encryptCrcBean = new EncryptCrcBean(); + encryptCrcBean.setPass(data); + String cipherText_crc = smCryptoService.encryptCrc(encryptCrcBean); + return cipherText_crc; + } + + // SM4加密(ECB模式) + private String encryptBody(String plainText) throws Exception { + EncryptCodeBean encryptCodeBean = new EncryptCodeBean(); + encryptCodeBean.setSecretKey(encrypt_key); + encryptCodeBean.setPass(plainText); + String cipherText = smCryptoService.encrypt_Body(encryptCodeBean); + return cipherText; + } + + // SM4解密(ECB模式) + private String decryptBody(String plainText) throws Exception { + DecryptCodeBean encrypt2 = new DecryptCodeBean(); + encrypt2.setSecretKey(decrypt_key); + encrypt2.setPass(plainText); + String cipherText = smCryptoService.decrypt_Body(encrypt2); + return cipherText; + } +}