解决工作问题---跟上游进行接口联调

1.以TCP方式进行通信

自己手写一个服务端:

    public static void main(String[] args) {
        try {
            ServerSocket socket = new ServerSocket(8801);
            System.out.println("socket套接字创建成功,等待连接");

            while (true){
                final Socket con = socket.accept();
                System.out.println("有客户端接入");

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //获取输入流,用来读取数据
                        InputStream in;
                        try {
                            in = con.getInputStream();
                            int len;
                            byte[] data = new byte[2048];
                            len = in.read(data);
                            System.out.println("读到消息:" + new String(data,0,len));

                            OutputStream out = con.getOutputStream();
                            byte[] a = xml.getBytes(StandardCharsets.UTF_8);
                            out.write(a);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

以XML格式进行对接则需要构建XML

@XmlRootElement(name="root")
@XmlType(propOrder = {"header","event","body"})
public class Root {
    private Header header;
    private Event event;
    private Body body;

    @XmlElement
    public Header getHeader() {
        return header;
    }
    public void setHeader(Header header) {
        this.header = header;
    }

    @XmlElement
    public Event getEvent() {
        return event;
    }

    public void setEvent(Event event) {
        this.event = event;
    }

    @XmlElement
    public Body getBody() {
        return body;
    }

    public void setBody(Body body) {
        this.body = body;
    }
}
@XmlType(propOrder = {"eventId","eventName","version","eventSwitch","contentType","location"}) //按你指定的顺序展示
public class Header {

    private String eventId = "0";
    private String eventName = "partProcessed";
    private String version = "1.0";
    private String eventSwitch;
    private String contentType = "3";

    private Location location;

    @XmlAttribute
    public String getEventId() {
        return eventId;
    }

    public void setEventId(String eventId) {
        this.eventId = eventId;
    }

    @XmlAttribute
    public String getEventName() {
        return eventName;
    }

    public void setEventName(String eventName) {
        this.eventName = eventName;
    }

    @XmlAttribute
    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @XmlAttribute
    public String getEventSwitch() {
        return eventSwitch;
    }

    public void setEventSwitch(String eventSwitch) {
        this.eventSwitch = eventSwitch;
    }

    @XmlAttribute
    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }


    @XmlElement
    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }
}
@XmlType(propOrder = {"lineNo","statNo","statIdx","fuNo","workPos","toolPos","application","processName","processNo"})
public class Location {

    private String lineNo = "5109";
    private String statNo = "175";
    private String statIdx = "1";
    private String fuNo = "1";
    private String workPos = "1";
    private String toolPos = "1";
    private String application = "IPC";
    private String processName ="";
    private String processNo="51091175";

    @XmlAttribute
    public String getLineNo() {
        return lineNo;
    }

    public void setLineNo(String lineNo) {
        this.lineNo = lineNo;
    }

    @XmlAttribute
    public String getStatNo() {
        return statNo;
    }

    public void setStatNo(String statNo) {
        this.statNo = statNo;
    }

    @XmlAttribute
    public String getStatIdx() {
        return statIdx;
    }

    public void setStatIdx(String statIdx) {
        this.statIdx = statIdx;
    }

    @XmlAttribute
    public String getFuNo() {
        return fuNo;
    }

    public void setFuNo(String fuNo) {
        this.fuNo = fuNo;
    }

    @XmlAttribute
    public String getWorkPos() {
        return workPos;
    }

    public void setWorkPos(String workPos) {
        this.workPos = workPos;
    }

    @XmlAttribute
    public String getToolPos() {
        return toolPos;
    }

    public void setToolPos(String toolPos) {
        this.toolPos = toolPos;
    }

    @XmlAttribute
    public String getApplication() {
        return application;
    }

    public void setApplication(String application) {
        this.application = application;
    }

    @XmlAttribute
    public String getProcessName() {
        return processName;
    }

    public void setProcessName(String processName) {
        this.processName = processName;
    }

    @XmlAttribute
    public String getProcessNo() {
        return processNo;
    }

    public void setProcessNo(String processNo) {
        this.processNo = processNo;
    }
}
public class Event {

    private PartProcessed partProcessed;

    @XmlElement
    public PartProcessed getPartProcessed() {
        return partProcessed;
    }

    public void setPartProcessed(PartProcessed partProcessed) {
        this.partProcessed = partProcessed;
    }
}
@XmlType(propOrder = {"identifier"})
public class PartProcessed {

    private String identifier;

    @XmlAttribute
    public String getIdentifier() {
        return identifier;
    }

    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }
}
public class Body {
    private Structs structs;

    @XmlElement
    public Structs getStructs() {
        return structs;
    }

    public void setStructs(Structs structs) {
        this.structs = structs;
    }
}
public class Structs {

    private ResHead resHead;

    @XmlElement
    public ResHead getResHead() {
        return resHead;
    }

    public void setResHead(ResHead resHead) {
        this.resHead = resHead;
    }
}
@XmlType(propOrder = {"nioBits","result","typeNo","typeVar","workingCode"})
public class ResHead {

    private String nioBits = "0";
    private String result = "1";
    private String typeNo = "1111111111";
    private String typeVar = "0001";
    private String workingCode = "0";

    @XmlAttribute
    public String getNioBits() {
        return nioBits;
    }

    public void setNioBits(String nioBits) {
        this.nioBits = nioBits;
    }

    @XmlAttribute
    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    @XmlAttribute
    public String getTypeNo() {
        return typeNo;
    }

    public void setTypeNo(String typeNo) {
        this.typeNo = typeNo;
    }

    @XmlAttribute
    public String getTypeVar() {
        return typeVar;
    }

    public void setTypeVar(String typeVar) {
        this.typeVar = typeVar;
    }

    @XmlAttribute
    public String getWorkingCode() {
        return workingCode;
    }

    public void setWorkingCode(String workingCode) {
        this.workingCode = workingCode;
    }
}
    public Integer backToLibrary(String binCode,String eventSwitch) {

        //构建XML
        Root root = new Root();
        Header header = new Header();
        Location location = new Location();
        header.setLocation(location);
        header.setEventSwitch(eventSwitch);

        Event event = new Event();
        PartProcessed partProcessed = new PartProcessed();
        partProcessed.setIdentifier(binCode);
        event.setPartProcessed(partProcessed);

        Body body = new Body();
        Structs structs = new Structs();
        ResHead resHead = new ResHead();
        structs.setResHead(resHead);
        body.setStructs(structs);

        root.setHeader(header);
        root.setEvent(event);
        root.setBody(body);

        JAXBContext context;

        Integer code = null;

        try {
            context = JAXBContext.newInstance(Root.class);
            Marshaller mar = context.createMarshaller();
            mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            mar.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

            StringWriter writer = new StringWriter();

            mar.marshal(root, writer);

            log.info("XML: {}",writer.toString());

            //将拼接好的xml发送给上游服务端,获取回复报文
            String result = returnResult(writer.toString());

            //解析XML,转成JSON拿到数量
            code = returnCode(result);

        } catch (JAXBException e) {
            e.printStackTrace();
        }

        return code;
    }

 

调用接口后需要解析上游返回的XML来进行业务处理

    public Integer returnCode(String xml) {

        Integer code = null;

        try {
            JSONObject js = XML.toJSONObject(xml);
            log.info("JSON数据 : {}",js);

            Object root = js.get("root");
            JSONObject rootValue = (JSONObject) root;

            Object event = rootValue.get("event");
            JSONObject eventValue = (JSONObject) event;

            Object result = eventValue.get("result");
            JSONObject resultValue = (JSONObject) result;

            Object returnCode = resultValue.get("returnCode");

            code = (Integer) returnCode;

        } catch (JSONException e) {
            e.printStackTrace();
        }

        return code;
    }

 

建立通信连接

    public String returnResult(String xml) {

        String result = "";
        Socket client = null;
        OutputStream out = null;
        DataOutputStream output = null;
        InputStream in = null;
        DataInputStream din = null;

        try {
            client = new Socket(host, port);

            //获取数据发送通道
            out = client.getOutputStream();
            output = new DataOutputStream(out);
            SendMessage(xml,output);

            //获取数据接收通道
            in = client.getInputStream();
            din = new DataInputStream(in);

            int len;
            byte[] data = new byte[2048];
            len = din.read(data);
            result = new String(data,0,len);
            log.info("获得服务端返回的数据:" + new String(data,0,len));

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            try {
                if(din!=null){
                    din.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(in!=null){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(output !=null){
                    output.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(out!=null){
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(client!=null){
                    client.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

 

对发送的报文进行十六进制转译

    public static void SendMessage(String message, DataOutputStream netS) throws IOException{

        //把发送过来的信息转化为一个字符数组1
        byte[] bSendContentOra = message.getBytes();

        //字符串的长度
        int iLenSendContent = message.length();

        //报文长度+4的总长度转化为字节数组
        byte[] bSendContentHead = getBytes(iLenSendContent + 4);

        byte[] bSendContent = new byte[iLenSendContent + 4];

        //一个新的字符数组3,大小为字符串长度+4
        for (int i = 0; i < 4; i++) {
            //这个新的数组3的前四项等于数组2的倒置
            bSendContent[i] = bSendContentHead[4 - i - 1];
        }

        for (int i = 0; i < message.length(); i++) {
            //这个新的数组3的第四项之后等于字符数组的每一项
            bSendContent[i + 4] = bSendContentOra[i];
        }

        netS.write(bSendContent, 0,bSendContent.length);
    }

    public static byte[] getBytes(int data){

        byte[] bytes = new byte[4];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data & 0xff00) >> 8);
        bytes[2] = (byte) ((data & 0xff0000) >> 16);
        bytes[3] = (byte) ((data & 0xff000000) >> 24);

        return bytes;
    }

 

2.以WebService方式通信

public interface WipClient {

    @RequestLine("POST")
    @Headers(value = {"Content-Type: application/x-www-form-urlencoded;charset=UTF-8"})
    String send(URI uri,@RequestBody String body);

    @RequestLine("POST")
    @Headers(value = {"Content-Type: application/x-www-form-urlencoded;charset=UTF-8"})
    String moveInSendReturnIn(URI uri, @RequestBody String body);

    @RequestLine("POST")
    @Headers(value = {"Content-Type: application/x-www-form-urlencoded;charset=UTF-8"})
    String moveOutSend(URI uri,@RequestBody String body);

    @RequestLine("POST")
    @Headers(value = {"Content-Type: application/x-www-form-urlencoded;charset=UTF-8"})
    String moveInSendProductionIn(URI uri,@RequestBody String body);
}

 

需要在Feign注册

@Configuration
public class FeignConfig {
@Bean
public WipClient wipClient(Decoder decoder, Encoder encoder) {
return Feign.builder().encoder(encoder).decoder(decoder)
.target(Target.EmptyTarget.create(WipClient.class));
}
}

 

需要自己写一个mock用来自测

@RestController
@RequestMapping(value = "")
@Slf4j
public class wipController {

@Value("${wip.flag1}")
private Boolean flag1;

@Value("${wip.flag2}")
private Boolean flag2;

@Value("${wip.flag3}")
private Boolean flag3;

@PostMapping("/test111")
public String moveInSendReturnIn(@RequestBody String body){
log.info("上架returnIn回传内容" + body);

if (flag1){
return b;
}else {
return a;
}
}

@PostMapping("/test222")
public String moveOutSend(@RequestBody String body){
log.info("出库回传内容" + body);

if (flag2){
return b;
}else {
return a;
}
}

@PostMapping("/test333")
public String moveInSendProductionIn(@RequestBody String body){
log.info("上架productionIN回传内容" + body);

if (flag3){
return b;
}else {
return a;
}
}
}

 

需要在Nacos里配置好

wip:
  customer_url: http://172.20.8.120:10000
  stockSync: /test1
  moveInSendReturnIn: /test111
  moveOutSend: /test222
  moveInSendProductionIn: /test333
  api:
    moveInCallbackApi1: WIP_PCBAPUTAWAY_IWMS
    moveInCallbackApi2: WIP_PCBABACK_IWMS
    moveOutCallbackApi: WIP_PCBAPICKOUT_IWMS
  flag1: true   
  flag2: true  
  flag3: true 
mes:
  # 出库回传标识
  eventSwitch1: -1
  # 回库标识
  eventSwitch2: 2
  # 上游服务端host
  host: 192.168.230.130
  # 上游服务端port
  port: 8801

 

解析上游返回的数据

    private String xml2JSON(String xml){
        cn.hutool.json.JSONObject jsonObject = XML.toJSONObject(xml);
        Object returnMsg = jsonObject.get("string");
        cn.hutool.json.JSONObject returnMsgValue = (cn.hutool.json.JSONObject) returnMsg;
        String o = (String) returnMsgValue.get("content");
        Gson gson = new Gson();
        Map<String, Object> map = new HashMap<String, Object>();
        map = gson.fromJson(o, map.getClass());
        return (String) map.get("MESSAGE_TYPE");
    }

 

XXL-Job定时查询数据进行回传

    /**
     * 定时查询出库单状态,如果有完成且Wip为未回传的出库单,则回传给客户系统,按订单,封箱码,明细回传都是针对一个订单
     */
    @XxlJob("moveOutOrderCallBackByOrderIdWipScheduler")
    public void moveOutOrderCallBackByOrderIdWip() {
        log.info("moveOutOrderCallBackByOrderId,当前时间" + LocalDateTime.now());
        CommonResponse<List<KsSaleOrderHeaderDTO>> moveOutOrderFinishedAndNotCallBack = moveOutApi.getMoveOutPreAllocatedFinishedAndNotCallBackWip();
        List<KsSaleOrderHeaderDTO> moveOutList = moveOutOrderFinishedAndNotCallBack.getData();
        moveOutList = moveOutList.stream().filter(moveOut -> moveOut.getStatus() == KsSaleOrderStatusEnum.FULL.getCode()).collect(Collectors.toList());
        log.info("出库预分配完成的订单信息{}", JSON.toJSONString(moveOutList));
        if (moveOutOrderFinishedAndNotCallBack.isSuccess() && !CollectionUtils.isEmpty(moveOutList)) {
            for (KsSaleOrderHeaderDTO ksSaleOrderHeaderDTO : moveOutList) {
                CommonResponse<List<KsSaleOrderDetailPreAllocatedRecordDTO>> listCommonResponse = moveOutApi.queryByHeaderId(ksSaleOrderHeaderDTO.getId());
                if (listCommonResponse.isSuccess()) {
                    List<KsSaleOrderDetailPreAllocatedRecordDTO> preAllocatedRecordDTOS = listCommonResponse.getData();
                    for (KsSaleOrderDetailPreAllocatedRecordDTO preAllocatedRecordDTO : preAllocatedRecordDTOS) {
                        if (OrderCallbackStatus.NOT_CALLBACK.getCode() == preAllocatedRecordDTO.getWipCallbackStatus()
                                || OrderCallbackStatus.CALLBACK_ERROR.getCode() == preAllocatedRecordDTO.getWipCallbackStatus()) {
                            WipMoveOutDTO wipMoveOutDTO = moveOutNewWipDTO(ksSaleOrderHeaderDTO,preAllocatedRecordDTO);
                            try {
                                String bodyStr = wipClient.moveOutSend(new URI(uri + moveOutSend),"Param=" + JsonUtils.obj2String(wipMoveOutDTO));
                                log.info("callbackWIP返回结果:{}", bodyStr);
                                String messageType = xml2JSON(bodyStr);
                                if ("SUCCESS".equalsIgnoreCase(messageType)) {
                                    String topic = KafkaTopicConstants.wms_core_move_out_order_wip;
                                    JSONObject jsonObject = moveOutSuccessNewJsonObjectWip(preAllocatedRecordDTO);
                                    log.info("回传-将结果发MQ给Core {} {}", kv(LogKey.TOPIC, topic), JSONObject.toJSONString(jsonObject));
                                    kafkaSender.send(topic, jsonObject.toJSONString());
                                } else {
                                    String topic = KafkaTopicConstants.wms_core_move_out_order_wip;
                                    JSONObject jsonObject = moveOutErrorNewJsonObjectWip(ksSaleOrderHeaderDTO, preAllocatedRecordDTO, wipMoveOutDTO);
                                    log.info("回传-将结果发MQ给Core {} {}", kv(LogKey.TOPIC, topic), JSONObject.toJSONString(jsonObject));
                                    kafkaSender.send(topic, jsonObject.toJSONString());
                                }
                            } catch (Exception e) {
                                log.error(e.getMessage());
                                throw new ApiException("WIP出库回传错误!");
                            }
                        }
                    }
                }
            }
        }
    }

 

3.以HTTP方式通信

手写一个HTTP请求

@Slf4j
@RequiredArgsConstructor
@Component
public class SealClient {

    @Value("${callback.url}")
    private String uri;

    @Value("${callback.sealBox}")
    private String sealBox;

    public String sealBox(List<SealBinCallBackDTO> sealBinCallBackDTOs){
        HashMap<String, String> headers = new HashMap<>();
        headers.put("Content-Type","application/json");

        String body = HttpUtil.createPost(uri + sealBox)
                .addHeaders(headers)
                .body(JSON.toJSONString(sealBinCallBackDTOs))
                .execute()
                .body();

        return body;
    }
}

 

调用接口进行封箱回传

    @Transactional(transactionManager = "mysqlTransactionManager", rollbackFor = Exception.class)
    public synchronized void callbackSealBox(String outerBoxCode) {
        List<SealBinCallBackDTO> sealBinCallBackDTOs = createSealBinCallBackDTO(outerBoxCode);
        log.info("调用上游接口入参: {}",JSON.toJSONString(sealBinCallBackDTOs));
        String response = sealClient.sealBox(sealBinCallBackDTOs);
        log.info("上游系统返回: {}",response);
        JSONObject jsonObject = JSON.parseObject(response);
        Object result = jsonObject.get("result");
        Map<String, Object> requestBody = JSON.parseObject(String.valueOf(result));
        if (requestBody.get("code").equals(0)){
            log.info("成功了");
            LambdaUpdateWrapper<KsSaleOrderContainerSku> wrapper = new LambdaUpdateWrapper<KsSaleOrderContainerSku>()
                    .set(KsSaleOrderContainerSku::getCallbackStatus, KsSaleOrderSnCallbackStatus.UPLOADED.getValue())
                    .eq(KsSaleOrderContainerSku::getOuterBoxCode, outerBoxCode);
            ksSaleOrderContainerSkuMapper.update(null,wrapper);
        }else {
            LambdaUpdateWrapper<KsSaleOrderContainerSku> wrapper = new LambdaUpdateWrapper<KsSaleOrderContainerSku>()
                    .set(KsSaleOrderContainerSku::getCallbackStatus, KsSaleOrderSnCallbackStatus.UPLOAD_FAILED.getValue())
                    .eq(KsSaleOrderContainerSku::getOuterBoxCode, outerBoxCode);
            ksSaleOrderContainerSkuMapper.update(null,wrapper);
        }
    }

 

手写一个MOCK服务端

@RestController
@RequestMapping(value = "")
@Slf4j
public class MockController {

    @Value("${callback.mock}")
    private boolean isMock;

    @PostMapping("/test1")
    public String sealBox(@RequestBody String body){
        log.info("外箱码封箱接口内容:" + body);

        if (isMock) {
            return " {\n" +
                    "     \"jsonrpc\": \"2.0\",\n" +
                    "     \"result\": {\n" +
                    "         \"code\": 0,\n" +
                    "         \"data\": {},\n" +
                    "         \"message\": \"ok\",\n" +
                    "         \"timestamp\": \"\",\n" +
                    "         \"traceid\": \"\"\n" +
                    "     }\n" +
                    "}";
        }
        return " {\n" +
                "     \"jsonrpc\": \"2.0\",\n" +
                "     \"result\": {\n" +
                "         \"code\": 500,\n" +
                "         \"data\": {},\n" +
                "         \"message\": \"ok\",\n" +
                "         \"timestamp\": \"\",\n" +
                "         \"traceid\": \"\"\n" +
                "     }\n" +
                "}";
    }
}

 

posted @ 2022-10-11 17:16  最强Java代表  阅读(136)  评论(0编辑  收藏  举报