1. 程式人生 > >基於webservice soap協議利用xml格式自定義報文進行傳輸和解析返回報文(例項)

基於webservice soap協議利用xml格式自定義報文進行傳輸和解析返回報文(例項)

一.傳送自定義soap報文(內嵌jsonString)獲取返回報文工具類

import com.meeno.apiservice.framework.BusinessException;
import javax.xml.soap.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;

/**
 * 傳送自定義soap報文(內嵌jsonString)獲取返回報文工具類
 */
public class SoapUtil {
    //對接服務地址
    private String addressUrl="http://XXXXXXXX";


    public SoapHepler(String addressUrl) {
        if(addressUrl!=null&&!"".equals(addressUrl.trim())){
            this.addressUrl = addressUrl;
        }
    }
    /**
     * 新增所需資訊
     * @param bodyJsonStr  請求體json
     * @param svcname      服務名稱
     * @param svccode      服務編碼
     * @param svcver       服務版本
     * @param orisys       來源系統標識
     * @param trantime     交易發起時間
     * @param tranno       全域性交易流水號
     * @param branchno     操作員機構程式碼op
     * @param userid       使用者IDop
     * @param tokenid      口令或令牌op
     * @param signature    數字簽名op
     * @param branchnoo    機構程式碼
     * @param destsys      目標系統標識
     * @return
     */
    public String sendSoapXml(String bodyJsonStr,
                              String svcname, String svccode,
                              String svcver,String orisys,
                              String trantime,String tranno,
                              String branchno,String userid,
                              String tokenid,String signature,
                              String branchnoo,String destsys) {
        String AUTH_PREFIX = "cl";
        String AUTH_NS = "http://www.e-chinalife.com/soa/";
        String XSD_NS = "http://www.w3.org/2001/XMLSchema";
        String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
        try {
            //例項化一個soap連線物件工廠
            SOAPConnectionFactory soapConnFactory = SOAPConnectionFactory.newInstance();
            //例項化一個連線物件
            SOAPConnection connection = soapConnFactory.createConnection();
            //例項化一個訊息物件
            MessageFactory messageFactory = MessageFactory.newInstance();
            //例項化一個訊息
            SOAPMessage message = messageFactory.createMessage();
            //獲取訊息中soap訊息部分的控制代碼
            SOAPPart soapPart = message.getSOAPPart();
            //獲取soap訊息部分中的信封控制代碼
            SOAPEnvelope envelope = soapPart.getEnvelope();
            envelope.setPrefix("soapenv");
            envelope.removeNamespaceDeclaration("SOAP-ENV");
//            envelope.setAttribute("xmlns:xsd", XSD_NS);
////            envelope.setAttribute("xmlns:xsi", XSI_NS);
            envelope.setAttribute("xmlns:soa", AUTH_NS);
            //獲取信封中需要填寫的請求報文部分的控制代碼
            //建立soap工廠
            SOAPFactory soapFactory = SOAPFactory.newInstance();
            //新增訊息體以及json字串
            SOAPBody body = envelope.getBody();
            body.setPrefix("soapenv");
            SOAPBodyElement bodyElement = body.addBodyElement(envelope.createName("execute", "soa", null));
            SOAPElement requestData = bodyElement.addChildElement("requestData","soa");
            requestData.addTextNode(judgeNull(bodyJsonStr));
            //新增資訊頭內容
            SOAPHeader header = envelope.getHeader();
            header.setPrefix("soapenv");
            SOAPElement wsHeaderElm = soapFactory.createElement("HEADER", AUTH_PREFIX, AUTH_NS);
            SOAPElement svcnameElm = soapFactory.createElement("SVCNAME");
            SOAPElement svccodeNameElm = soapFactory.createElement("SVCCODE");
            SOAPElement svcverElm = soapFactory.createElement("SVCVER");
            SOAPElement orisysElm = soapFactory.createElement("ORISYS");
            SOAPElement trantimeElm = soapFactory.createElement("TRANTIME");
            SOAPElement trannoElm = soapFactory.createElement("TRANNO");
            SOAPElement authElm = soapFactory.createElement("AUTH");
            SOAPElement securityElm = soapFactory.createElement("SECURITY");
            SOAPElement routeElm = soapFactory.createElement("ROUTE");
            SOAPElement branchnoElm = soapFactory.createElement("BRANCHNO");
            SOAPElement useridElm = soapFactory.createElement("USERID");
            SOAPElement tokenidElm = soapFactory.createElement("TOKENID");
            SOAPElement signatureElm = soapFactory.createElement("SIGNATURE");
            SOAPElement branchnooElm = soapFactory.createElement("BRANCHNO");
            SOAPElement destsysElm = soapFactory.createElement("DESTSYS");
            //為上述訊息頭標籤新增節點文字值
            svcnameElm.addTextNode(judgeNull(svcname));
            svccodeNameElm.addTextNode(judgeNull(svccode));
            svcverElm.addTextNode(judgeNull(svcver));
            orisysElm.addTextNode(judgeNull(orisys));
            trantimeElm.addTextNode(judgeNull(trantime));
            trannoElm.addTextNode(judgeNull(tranno));
            branchnoElm.addTextNode(judgeNull(branchno));
            useridElm.addTextNode(judgeNull(userid));
            tokenidElm.addTextNode(judgeNull(tokenid));
            signatureElm.addTextNode(judgeNull(signature));
            branchnooElm.addTextNode(judgeNull(branchnoo));
            destsysElm.addTextNode(judgeNull(destsys));
            authElm.addChildElement(branchnoElm);
            authElm.addChildElement(useridElm);
            authElm.addChildElement(tokenidElm);
            securityElm.addChildElement(signatureElm);
            routeElm.addChildElement(branchnooElm);
            routeElm.addChildElement(destsysElm);
            wsHeaderElm.addChildElement(svcnameElm);
            wsHeaderElm.addChildElement(svccodeNameElm);
            wsHeaderElm.addChildElement(svcverElm);
            wsHeaderElm.addChildElement(orisysElm);
            wsHeaderElm.addChildElement(trantimeElm);
            wsHeaderElm.addChildElement(trannoElm);
            wsHeaderElm.addChildElement(authElm);
            wsHeaderElm.addChildElement(securityElm);
            wsHeaderElm.addChildElement(routeElm);
            header.addChildElement(wsHeaderElm);
            message.saveChanges();
            System.out.println("輸出報文,如下:");
            message.writeTo(System.out);
            //傳送資訊
            SOAPMessage call = connection.call(message, addressUrl);
            TransformerFactory transformerFactory=TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            Source sourceContent = call.getSOAPPart().getContent();
            StreamResult result = new StreamResult(new ByteArrayOutputStream());
            transformer.transform(sourceContent,result);
            //獲取返回報文
            String s = ((ByteArrayOutputStream) result.getOutputStream()).toString();
            System.out.println("返回報文,如下:");
            System.out.print( s);
            connection.close();
            return s;
        } catch (Exception e) {
             throw new BusinessException("返回報文失敗  ,錯誤資訊:"+e);
        }
    }
    /**新增上述節點文字是不能為null
     * 如果str為null 置為“”
     * @param str
     * @return
     */
    public static  String  judgeNull(String str){
        return (str==null)?"":str;
    }

}

二. 解析返回soap報文,獲取目標節點值

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 解析返回soap報文,獲取目標節點值
 */
public class XMLUtil {

    /**
     * 將字串型別的XML 轉化成Docunent文件結構</p>
     * @param parseStrXml  待轉換的xml 字串
     * @return
     */
    public static Document strXmlToDocument(String parseStrXml){
        StringReader read = new StringReader(parseStrXml);
        //建立新的輸入源SAX 解析器將使用 InputSource 物件來確定如何讀取 XML 輸入
        InputSource source = new InputSource(read);
        //建立一個新的SAXBuilder
        SAXBuilder sb = new SAXBuilder();   // 新建立構造器
        Document doc = null;
        try {
            doc = sb.build(source);
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return doc;
    }

    /**
     *  根據目標節點名獲取值
     * @param doc 文件結構
     * @param finalNodeName  最終節點名
     * @return
     */
    public static String getValueByElementName(Document doc,String finalNodeName){
        Element root = doc.getRootElement();
        HashMap<String,Object> map=new HashMap<String,Object>();
       //呼叫getChildAllText方法。獲取目標子節點的值
        Map<String,Object> resultmap=getChildAllText(doc, root,map);
        String result=(String)resultmap.get(finalNodeName);
        return result;
    }

    /**
     *  遞迴獲得子節點的值
     * @param doc 文件結構
     * @param e  節點元素
     * @param resultmap  遞迴將值壓入map中
     * @return
     */
    public static Map<String ,Object> getChildAllText(Document doc, Element e,HashMap<String,Object> resultmap)
    {
        if (e != null)
        {
            if (e.getChildren() != null)   //如果存在子節點
            {
                List<Element> list = e.getChildren();
                for (Element el : list)    //迴圈輸出
                {
                    if(el.getChildren().size() > 0)   //如果子節點還存在子節點,則遞迴獲取
                    {
                        getChildAllText(doc, el,resultmap);
                    }
                    else
                    {
                        resultmap.put(el.getName(), el.getTextTrim());  //將葉子節點值壓入map
                    }
                }
            }
        }
        return resultmap;
    }

}

三.測試controller

import com.menno.insurance.chinalifeinsurance.utils.SoapHepler;
import com.menno.insurance.chinalifeinsurance.utils.XMLUtil;
import org.apache.axis.AxisFault;
import org.jdom.Document;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * just for test by fangyi
 */
@RestController
public class ControllerForTest {

    @RequestMapping("/testSoap1")
    public String getSoapXml() throws AxisFault {
        String hospitalRegistrationUrl="http://xxx.xxx.xxx.xxxx:xxxx/SOA/CIS/ApplyMDExchange";
        Date date  = new Date();
        SimpleDateFormat ad= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");

        String format = ad.format(date);

  String registrationData=" { 'root': { 'head': {  'BusinessType': '3', 'CorrelationId': '172b9e03490c1143aa123f8f3096622074d0505e','MessageDateTime': '2016-9-26 13:53:05.12',  'MessageId': '201611210001', 'ReceiverAddress': '',    'ReceiverCode': 'UNCL', 'ReceiverName': '中國人壽保險股份有限公司(宜昌)', 'SenderAddress': '', 'SenderCode': '20161104001', 'SenderName': '天津社保局', 'StandardVersionCode': '1.0.0', 'TotalRecord': '', 'TransRefGUID': '201611210001', 'TransactionCode': 'S107', 'TransactionSubCode': '00' },'body': {'HospitalRegistration': { 'PersonGUID': '372922731004503', 'MedicalGUID': '201802010002', 'Name': '測試', 'GenderCode': '1', 'Birthday': '1973-10-03 00:00:00', 'CredentialNum': '372922731004503', 'CredentialType': 'I', 'InstituteCode': '120000', 'BelongInstituteAreaCode': '120000', 'AccidentDate': '', 'AccidentProcedure': '', 'AccidentReason': '2', 'Address': '武漢市青山區紅衛路49街坊100門1號', 'AllergyHistory': '', 'BabyName': '', 'BedNumber': '44', 'BodyMassIndex': '', 'ChestCircumference': '', 'Company': '無', 'ComplicationCode': '', 'DiastolicPressure': '', 'FamilyDiseaseHistory': '', 'HeartRate': '', 'Height': '', 'HospitalNumber': '201674903', 'MainDiagnosisCode': 'J98.414', 'MainDiagnosisName': '肺部感染', 'MarriageStatus': '', 'MasterDoctor': '湯鎮', 'MedicalDate': '2011-08-31 01:03:59', 'MedicalDepartment': '呼吸內科住院', 'MedicalInstituteCode': '11', 'MedicalInstituteName': '三峽大學咐屬仁和醫院', 'MedicalType': '21', 'Memo': '', 'Mobilephone': '15971663338', 'Nationality': '01', 'NowDiseaseHistory': '', 'OperatorName': '', 'OperatorNum': '', 'OtherDiagnosisCode': '', 'PathologyReport': '', 'PatientAreaNumber': '17', 'PatientType': 'N', 'PersonalIdentification': '', 'Phone': '', 'PhysicalExaminationReport': '', 'PrincipleAction': '', 'ProviderID': '', 'Pulse': '', 'Rhythm': '', 'SecondaryDiagnosisCode': 'N39.000', 'SecondaryDiagnosisName': '泌尿道感染', 'SettlementWay': '1', 'SocialInsuranceNumber': '901099033', 'SocialMedicareType': 'JD', 'SystolicPressure': '', 'TCMReport': '', 'Temperature': '', 'Weight': '', 'BankCode': '1101', 'BankName': '中國工商銀行', 'AccountNumber': '111122223333', 'AccountHolder': '哈哈哈' } } } }";

   //傳送soap報文
        SoapHepler soapHepler=new SoapHepler(hospitalRegistrationUrl);
        String s = soapHepler.sendSoapXml(registrationData, "ApplyMDExchange", "CIS-0007",
            "1.0", "SZSB-EPS", ""+format, "6", null, null, null,null, "000000", "CIS");
        //解析,獲取返回json
        Document document = XMLUtil.strXmlToDocument(s);
        String returnJson = XMLUtil.getValueByElementName(document, "return");
        System.out.print(returnJson);
        return returnJson;
    }
}

四.效果

輸出報文,如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soa="http://www.e-chinalife.com/soa/"><soapenv:Header><cl:HEADER xmlns:cl="http://www.e-chinalife.com/soa/"><SVCNAME>ApplyMDExchange</SVCNAME><SVCCODE>CIS-0007</SVCCODE><SVCVER>1.0</SVCVER><ORISYS>SZSB-EPS</ORISYS><TRANTIME>2018-02-22 16:50:38,101</TRANTIME><TRANNO>6</TRANNO><AUTH><BRANCHNO/><USERID/><TOKENID/></AUTH><SECURITY><SIGNATURE/></SECURITY><ROUTE><BRANCHNO>000000</BRANCHNO><DESTSYS>CIS</DESTSYS></ROUTE></cl:HEADER></soapenv:Header><soapenv:Body><soa:execute><soa:requestData xmlns:soa="http://www.e-chinalife.com/soa/"> { 'root': { 'head': {  'BusinessType': '3', 'CorrelationId': '172b9e03490c1143aa123f8f3096622074d0505e','MessageDateTime': '2016-9-26 13:53:05.12',  'MessageId': '201611210001', 'ReceiverAddress': '',    'ReceiverCode': 'UNCL', 'ReceiverName': '中國人壽保險股份有限公司(宜昌)', 'SenderAddress': '', 'SenderCode': '20161104001', 'SenderName': '天津社保局', 'StandardVersionCode': '1.0.0', 'TotalRecord': '', 'TransRefGUID': '201611210001', 'TransactionCode': 'S107', 'TransactionSubCode': '00' },'body': {'HospitalRegistration': { 'PersonGUID': '372922731004503', 'MedicalGUID': '201802010002', 'Name': '測試', 'GenderCode': '1', 'Birthday': '1973-10-03 00:00:00', 'CredentialNum': '372922731004503', 'CredentialType': 'I', 'InstituteCode': '120000', 'BelongInstituteAreaCode': '120000', 'AccidentDate': '', 'AccidentProcedure': '', 'AccidentReason': '2', 'Address': '武漢市青山區紅衛路49街坊100門1號', 'AllergyHistory': '', 'BabyName': '', 'BedNumber': '44', 'BodyMassIndex': '', 'ChestCircumference': '', 'Company': '無', 'ComplicationCode': '', 'DiastolicPressure': '', 'FamilyDiseaseHistory': '', 'HeartRate': '', 'Height': '', 'HospitalNumber': '201674903', 'MainDiagnosisCode': 'J98.414', 'MainDiagnosisName': '肺部感染', 'MarriageStatus': '', 'MasterDoctor': '湯鎮', 'MedicalDate': '2011-08-31 01:03:59', 'MedicalDepartment': '呼吸內科住院', 'MedicalInstituteCode': '11', 'MedicalInstituteName': '三峽大學咐屬仁和醫院', 'MedicalType': '21', 'Memo': '', 'Mobilephone': '15971663338', 'Nationality': '01', 'NowDiseaseHistory': '', 'OperatorName': '', 'OperatorNum': '', 'OtherDiagnosisCode': '', 'PathologyReport': '', 'PatientAreaNumber': '17', 'PatientType': 'N', 'PersonalIdentification': '', 'Phone': '', 'PhysicalExaminationReport': '', 'PrincipleAction': '', 'ProviderID': '', 'Pulse': '', 'Rhythm': '', 'SecondaryDiagnosisCode': 'N39.000', 'SecondaryDiagnosisName': '泌尿道感染', 'SettlementWay': '1', 'SocialInsuranceNumber': '901099033', 'SocialMedicareType': 'JD', 'SystolicPressure': '', 'TCMReport': '', 'Temperature': '', 'Weight': '', 'BankCode': '1101', 'BankName': '中國工商銀行', 'AccountNumber': '111122223333', 'AccountHolder': '哈哈哈' } } } }</soa:requestData></soa:execute></soapenv:Body></soapenv:Envelope>

返回報文,如下:

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><ns2:executeResponse xmlns:ns2="http://www.e-chinalife.com/soa/"><return>{"root":{"body":{"HospitalRegistrationResponse":{"Message":"success","MessageStatusCode":"10","BusinessProcessStatus":{"BusinessStatus":"1","BusinessName":"","BusinessMessage":"success!客戶測試,證件號:372922731004503住院申報已成功,不能重複申報!請核對"}}},"head":{"StandardVersionCode":"1.0.0","TransactionSubCode":"00","TransactionCode":"S107","BusinessType":"3","ReceiverCode":"20161104001","SenderName":"中國人壽保險股份有限公司(宜昌)","ReceiverAddress":"","MessageDateTime":"","CorrelationId":"5919e086779a40bb3bcd89d5c27eb0373f33a180","MessageId":"201611210001","SenderAddress":"","SenderCode":"UNCL","TotalRecord":"","TransRefGUID":"201611210001","ReceiverName":"天津社保局"}}}</return></ns2:executeResponse></soap:Body></soapenv:Envelope>{"root":{"body":{"HospitalRegistrationResponse":{"Message":"success","MessageStatusCode":"10","BusinessProcessStatus":{"BusinessStatus":"1","BusinessName":"","BusinessMessage":"success!客戶測試,證件號:372922731004503住院申報已成功,不能重複申報!請核對"}}},"head":{"StandardVersionCode":"1.0.0","TransactionSubCode":"00","TransactionCode":"S107","BusinessType":"3","ReceiverCode":"20161104001","SenderName":"中國人壽保險股份有限公司(宜昌)","ReceiverAddress":"","MessageDateTime":"","CorrelationId":"5919e086779a40bb3bcd89d5c27eb0373f33a180","MessageId":"201611210001","SenderAddress":"","SenderCode":"UNCL","TotalRecord":"","TransRefGUID":"201611210001","ReceiverName":"天津社保局"}}}2018-02-22 16:50:41.587  INFO 85992 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via configuration

解析獲取jsonString:

{"root":{"body":{"HospitalRegistrationResponse":{"Message":"success","MessageStatusCode":"10","BusinessProcessStatus":{"BusinessStatus":"1","BusinessName":"","BusinessMessage":"success!客戶測試,證件號:372922731004503住院申報已成功,不能重複申報!請核對"}}},"head":{"StandardVersionCode":"1.0.0","TransactionSubCode":"00","TransactionCode":"S107","BusinessType":"3","ReceiverCode":"20161104001","SenderName":"中國人壽保險股份有限公司(宜昌)","ReceiverAddress":"","MessageDateTime":"","CorrelationId":"5919e086779a40bb3bcd89d5c27eb0373f33a180","MessageId":"201611210001","SenderAddress":"","SenderCode":"UNCL","TotalRecord":"","TransRefGUID":"201611210001","ReceiverName":"天津社保局"}}}