一:HTTP接口调用:
1,线程池准备
场景:erp接口返回数据量为几万条,为提高性能,使用线程池
@Transactional //为代码加锁,保证数据完整性 由于数据量可能比较大,所有设置超时时间为300秒,放后台慢慢跑,不影响别的代码执行
executorService.submit(new DataOperationMaterialThread(batch,iMaterialService)); 每个线程需要执行的代码
@Override
//为代码加锁,保证数据完整性 由于数据量可能比较大,所有设置超时时间为300秒,放后台慢慢跑,不影响别的代码执行
@Transactional(rollbackFor = Exception.class,timeout = 300)
public Boolean getMaterial() {
List<ErpMaterialVO> mList = null;
try {
//erp接口调用,返回参数为mList
mList = erpMagerial();
} catch (IOException e) {
logger.info("ERP物料接口调用失败:{}", e.getMessage());
}
int threadCount = 10; // 线程数量
int batchSize = 900; // 每批数据数量
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
List<List<ErpMaterialVO>> dataBatches = new ArrayList<>();
//根据线程数拆分接口返回数据
for (int i = 0; i < mList.size(); i += batchSize) {
int endIndex = Math.min(i + batchSize, mList.size());
List<ErpMaterialVO> batch = mList.subList(i, endIndex);
dataBatches.add(batch);
}
for (List<ErpMaterialVO> batch : dataBatches) {
//new DataOperationMaterialThread为每个线程需要执行的代码
executorService.submit(new DataOperationMaterialThread(batch,iMaterialService));
}
executorService.shutdown();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
return true;
}
}
2,erpMagerial() 调用erp接口
http接口请求方式一
将返回值转为实体类
//实体类中可以包括list属性
Gson gson = new Gson();
Type listType = new TypeToken<List<ErpMaterialVO>>() {}.getType();
material = gson.fromJson(response,listType);
请求方法:
HttpGet httpGet = new HttpGet(url);
HttpPost httpPost = new HttpPost(url);
HttpPut httpPut = new HttpPut(url);
HttpDelete httpDelete = new HttpDelete(url);
//调用erp接口获取物料信息
public static List<ErpMaterialVO> erpMagerial() throws IOException {
String url ="接口地址;
logger.info("ERP物料接口----接口地址"+url);
List<ErpMaterialVO> material = new ArrayList<>();
try {
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
// 执行请求
HttpResponse httpResponse = httpClient.execute(httpGet);
// 获取响应码
int responseCode = httpResponse.getStatusLine().getStatusCode();
System.out.println("Response Code: " + responseCode);
// 读取响应内容
String response = EntityUtils.toString(httpResponse.getEntity());
Gson gson = new Gson();
Type listType = new TypeToken<List<ErpMaterialVO>>() {}.getType();
material = gson.fromJson(response,listType);
logger.info("ERP物料接口----接口地址"+url+"接口返回共"+material.size()+"条数据");
} catch (Exception e) {
logger.info("ERP物料接口----接口地址"+url+"接口调用失败"+e.getMessage());
e.printStackTrace();
}finally {
return material;
}
}
run方法 DataOperationMaterialThread
public class DataOperationMaterialThread implements Runnable{
private IMaterialService iMaterialService;
private List<ErpMaterialVO> dataList;
private static int count = 0;
public DataOperationMaterialThread(List<ErpMaterialVO> dataList, IMaterialService iMaterialService) {
this.dataList = dataList;
this.iMaterialService = iMaterialService;
}
@Override
@Transactional(rollbackFor = Exception.class,timeout = 120)
public void run() {
//根据实际需求写字机的run方法;每个线程需要执行的操作
}
http接口方法二
实体类总包含一个对象数组 如:
@Data
@ApiModel(value = "已排产(生产任务)", description = "已排产(生产任务)")
public class DailyPickingListVO {
@ApiModelProperty(value = "日期")
private String date;
@ApiModelProperty(value = "投料单编号")
private String ppbomBillNo;
@ApiModelProperty(value = "日期")
private List<DailyPickingListTwoVO> entries;
}
@Data
@ApiModel(value = "已排产(生产任务)", description = "已排产(生产任务)")
public class DailyPickingListTwoVO {
@ApiModelProperty(value = "序号 原投料单对应的序号")
private Integer index;
@ApiModelProperty(value = "物料代码")
private String itemNumber;
@ApiModelProperty(value = "计量单位代码")
private String unitNumber;
@ApiModelProperty(value = "应发数量")
private Double qtyMust;
@ApiModelProperty(value = "投料单行号")
private Integer ppbomIndex;
}
将实体类转为json字符串
//调用每日投料单创建接口
dailyPickingListVO.setEntries(dailyPickingListTwoVOS);
//实体转为JSON字符串 实体类中包括list
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = objectMapper.writeValueAsString(dailyPickingListVO);
System.out.println("JSON字符串: 投料单号"+pickNo+"明细数据" + jsonString);
Integer code = erpProPickService.DailyPickingList(jsonString);
调用接口时携带json参数
//ERP接口创建每日投料单
@Override
public Integer DailyPickingList(String json) throws Exception {
int responseCode = 0;
try {
String targetURL ="接口地址";
logger.info("ERP标签接口----接口地址"+targetURL+"接口参数 --- :"+"明细数据"+json);
URL url = new URL(targetURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置连接超时时间,根据实际情况调整
connection.setConnectTimeout(5000);
// 设置读取超时时间,根据实际情况调整
connection.setReadTimeout(5000);
// 设置请求方法为POST
connection.setRequestMethod("POST");
// 启用输出流(默认是不启用)
connection.setDoOutput(true);
// 设置请求头,指定数据格式为JSON
connection.setRequestProperty("Content-Type", "application/json");
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8);
writer.write(json);
writer.flush();
writer.close();
// 获取响应码
responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
} else {
// 读取错误响应
BufferedReader errorReader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
String inputLine;
StringBuilder errorResponse = new StringBuilder();
while ((inputLine = errorReader.readLine()) != null) {
errorResponse.append(inputLine);
}
errorReader.close();
// 打印结果
logger.info("ERP标签接口返回值 Error Response code :"+responseCode+"------"+errorResponse.toString());
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
return responseCode;
}
}
二:HTTP接口调用参数返回值为xml格式字符串
方法一:无需处理返回结果
1,组合请求参数:主参数
根据需求拼接xml中的data.file请求参数
@Override
//生产报工保存批次 工序报工
public String openumZjOrderSaveErp(ProReportDTO search, ProWorkOrderEntity workOrder) {
//参数
String file = "";
//工单号
String mfgnum = workOrder.getMfgnum();
//工序
Integer openum = workOrder.getOpenum();
ErpMfgitmEntity mfgitm = new ErpMfgitmEntity();
List<ErpMfgitmEntity> mfgitms = erpMfgitmMapper.selectBYMfgnum(mfgnum);
if(mfgitms.size() > 0){
mfgitm = mfgitms.get(0);
}
//生产地点
String mfgfcy = mfgitm.getMfgfcy();
//工艺路线
String itmref = mfgitm.getItmref();
//工艺路线代码
Integer routingVersion = workOrder.getRoutingVersion();
//单位
// ErpInventoryEntity erpInventory = new ErpInventoryEntity();
// erpInventory.setMaterialNo(itmref);
// ErpInventoryEntity material = erpInventoryMapper.getMaterialId(erpInventory);
// String unit = material.getUnit();
String unit = erpInventoryMapper.getRouopeByItmref(workOrder);
//时间
Date date = new Date();
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMdd");
String format = dateFormat.format(date);
//完成数量 proMeter
BigDecimal numSum = search.getZjReport().getProMeter();
//调整时间
ProPlanEntity byId = proPlanService.getById(workOrder.getPlanId());
Integer changeDate = byId.getChangeDate();
//操作时间 minutesDifference 下达时间 取工时字段
long minutesDifference = search.getZjReport().getWorkHour();
//工单号,工序,生产地点,工艺路线,工艺路线代码选择,单位,工序单位转换,总的完成数量(实际数量),不合格完成数量(实际退回数量),已完成工作中心,
// 实际调整时间,实际操作时间,员工编号(0),拒绝(0),消息(0),过账日期 ;;;;工艺路线,工艺路线代码选择,0;0
//M;C01240602834;5;C0101;PS000277;40;KG;1;1;0;CM01;0.0417;1;0;0;0;20240611;;;;PS000277;40;0;0;
//LC;DPT;BU;PRJ;;;
file += "M;"+mfgnum+";"+openum+";"+mfgfcy+";"+itmref+";"+routingVersion+";"+unit+";1;"+numSum+";0;"+workOrder.getExtwst();
file += ";"+changeDate+";"+minutesDifference+";0;0;0;"+format+";;;;"+itmref+";"+routingVersion+";"+"0;0;|";
file += "LC;DPT;BU;PRJ;;;|END";
//调用x3工序追踪接口
logger.info("工序追踪接口参数》》》》》》》》》》》》》》》"+file);
return openumX3(file);
}
2,接口请求方法
endpoint接口地址
//工序追踪x3接口
public String openumX3(String file){
String mtk = "";
try {
JSONObject data = new JSONObject();
//工序追踪模版 ZMKO1
data.set("I_MODIMP", "ZMKO1");
data.set("I_AOWSTA", "NO");
data.set("I_EXEC", "REALTIME");
data.set("I_RECORDSEP", "|");
// data.set("I_FILE", "M;C01240401952;C0101;1000;5;015;1;20240416;;;;|L;LC010124020069;;200101;-0.004|L;LC010124030817;;200101;-0.996|ad|M;C01240401952;C0101;1000;60;208;1;20240416;;;;|L;LC010124030363;;200101;-1|ad|END");
data.set("I_FILE",file);
// 创建SOAP请求的XML数据 "<poolAlias xsi:type=\"xsd:string\">TEST1</poolAlias>\n" TEST1 X3测试环境 SOLIV 正式环境
String soapRequest = "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
"\txmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n" +
"\txmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" \n" +
"\txmlns:wss=\"http://www.adonix.com/WSS\">\n"
+ "<soapenv:Header/>\n"
+ "<soapenv:Body>\n"
+ "<wss:run soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
+ "<callContext xsi:type=\"wss:CAdxCallContext\">\n"
+ "<codeLang xsi:type=\"xsd:string\">ENG</codeLang>\n"
+ "<poolAlias xsi:type=\"xsd:string\">"+poolAlias+"</poolAlias>\n"
+ "<poolId xsi:type=\"xsd:string\"></poolId>\n"
+ "<requestConfig xsi:type=\"xsd:string\">\n"
+ "<![CDATA[adxwss.optreturn=JSON&adxwss.beautify=true&adxwss.trace.on=off]]>\n"
+ "</requestConfig>\n"
+ "</callContext>\n"
+ "<publicName xsi:type=\"xsd:string\">ZOWSIMPORT</publicName>\n"
+ "<inputXml xsi:type=\"xsd:string\">\n"
+ "<![CDATA[{\n"
+ "\"GRP1\":\n"
+ data.toString()
+ "}]]>\n"
+ " </inputXml>\n"
+ "</wss:run>\n"
+ "</soapenv:Body>\n"
+ "</soapenv:Envelope>\n";
// 发送SOAP请求,并接收返回的响应
HttpURLConnection connection = (HttpURLConnection) new URL(endpoint).openConnection();
String AccountPassword = "账号:密码";
//加密账号密码使用base64编码
String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(AccountPassword.getBytes());
connection.setRequestProperty("Authorization", basicAuth);
connection.setRequestMethod("POST");
//请求参数为xml
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "*/*");
connection.setRequestProperty("soapAction", "saveRequest");
// 设置连接超时时间,根据实际情况调整
connection.setConnectTimeout(15000);
// 设置读取超时时间,根据实际情况调整
connection.setReadTimeout(5000);
connection.setDoOutput(true);
OutputStreamWriter osw = new OutputStreamWriter(connection.getOutputStream());
osw.write(soapRequest);
osw.flush();
//1.创建Reader对象
SAXReader reader = new SAXReader();
//2.加载xml
Document document = reader.read(new InputStreamReader(connection.getInputStream()));
String ec = document.asXML();
logger.info("工序接口请求参数:"+ soapRequest);
logger.info("工序追踪接口返回值》》》》》》》》" +ec);
//3.获取根节点
Element rootElement = document.getRootElement();
//有多少层循环取决于返回值参数是中有多少层,可以使用post调用完接口那这道一层一层解析,
//直到拿到你需要的数据
Iterator iterator = rootElement.elementIterator();
while (iterator.hasNext()){
Element stu = (Element) iterator.next();
List<Attribute> attributes = stu.attributes();
System.out.println("======获取属性值======");
for (Attribute attribute : attributes) {
System.out.println(attribute.getValue());
}
System.out.println("======遍历子节点======");
Iterator iterator1 = stu.elementIterator();
while (iterator1.hasNext()){
Element stuChild = (Element) iterator1.next();
Iterator iterator2 = stuChild.elementIterator();
while (iterator2.hasNext()){
Element next = (Element) iterator2.next();
Iterator iterator3 = next.elementIterator();
if (next.getStringValue().indexOf("Creation of WO tracking") != -1){
int creationOfWoTracking = next.getStringValue().indexOf("Creation of WO tracking");
creationOfWoTracking = creationOfWoTracking+24;
mtk = next.getStringValue().substring(creationOfWoTracking);
System.out.println(">>>>>>"+"所在位置"+creationOfWoTracking+next.getName()+":"+next.getStringValue()+">>"+mtk);
}
while (iterator3.hasNext()){
Element next1 = (Element) iterator3.next();
if (next1.getName().equals("status")){
System.out.println(""+next1.getName()+":"+next1.getStringValue()+"");
}
//最后的子节点
Iterator iterator4 = next1.elementIterator();
while (iterator4.hasNext()){
Element next2 = (Element) iterator4.next();
System.out.println(""+next2.getName()+":"+next2.getStringValue()+"");
}
}
}
}
}
document.clone();
} catch (Exception e) {
e.printStackTrace();
}finally {
return mtk;
}
}
方法二:需要处理返回结果
代码解释:
//因为是BigDecimal格式 所以使用以下方法
// .add 意思为相加
//.add() 中的意思为,如果下标为6的数据是空字符串,赋值为0.0,否则就将下标为6的数据装维BigDecimal格式,在于元数据相加
//举例,看一看为,int a = 0; a = a+b;
BigDecimal actualQty = new BigDecimal("0.0");
actualQty = actualQty.add(parts[6].equals("") ? new BigDecimal("0.0") : new BigDecimal(parts[6]));
// 使用split方法根据"|"分隔字符串
String[] partsa = ret.split("\\|");
//字符串根据,分隔为stating数组
String[] parts = part.split(",");
1,请求参数:mfgnum 工单号 op工序号 itmref 产品代码
endpoint接口地址
@Override
public ErpToupOpItmrefVO toupChuErpByMfgnumOpItmref(String mfgnum, String op, String itmref) {
logger.info("校验是否投料接口》》》》》》》》》》》》》》》工单号"+mfgnum+"工序"+op+"产品代码"+itmref);
String ret = "";
Boolean isWeting = false;
try {
// JSONObject data = new JSONObject();
// data.set("I_TCRITERE", "MFGNUM="+mfgnum+"&OPENUM="+op);
String soapRequest = "<soapenv:Envelope\n" +
" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
" xmlns:wss=\"http://www.adonix.com/WSS\"\n" +
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <wss:run soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
" <callContext xsi:type=\"wss:CAdxCallContext\">\n" +
" <codeLang xsi:type=\"xsd:string\">ENG</codeLang>\n" +
" <poolAlias xsi:type=\"xsd:string\">"+poolAlias+"</poolAlias>\n" +
" <poolId xsi:type=\"xsd:string\"/>\n" +
" <requestConfig xsi:type=\"xsd:string\">\n" +
" <![CDATA[adxwss.optreturn=JSON&adxwss.beautify=true&adxwss.trace.on=off]]>\n" +
" </requestConfig>\n" +
" </callContext>\n" +
" <publicName xsi:type=\"xsd:string\">AOWSEXPORT</publicName>\n" +
" <inputXml xsi:type=\"xsd:string\">\n" +
" <![CDATA[{\n" +
" \"GRP1\": {\n" +
" \"I_MODEXP\": \"MF1\",\n" +
" \"I_CHRONO\": \"NO\"\n" +
" },\n" +
" \"GRP2\": [{\"I_TCRITERE\": \"[F:MFM]MFGNUM='"+mfgnum+"'&[F:MFM]BOMOPE="+op+"\"}],\n" +
" \"GRP3\": {\n" +
" \"I_EXEC\": \"REALTIME\",\n" +
" \"I_RECORDSEP\": \"|\"}\n" +
" }]]>\n" +
" </inputXml>\n" +
" </wss:run>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
logger.info("校验是否投料接口请求参数》》》》》》》》" + soapRequest);
//
HttpURLConnection connection = (HttpURLConnection) new URL(endpoint).openConnection();
String AccountPassword = "账号:密码";
//账号密码使用base64加密
String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(AccountPassword.getBytes());
connection.setRequestProperty("Authorization", basicAuth);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "*/*");
connection.setRequestProperty("soapAction", "saveRequest");
// 设置连接超时时间,根据实际情况调整
connection.setConnectTimeout(15000);
// 设置读取超时时间,根据实际情况调整
connection.setReadTimeout(5000);
connection.setDoOutput(true);
OutputStreamWriter osw = new OutputStreamWriter(connection.getOutputStream());
osw.write(soapRequest);
osw.flush();
int responseCode = connection.getResponseCode();
if (responseCode != 200){
isWeting = false;
}
//1.创建Reader对象
SAXReader reader = new SAXReader();
//2.加载xml
Document document = reader.read(new InputStreamReader(connection.getInputStream()));
String ec = document.asXML();
logger.info("校验是否投料接口返回结果》》》》》》》》" + ec);
// File file = new File("E:\\fanhui.xml");
// Document document = reader.read(file);
//3.获取根节点
Element rootElement = document.getRootElement();
Iterator iterator = rootElement.elementIterator();
while (iterator.hasNext()) {
Element stu = (Element) iterator.next();
System.out.println("======遍历子节点======");
Iterator iterator1 = stu.elementIterator();
while (iterator1.hasNext()) {
Element stuChild = (Element) iterator1.next();
Iterator iterator2 = stuChild.elementIterator();
while (iterator2.hasNext()) {
Element next = (Element) iterator2.next();
Iterator iterator3 = next.elementIterator();
while (iterator3.hasNext()) {
Element next1 = (Element) iterator3.next();
if (next1.getName().equals("resultXml")) {
JSONObject jsonObject = new JSONObject(next1.getStringValue());
Object grp3 = jsonObject.get("GRP3");
JSONObject grp3Object = new JSONObject(grp3);
ret = grp3Object.get("O_FILE").toString();
isWeting = true;
logger.info("校验是否投料接口----接口地址" + endpoint + "接口返回O_FILE" + grp3Object.get("O_FILE").toString());
}
}
}
}
}
} catch (Exception e) {
isWeting = false;
e.printStackTrace();
}finally {
//标准投入量合计
BigDecimal standardQty = new BigDecimal("0.0");
//实际投入量合计
BigDecimal actualQty = new BigDecimal("0.0");
//空字符串代表不需要投料,第五位为投料状态,第六位为标准投料量,第七位为实际投料量
if (!isWeting){
ErpToupOpItmrefVO erpToupOpItmref = new ErpToupOpItmrefVO();
erpToupOpItmref.setIsToup(isWeting);
erpToupOpItmref.setStandardQty(standardQty);
erpToupOpItmref.setActualQty(actualQty);
return erpToupOpItmref;
}
Boolean rasult = true;
if(! ret.equals("")){
// 使用split方法根据"|"分隔字符串
String[] partsa = ret.split("\\|");
// 打印分隔后的数组元素
for (String part : partsa) {
Integer retInt = 0;
if(!part.equals("")){
String[] parts = part.split(",");
retInt = parts[4].equals("") ? 0 :Integer.valueOf(parts[4]);
BigDecimal a = new BigDecimal(parts[5]);
standardQty = standardQty.add(parts[5].equals("") ? new BigDecimal("0.0") : new BigDecimal(parts[5]));
actualQty = actualQty.add(parts[6].equals("") ? new BigDecimal("0.0") : new BigDecimal(parts[6]));
}
if (retInt < 2){
isWeting = false;
break;
}
}
}else{
isWeting = true;
}
ErpToupOpItmrefVO erpToupOpItmref = new ErpToupOpItmrefVO();
erpToupOpItmref.setIsToup(isWeting);
erpToupOpItmref.setStandardQty(standardQty);
erpToupOpItmref.setActualQty(actualQty);
return erpToupOpItmref;
}
}