最近项目需要调用外部webservice接口,之前没接触过,研究了2天做个笔记:

1、首先发送请求,格式接口那边已经提供了,期间遇到的问题就是提示“no SOAPAction header” 的错误,请求代码如下:

/**
     * 根据参数拼接后发生soap请求
     * @param params
     * @return
     * @throws Exception
     */
    public static String SoapRequest(Map<String,Object> params)throws Exception{
        String sendMsg = "";
        String resultStr = "";
        String url = MapUtil.getStrValue(params,"url");
        if(StringUtil.isEmpty(url)){
            return "";
        }
        //定义HttpClient
        HttpClient client = new HttpClient();
        PostMethod postMethod = new PostMethod(url);
        try {
            Map<String,Object> reqMap = new HashMap<>();
            reqMap.put("reqCode",MapUtil.getStrValue(params,"reqCode"));
            reqMap.put("offerId",MapUtil.getStrValue(params,"offerId"));
            reqMap.put("srvModule",MapUtil.getStrValue(params,"srvModule"));
            //这里是项目写了个工具类拼接请求xml报文
            sendMsg = XmlConverterUtil.createXmlFromTemplate(reqMap);
            // 然后把Soap请求数据添加到PostMethod中
            RequestEntity requestEntity = new StringRequestEntity(sendMsg, "text/xml", "UTF-8");
            //设置请求头部,否则可能会报 “no SOAPAction header” 的错误
            postMethod.setRequestHeader("SOAPAction","");
            postMethod.setRequestHeader("Content-Types","text/xml");
            // 设置请求体
            postMethod.setRequestEntity(requestEntity);
            int status = client.executeMethod(postMethod);
            // 打印请求状态码
            System.out.println("status:" + status);
            // 获取响应体输入流
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(postMethod.getResponseBodyAsStream(),"UTF-8"));
            resultStr = IOUtils.toString(in);
            // 获取请求结果字符串并转换格式,这里一开始有遇到字符转换问题,后面方法可以解决,可
          //以不使用
            /*resultStr = resultStr.replaceAll("&", "&");
            resultStr = resultStr.replaceAll("<", "<").replaceAll(">", ">");
            resultStr = resultStr.replaceAll(""", "\"");
            resultStr = (String) XmlConverterUtil.decodeStr(resultStr);*/
        }catch (Exception e){
            e.printStackTrace();
        }
        return resultStr;
    }

2、根据返回的xml报文解析,转成java对象,先看下返回的格式:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:callWebServiceResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://hnlocal.webservice.bsn.ztesoft.com   ">
            <callWebServiceReturn href="#id0"/>
        </ns1:callWebServiceResponse>
        <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:RespMessage" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://model.webservice.bsn.ztesoft.com">
            <content xsi:type="xsd:string">
<?xml version="1.0" encoding="UTF-8"?>
<CommissionOrderRespType xmlns:xml="http://www.w3.org/XML/1998/namespace"><Alllist><OfferId>200000573</OfferId><OfferName>产品发展类-乐享4G单产品C</OfferName><EffDate>2014-05-04 10:24:24.0</EffDate><PricingSectionName>销售品类型 in 乐享4G套餐</PricingSectionName><RefObjectName>当前销售品类型</RefObjectName><OperatorName>必须订购</OperatorName><AcctItemTypeId>100000038</AcctItemTypeId><name>天翼-首返</name></Alllist><Alllist><OfferId>200000639</OfferId><OfferName>集约化_金昌_4G_19-999元天翼产品</OfferName><EffDate>2014-05-11 17:31:09.0</EffDate><PricingSectionName>零费用周期性事件生成</PricingSectionName><RefObjectName>当前销售品类型</RefObjectName><OperatorName>必须订购</OperatorName><AcctItemTypeId>100000038</AcctItemTypeId><name>天翼-首返</name></Alllist>
</content>
            <respCode xsi:type="xsd:string">0</respCode>
            <srvFunction xsi:type="xsd:string">query</srvFunction>
            <srvModule xsi:type="xsd:string">CommissionOrderQuery</srvModule>
        </multiRef>
    </soapenv:Body>
</soapenv:Envelope>

上面的报文可以分成两部分,一部分是soap的返回头参数,中间content中的是结果xml,我们主要是要将content里面的内容转成java对象集合,先看下content里面的内容

java soap xml格式参数_解析xml

 先上获取到content这部分xml内容的代码:

/**
     * 
     * @param soapXml 请求结果string
     * @param c   要转换成的java对象
     * @param <T>
     * @return
     */
public static <T> T soapXmlToBean(String soapXml,Class<T> c){
        Iterator<SOAPElement> iterator = null;
        T t = null;
        try {
            //javax.xml.soap类MessageFactory
            MessageFactory msgFactory = MessageFactory.newInstance();
            //创建一个soapmessage对象
            SOAPMessage reqMsg = msgFactory.createMessage(new MimeHeaders(),
                    new ByteArrayInputStream(soapXml.getBytes("UTF-8")));
            reqMsg.saveChanges();
            //取出soapBoby对象
            SOAPBody body = reqMsg.getSOAPBody();
            遍历子节点
            iterator = body.getChildElements();
        }catch (Exception e){
            e.printStackTrace();
        }
        while (iterator.hasNext()) {
            SOAPElement element = iterator.next();
            logger.info("节点名称---:"+element.getNodeName());
            if("multiRef".equals(element.getNodeName())){
                Iterator<SOAPElement> it = element.getChildElements();
                SOAPElement el = null;
                while (it.hasNext()) {
                    el = it.next();
                    //取到content子节点的值
                    if ("content".equals(el.getNodeName())) {
                        logger.info("子节点值---:"+el.getValue());
                        //这里是调用工具来将content中的xml转换成java对象
                        t = XmlConverterUtil.analyzeXmlToBean(el.getValue(),c);
                        break;
                    }
                }
                break;
            }
        }
        return t;
    }

3、将xml转换成java对象集合,利用JAXBContext将xml解析成java对象集合,思路就是把xml当做一个list<T> ,定义一个存list的对象,然后再定义一个T对象,然后通过JAXBContext进行解析:

@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "CommissionOrderRespType")//根路径
public class CommissionContentResp extends ArrayList<CommissionResp> implements Serializable {
    private static final long serialVersionUID = 1L;

    @XmlElement(name="Alllist")//子节点名称
    public List<CommissionResp> getList(){
        return  this;
    }


}
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Alllist")//根路径
public class CommissionResp implements Serializable {
    private static final long serialVersionUID = 1L;
    @XmlElement(name="OfferId")
    private String offerId; 
    @XmlElement(name="OfferName")
    private String offerName;//
    @XmlElement(name="EffDate")
    private String effDate;
    @XmlElement(name="PricingSectionName")
    private String pricingSectionName;
    @XmlElement(name="RefObjectName")
    private String refObjectName;
    @XmlElement(name="OperatorName")
    private String operatorName;
    @XmlElement(name="AcctItemTypeId")
    private String acctItemTypeId;
    @XmlElement(name="name")
    private String name;

}
/**
     * 解析返回报文,返回对象
     * */

    public static <T> T analyzeXmlToBean(String xmlStr, Class<T> c){
        T t = null;
        try {
            JAXBContext context = JAXBContext.newInstance(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            t = (T) unmarshaller.unmarshal(new StringReader(xmlStr));
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return t;
    }

 最后传入content里面的xml内容和CommissionContentResp对象就能解析出结果List<T>  ,希望能帮到大家 喜欢的点个赞~

补充:

返回报文含有集合加单个对象,可以这样定义:

@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ShareMsgQueryRespType")
public class ShareMsgResp extends ArrayList<SourseAcctItem> implements Serializable {
    private static final long serialVersionUID = 1L;
    //private List<SourseAcctItem> newlist;

    @XmlElement(name="Newlist")
    private List<SourseAcctItem> newlist;
    @XmlElement(name="Alllist")
    private ShareContent alllist;

}

返回参数:

<?xml version="1.0" encoding="UTF-8"?>
<ShareMsgQueryRespType>
	<Newlist>
		<SourseAcctItemTypeId>602040</SourseAcctItemTypeId>
		<SourseAcctItemTypeName>其它补退费</SourseAcctItemTypeName>
	</Newlist>
	<Newlist>
		<SourseAcctItemTypeId>611162</SourseAcctItemTypeId>
		<SourseAcctItemTypeName>天翼大流量套餐功能费</SourseAcctItemTypeName>
	</Newlist>
	<Alllist>
		<ProductId>900000001</ProductId>
		<ProductName>移动电话</ProductName>
		<AcctItemTypeId>108021</AcctItemTypeId>
		<Name>来电显示 (移动业务)</Name>
		<FairValue>5.00000</FairValue>
	</Alllist>
</ShareMsgQueryRespType>