最近在解决一个设备强制校时(对设备时间不准的问题进行校时)的一个任务,该任务设计到一个调用C++写的一个校时服务,需要在java的程序中进行调用,因为以前没有做过到调用外部服务的,所以查了很多资料,终于解决了,记录一下。顺带给有需要的朋友一点帮助。
我拿到一个服务后,如下图:
(1)、打开ns.wsdl文件,看到如下(具体不用看,只看最下面几行就好)
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Service"
targetNamespace="http://tempuri.org/ns.xsd/Service.wsdl"
xmlns:tns="http://tempuri.org/ns.xsd/Service.wsdl"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
.......
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="http://tempuri.org/ns.xsd"
................
attributeFormDefault="unqualified">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<!-- operation request element -->
<element name="Calibration">
<complexType>
<sequence>
<element name="Factory-code" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- ns__Calibration::Factory_code -->
<element name="strIP" type="xsd:string" minOccurs="0" maxOccurs="1"/><!-- ns__Calibration::strIP -->
<element name="nPort" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- ns__Calibration::nPort -->
<element name="strUserName" type="xsd:string" minOccurs="0" maxOccurs="1"/><!-- ns__Calibration::strUserName -->
<element name="strPasswd" type="xsd:string" minOccurs="0" maxOccurs="1"/><!-- ns__Calibration::strPasswd -->
</sequence>
</complexType>
</element>
...........
</schema>
</types>
<message name="CalibrationRequest">
<part name="Body" element="ns:Calibration"/><!-- ns__Calibration::ns__Calibration -->
</message>
..........
<service name="Service">
<documentation>gSOAP 2.8.39 generated service definition</documentation>
<port name="Service" binding="tns:Service">
<SOAP:address location="http://localhost:8080"/>
</port>
</service>
</definitions>
(2)、启动服务(就是.exe文件)
(3)、访问我标注的地址在后面添加/?wsdl。如: http://localhost:8080/?wsdl去在浏览器上看这个地址的内容,具体格式可以看网上查询号码的webService的wsdl文件http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl。如果可以显示的这样格式的内容的话,然后再在soapUI软件访问
(4)、点击ok后,在左侧会多一个项目,双击你要的调用的方法,会打开一个窗口,你把?替换成你要传个服务接口的参数
(5)、点击左上角的运行按钮运行,如果右侧可以出来结果,这接口可以进行交互。
然后在java后台开始写接口了。我是写在controller层的,前端点击按钮后去调用这个方法,进行服务接口的访问。
/**
* 强制校时
*
* @param request
* @param response
* @return
* @throws JsonProcessingException
*/
@RequestMapping(params = "act=compulsorySchoolTimeThree", method = {RequestMethod.POST, RequestMethod.GET})
public Map<String, Object> compulsorySchoolTimeThree(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> resultMap = null;
String URL = "http://localhost:8080";
try {
String urlStr = URL;
java.net.URL url = new URL(urlStr);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
OutputStream oStream = con.getOutputStream();
//下面这行代码是用字符串拼出要发送的xml,xml的内容是从测试软件里拷贝出来的
//需要注意的是,有些空格不要弄丢哦,要不然会报500错误的。
//参数什么的,你可以封装一下方法,自动生成对应的xml脚本
String soap = strSoap(498, "120.114.3.211",2043,"dsfdsf","sdfsfd");
oStream.write(soap.getBytes());
oStream.close();
InputStream iStream = con.getInputStream();
Reader reader = new InputStreamReader(iStream);
int tempChar;
String str = new String();
while ((tempChar = reader.read()) != -1) {
str += (char) tempChar;
}
//下面这行输出返回的xml到控制台,相关的解析操作大家自己动手喽。
//如果想要简单的话,也可以用正则表达式取结果出来。
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>returnedxmlstr:" + str);
iStream.close();
oStream.close();
con.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return resultMap;
}
public static String strSoap(int factoryCode, String strIp, int nPort, String strUserName,String strPasswd){
String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns=\"http://tempuri.org/ns.xsd\"> " +
" <soapenv:Header/> " +
" <soapenv:Body> " +
" <ns:Calibration> " +
" <Factory-code>"+ factoryCode +"</Factory-code> " +
" <!--Optional:--> " +
" <strIP>"+ strIp +"</strIP> " +
" <nPort>"+ nPort +"</nPort> " +
" <!--Optional:--> " +
" <strUserName>"+ strUserName +"</strUserName> " +
" <!--Optional:--> " +
" <strPasswd>"+ strPasswd +"</strPasswd> " +
" <Factory-code>"+ factoryCode +"</Factory-code> " +*/
" </ns:Calibration> " +
" </soapenv:Body> " +
"</soapenv:Envelope>";
return soap;
}
这样访问就可以测试通了,本人已测试,ok如果有问题可以留言,我会尽可能帮助大家
下面也有两种通过RPC方式进行调用用的,但是不清楚为啥掉不同我的服务,但是调用晚上的服务是可以的,你们可以了解一下,也是一种调用方法
/** * 强制校时 * * @param request * @param response * @return * @throws JsonProcessingException */ @RequestMapping(params = "act=compulsorySchoolTime", method = { RequestMethod.POST, RequestMethod.GET }) public Map<String, Object> compulsorySchoolTime(HttpServletRequest request, HttpServletResponse response) { Map<String, Object> resultMap = null; try { // 使用RPC方式调用WebService RPCServiceClient serviceClient = new RPCServiceClient(); // 创建WSDL的URL,注意不是服务地址 String url = "http://localhost:8080"; // 指定调用WebService的URL EndpointReference targetEPR = new EndpointReference(url); Options options = serviceClient.getOptions(); // 确定目标服务地址 options.setTo(targetEPR); // 确定调用方法(wsdl 命名空间地址 (wsdl文档中的targetNamespace) 和 方法名称 的组合) options.setAction("http://localhost:8080/Calibration"); // 指定方法的参数值 Object[] parameters = new Object[] {498, "120.114.3.211",2043,"dsfdsf","sdfsfd"}; // 创建服务名称 // 1.namespaceURI - 命名空间地址 (wsdl文档中的targetNamespace) // 2.localPart - 服务视图名 (wsdl文档中operation的方法名称,例如<wsdl:operation name="getMobileCodeInfo">) QName qname = new QName("http://localhost:8080/", "Calibration"); // 调用方法一 传递参数,调用服务,获取服务返回结果集 OMElement element = serviceClient.invokeBlocking(qname, parameters); System.out.println(element); /* * 值得注意的是,返回结果就是一段由OMElement对象封装的xml字符串。 * 我们可以对之灵活应用,下面我取第一个元素值,并打印之。因为调用的方法返回一个结果 */ String result = element.getFirstElement().getText(); System.out.println(result); // 调用方法二 getPrice方法并输出该方法的返回值 // 指定方法返回值的数据类型的Class对象 Class[] returnTypes = new Class[] {String.class}; Object[] responseParam = serviceClient.invokeBlocking(qname, parameters, returnTypes); String r = (String) responseParam[0]; System.out.println(r); } catch (AxisFault e) { e.printStackTrace(); } return resultMap; } /** * 强制校时 * * @param request * @param response * @return * @throws JsonProcessingException */ @RequestMapping(params = "act=compulsorySchoolTimeTwo", method = { RequestMethod.POST, RequestMethod.GET }) public Map<String, Object> compulsorySchoolTimeTwo(HttpServletRequest request, HttpServletResponse response) { Map<String, Object> resultMap = null; try { ServiceClient serviceClient = new ServiceClient(); //创建服务地址WebService的URL,注意不是WSDL的URL String url = "http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx"; EndpointReference targetEPR = new EndpointReference(url); Options options = serviceClient.getOptions(); options.setTo(targetEPR); //确定调用方法(wsdl 命名空间地址 (wsdl文档中的targetNamespace) 和 方法名称 的组合) options.setAction("http://WebXml.com.cn/getMobileCodeInfo"); OMFactory fac = OMAbstractFactory.getOMFactory(); /* * 指定命名空间,参数: * uri--即为wsdl文档的targetNamespace,命名空间 * perfix--可不填 */ OMNamespace omNs = fac.createOMNamespace("http://WebXml.com.cn/", ""); // 指定方法 OMElement method = fac.createOMElement("getMobileCodeInfo", omNs); // 指定方法的参数 OMElement mobileCode = fac.createOMElement("mobileCode", omNs); mobileCode.setText("15932582632"); OMElement userID = fac.createOMElement("userID", omNs); userID.setText(""); method.addChild(mobileCode); method.addChild(userID); method.build(); //远程调用web服务 OMElement result = serviceClient.sendReceive(method); System.out.println(result); } catch (AxisFault axisFault) { axisFault.printStackTrace(); } return resultMap; }