package com.mes.connect.IndustrialInterface;
|
|
import com.alibaba.fastjson.JSON;
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.mes.connect.entity.ApiConfig;
|
import com.mes.connect.entity.LogicItem;
|
import com.mes.connect.entity.PlcParameters;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.http.*;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.SqlOutParameter;
|
import org.springframework.jdbc.core.SqlParameter;
|
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
|
import org.springframework.stereotype.Service;
|
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.util.UriComponentsBuilder;
|
|
import java.sql.Types;
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.stream.Collectors;
|
|
@Slf4j
|
@Service
|
public class Api implements ApiService {
|
|
|
|
private final RestTemplate restTemplate;
|
|
private final JdbcTemplate jdbcTemplate;
|
@Autowired
|
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
|
// 使用构造函数注入
|
@Autowired
|
public Api(RestTemplate restTemplate, JdbcTemplate jdbcTemplate) {
|
this.restTemplate = restTemplate;
|
this.jdbcTemplate = jdbcTemplate;
|
}
|
|
/**
|
* 发送调用接口请求 ,根据逻辑配置调用
|
*
|
* @param apiConfig 逻辑配置参数
|
* @param plcParameters plc参数
|
* @return 响应内容按行分割的数组
|
*/
|
public List<String> callApi(ApiConfig apiConfig, PlcParameters plcParameters){
|
try{
|
List<String> result=new ArrayList<>();
|
String connectType=apiConfig.getType();
|
String connectAddress=apiConfig.getAddress();
|
Map<String,Object> map=new HashMap<String,Object>();
|
map.put("apiConfig",apiConfig);
|
map.put("plcParameter",plcParameters);
|
switch (connectType) {
|
case "Http":
|
result= this.httpApi(connectAddress,map);
|
break;
|
case "View": // 视图/表
|
result= this.viewApi(connectAddress,map);
|
break;
|
case "Procedure": // 存储过程
|
result= this.procedureAPI(connectAddress,map);
|
break;
|
default:
|
log.warn("不支持的连接类型: {}", connectType);
|
return null; // 不支持的方式
|
}
|
return result;
|
}catch (Exception e){
|
log.error("调用接口失败: {}", e.getMessage(), e);
|
}
|
return null;
|
}
|
|
|
|
|
|
/**
|
* 发送HTTP请求,支持GET和POST方法
|
*
|
* @param url 请求URL
|
* @param data 请求参数或请求体
|
* @return 响应内容按行分割的数组
|
*/
|
@DS("mes_machine")
|
@Override
|
public List<String> httpApi(String url,Map<String, Object> data) {
|
try {
|
// 构建URL
|
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
|
// 处理响应
|
String responseBody;
|
ObjectMapper mapper = new ObjectMapper();
|
Map<String, Object> apiConfig= mapper.convertValue(data.get("apiConfig"), Map.class);
|
Map<String, Object> parameters= mapper.convertValue(apiConfig.get("parameters"), Map.class);
|
String method=parameters.get("method").toString();
|
data.remove("parameters");
|
if ("GET".equals(method)) {
|
// GET请求:将参数添加到URL查询参数中
|
if (data != null) {
|
data.forEach(builder::queryParam);
|
}
|
// 发送GET请求
|
ResponseEntity<String> response = restTemplate.exchange(
|
builder.toUriString(),
|
HttpMethod.GET,
|
null,
|
String.class
|
);
|
responseBody = response.getBody();
|
} else if ("POST".equals(method)) {
|
// POST请求:将参数作为请求体
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
HttpEntity<?> entity = new HttpEntity<>(data, headers);
|
// 发送POST请求
|
ResponseEntity<String> response = restTemplate.exchange(
|
builder.toUriString(),
|
HttpMethod.POST,
|
entity,
|
String.class
|
);
|
responseBody = response.getBody();
|
} else {
|
throw new IllegalArgumentException("不支持的HTTP方法: " + method);
|
}
|
// 直接提取data数组
|
List<String> dataList = JSON.parseObject(responseBody)
|
.getJSONArray("data")
|
.toJavaList(String.class);
|
return dataList;
|
//return responseBody != null ? responseBody.split("\n") : new String[0];
|
} catch (Exception e) {
|
// 异常处理
|
e.printStackTrace();
|
return null;
|
}
|
}
|
@DS("mes_machine")
|
@Override
|
public List<String> viewApi(String viewName, Map<String, Object> parameters) {
|
// 验证视图名是否合法,防止SQL注入
|
if (!isValidViewName(viewName)) {
|
throw new IllegalArgumentException("无效的视图名称");
|
}
|
ObjectMapper mapper = new ObjectMapper();
|
Map<String, Object> apiConfig= mapper.convertValue(parameters.get("apiConfig"), Map.class);
|
Map<String, Object> params= mapper.convertValue(apiConfig.get("parameters"), Map.class);
|
// 使用预编译语句构建查询
|
StringBuilder sql = new StringBuilder("SELECT * FROM " + viewName);
|
MapSqlParameterSource paramSource = new MapSqlParameterSource();
|
|
if (params != null && !params.isEmpty()) {
|
sql.append(" WHERE ");
|
boolean first = true;
|
|
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
if (!first) {
|
sql.append(" AND ");
|
}
|
sql.append(entry.getKey()).append(" = :").append(entry.getKey());
|
paramSource.addValue(entry.getKey(), entry.getValue());
|
first = false;
|
}
|
}
|
// 使用Map参数执行查询并转换结果
|
List<Map<String, Object>> resultList = namedParameterJdbcTemplate.queryForList(
|
sql.toString(),
|
paramSource.getValues()
|
);
|
|
return convertResultToList(resultList);
|
}
|
@DS("jiumumes")
|
@Override
|
public List<String> procedureAPI(String procedureName, Map<String, Object> params) {
|
try {
|
if (!isValidProcedureName(procedureName)) {
|
throw new IllegalArgumentException("无效的存储过程名称");
|
}
|
ObjectMapper mapper = new ObjectMapper();
|
Map<String, Object> apiConfig= mapper.convertValue(params.get("apiConfig"), Map.class);
|
Map<String, Object> parameters=mapper.convertValue(apiConfig.get("parameters"), Map.class);
|
Map<String, Object> inParams= mapper.convertValue(parameters.get("inParams"), Map.class);
|
Map<String, Object> outParams= mapper.convertValue(parameters.get("outParams"), Map.class);
|
// 创建新的 Map 并合并
|
Map<String, Object> mergedMap = new HashMap<>(inParams);
|
mergedMap.putAll(outParams);
|
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
|
.withProcedureName(procedureName)
|
.withoutProcedureColumnMetaDataAccess();
|
for (Map.Entry<String, Object> entry : inParams.entrySet()) {
|
int sqlType = getSqlType(entry.getValue());
|
// 作为输入参数
|
jdbcCall.declareParameters(
|
new SqlParameter(entry.getKey(), sqlType)
|
);
|
}
|
for (Map.Entry<String, Object> entry : outParams.entrySet()) {
|
int outSqlType=12;
|
// int sqlType = getSqlType(entry.getValue());
|
// Object outParamInfo = outParams.get(entry.getKey());
|
// // 从输出参数信息中获取SQL类型
|
// if (outParamInfo instanceof Integer) {
|
// outSqlType = (Integer) outParamInfo;
|
// } else if (outParamInfo instanceof Map) {
|
// // 假设Map中包含"sqlType"键
|
// Map<String, Object> outParamMap = (Map<String, Object>) outParamInfo;
|
// outSqlType = (Integer) outParamMap.getOrDefault("sqlType", sqlType);
|
// } else {
|
// // 默认使用输入参数的SQL类型
|
// outSqlType = sqlType;
|
// }
|
|
// 使用指定的SQL类型作为输出参数
|
jdbcCall.declareParameters(
|
new SqlOutParameter(entry.getKey(), outSqlType)
|
);
|
}
|
// 执行存储过程并获取结果
|
Map<String, Object> result = jdbcCall.execute(mergedMap);
|
|
// 处理输出参数
|
if (outParams != null) {
|
for (String paramName : outParams.keySet()) {
|
if (result.containsKey(paramName)) {
|
// 将输出参数的值放回原参数Map中
|
outParams.put(paramName, result.get(paramName));
|
}
|
}
|
}
|
List<String> outParamsValues = outParams.values().stream()
|
.map(value -> value != null ? value.toString() : "null")
|
.collect(Collectors.toList());
|
// 返回结果信息
|
return outParamsValues;
|
} catch (Exception e) {
|
return null;
|
}
|
}
|
|
// 将查询结果转换为字符串数组
|
private List<String> convertResultToList(List<Map<String, Object>> resultList) {
|
List<String> resultStrings = new ArrayList<>();
|
for (Map<String, Object> row : resultList) {
|
for (String key : row.keySet()) {
|
resultStrings.add(row.get(key).toString());
|
}
|
return resultStrings;
|
}
|
//return resultStrings.toArray(new String[0]);
|
return resultStrings;
|
}
|
|
// 类型映射方法
|
private int getSqlType(Object value) {
|
if (value instanceof String) return Types.VARCHAR;
|
if (value instanceof Integer) return Types.INTEGER;
|
if (value instanceof Double) return Types.DOUBLE;
|
if (value instanceof java.util.Date) return Types.TIMESTAMP;
|
if (value instanceof Boolean) return Types.BOOLEAN;
|
return Types.VARCHAR;
|
}
|
|
// 验证视图名称(防止SQL注入)
|
private boolean isValidViewName(String viewName) {
|
// 简单验证:只允许字母、数字和下划线,且长度不超过50
|
return viewName.matches("^[a-zA-Z0-9_]{1,50}$");
|
}
|
|
// 验证存储过程名称
|
private boolean isValidProcedureName(String procedureName) {
|
return procedureName.matches("^[a-zA-Z0-9_]{1,50}$");
|
}
|
|
}
|