一次获取soapenv:Header请求中的内容的辛酸经历
写给那些不是很懂webservice请求和http请求的兄dei们
前言
提示:一次涉及接口服务端编写的辛酸历程:
由于开发需要,在springboot项目中我们要写一个webservice请求的服务端,供别人调用。于是我们做出了许多尝试。
提示:以下是本篇文章正文内容,下面案例可供参考
一、webservice是什么?
我通过网上参考别人对webservice接口的表述,理解为是一种不与平台和开发语言相关的一种数据传输方式。webservice请求是以xml文档形式进行发送请求数据,向webservice客户端提供可供调用相关接口方法的API文档。前些年使用的人比较多,现在的新项目使用的相对以前比较少了,所以现在开发webservice请求服务还需要提前做做相关功课。
二、soap协议是什么
soap协议是一种应用程序之间的基于XML的通信协议,与平台和语言无关,常用于webservice请求中进行网络数据通信传输数据。下面举个代码例子
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<test>
<m:nodetest>DEMO</m:nodetest>
</test>
</soap:Body>
</soap:Envelope>
三、项目开发历程
最开始产品经理给了我一份Word开发文档,我以为我按照开发文档来应该没什么大问题,我太怜了(弱小无助又可怜),来看请求报文格式
<?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:Header>
<Esb soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0">
<Route>
<TransId></TransId>
<Version/>
<AuthCode/>
<AuthType/>
<CarryType></CarryType>
<ServTestFlag></ServTestFlag>
<EsbId></EsbId></Route>
<traceId></traceId>
<sampledFlag>1</sampledFlag>
<debugFlag>1</debugFlag>
</Esb>
</soapenv:Header>
<soapenv:Body>
<handler xmlns="http://service.ispp.ztesoft.com/">
<infType xmlns="">GroupActiveTask</infType>
<inXML xmlns=""><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<RequestMsg>
……………………
</RequestMsg>]]>
</inXML>
</handler>
</soapenv:Body>
</soapenv:Envelope>
我一看,呦,这不是webservice请求嘛,好家伙,我没有大意啊,我于是啪又开打了开发文档,我一看
好家伙,我没有闪,这一个webservice撞我脸,这产品经理真讲无得,我给他赶忙送几瓶耗子尾汁。于是我开始干活了,代码如下:
1.接收webservice请求的接口
GroupActiveTaskWebService.java
package usi.eip.sys.cxf;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* @Classname GroupActiveTaskService
* @Description TODO
* @Date 2020/12/9 16:17
*/
@WebService(name = "GroupActiveTask", targetNamespace = "http://service.test.testaaa.com/")
public interface GroupActiveTaskWebService {
/**
* @param infType
* @param inXML
* @return returns java.lang.String
*/
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "handler", targetNamespace = "http://service.test.testaaa.com/", className = "usi.eip.sys.cxf.Handler")
@ResponseWrapper(localName = "handlerResponse", targetNamespace = "http://service.test.testaaa.com/", className = "usi.eip.sys.cxf.HandlerResponse")
public String groupActiveTask(@WebParam(name = "infType") String infType,
@WebParam(name = "inXML") String inXML);
}
2.接收webservice请求的接口的实现类
GroupActiveTaskWebServiceImpl.java
/**
* webService接口实现
*
*/
@WebService(serviceName = "GroupActiveTask", targetNamespace = "http://service.test.testaaa.com/",
endpointInterface = "cxf.GroupActiveTaskWebService")
public class GroupActiveTaskWebServiceImpl implements GroupActiveTaskWebService {
// 打印日志
private static final Logger LOGGER = LoggerFactory.getLogger(GroupActiveTaskWebServiceImpl.class);
public String groupActiveTask(String infType, String inXML) {
Document crmDoc = null;
Document resaleDoc = null ;
String response = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<ResponseMsg>\n" +
"\t<RetCode>1</RetCode>\n" +
"</ResponseMsg>";
try {
resaleDoc = DocumentHelper.parseText(inXML);
} catch (DocumentException e) {
return response;
}
//获取报文处理结果信息
String accNbr;
String custOrderId;
String catChannel;
String subCatChannel;
String serviceId;
String sysId;
try {
accNbr = IOMUtils.getNodeValue(resaleDoc,"RequestMsg/PubicVarList/AccNbr");
custOrderId = IOMUtils.getNodeValue(resaleDoc,"RequestMsg/BusinessInfo/CustOrderId");
catChannel = IOMUtils.getNodeValue(resaleDoc,"RequestMsg/BusinessInfo/CatChannel");
subCatChannel = IOMUtils.getNodeValue(resaleDoc,"RequestMsg/BusinessInfo/SubCatChannel");
serviceId = IOMUtils.getNodeValue(resaleDoc,"RequestMsg/OperatMaintenance/ServiceId");
sysId = IOMUtils.getNodeValue(resaleDoc,"RequestMsg/SysId");
}catch (Exception e){
LOGGER.info("获取节点值异常:",e);
return response;
}
String resultCode = "0"; //消息分析结果:0、成功,1、失败(抛出异常)
//返回结果
response = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"\t<ResponseMsg>\n" +
"\t\t<AccNbr>"+accNbr+"</AccNbr>\n" +
"\t\t<CustOrderId>"+custOrderId+"</CustOrderId>\n" +
"\t\t<CatChannel>"+catChannel+"</CatChannel>\n" +
"\t\t<SubCatChannel>"+subCatChannel+"</SubCatChannel>\n" +
"\t\t<ServiceId>"+serviceId+"</ServiceId>\n" +
"\t\t<RetCode>"+resultCode+"</RetCode>\n" +
"\t</ResponseMsg>";
return response;
}
}
3.用于接收请求参数封装的实体类
Handler .java
package usi.eip.sys.cxf;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
/**
* <p>
* Java class for handler complex type.
*
* <p>
* The following schema fragment specifies the expected content contained within
* this class.
*
* <pre>
* <complexType name="handler">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="IsapCopmletionType" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="inXML" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "handler", propOrder = { "infType", "inXML" })
public class Handler {
protected String infType;
protected String inXML;
/**
* Gets the value of the isapCopmletionType property.
*
* @return possible object is {@link String }
*
*/
public String getInfType() {
return infType;
}
/**
* Sets the value of the isapCopmletionType property.
*
* @param value
* allowed object is {@link String }
*
*/
public void setInfType(String value) {
this.infType = value;
}
/**
* Gets the value of the inXML property.
*
* @return possible object is {@link String }
*
*/
public String getInXML() {
return inXML;
}
/**
* Sets the value of the inXML property.
*
* @param value
* allowed object is {@link String }
*
*/
public void setInXML(String value) {
this.inXML = value;
}
}
4.相应请求封装的实体类
HandlerResponse .java
package usi.eip.sys.cxf;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>
* Java class for handlerResponse complex type.
*
* <p>
* The following schema fragment specifies the expected content contained within
* this class.
*
* <pre>
* <complexType name="handlerResponse">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="return" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "handlerResponse", propOrder = { "_return" })
public class HandlerResponse {
@XmlElement(name = "return")
protected String _return;
/**
* Gets the value of the return property.
*
* @return possible object is {@link String }
*
*/
public String getReturn() {
return _return;
}
/**
* Sets the value of the return property.
*
* @param value
* allowed object is {@link String }
*
*/
public void setReturn(String value) {
this._return = value;
}
}
5.创建webservice服务地址供客户端调用
WebServiceConfig.java
/**
* webService 配置类
*
*/
@Configuration
public class WebServiceConfig {
@Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), webServices());
// 接口发布
endpoint.publish("/Services");
return endpoint;
}
@Bean
public GroupActiveTaskWebService groupActiveTaskWebService() {
return new GroupActiveTaskWebServiceImpl();
}
@Bean
public WebServices webServices() {
return new WebServicesImpl();
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
}
开发到这,客户端的请求服务端已经能收到正确的报文了,可是后来产品经理又提了新需求,就是要获取请求中的soapenv:Header里的节点的值。这不是简单嘛,我于是上网各种百度,CSDN,我大意了啊,找了整整两天…没找到这样写的。喊上项目经理一起找资料,,,,,又过去了一天,,,还是没有相关介绍,到这我知道事情肯定没有那么简单了。
最后又过了两天,我偶然看到在项目里别人的代码写的这种请求竟然用了HttpPost发请求。。。他竟然用了HttpPost我真是十万个小马在我内心奔腾。我接着百度搜了一下,说soap只是协议,在http请求中也可以使用此协议。我于是做了一个大胆的决定,用Http服务端接收这个客户端来的不知道什么玩意的请求,直接发到测试环境开测。事实证明,我赌对了,原本一筹莫展的功能摇身一变接收到了所有的报文,我直接一个split三下五除二拿出了所有需要的节点值。至此,我只能感叹一句,开发需求不对接明确就是在间接谋杀程序猿。。还有一句,到一筹莫展的时候不妨坐下歇歇,可能回头看一眼就望见了希望在向你招手。
总结
对待webservice请求和http请求的功能需求,一定要明确开发需求。要是实在无法实现功能,就要怀疑你的开发文档是不是一个假的开发文档了。