最近学习做Webservice项目,模仿物流发货,A公司每向B公司一车货,发2次消息,分A出发时和到达B时,2消息内容相同。消息包含车号、司机、货物清单及可能是集装箱等。wsdl文件:
用wsimport生成相应的类,主要的是接口LGSService,
@WebService(name = "LGSService", targetNamespace = "http://hjs.com/services/atob/lgsservice/v1.0/")
@XmlSeeAlso({
com.hjs.schema.atob.logistics.ObjectFactory.class,
com.hjs.schema.atob.common.ObjectFactory.class
})
public interface LGSService {
@WebMethod(operationName = "CargoArrival", action = "http://hjs.com/services/atob/lgsservice/v1.0/CargoArrival")
@RequestWrapper(localName = "CargoArrival", targetNamespace = "http://hjs.com/schema/atob/logistics/", className = "com.hjs.schema.atob.logistics.CargoArrival")
@ResponseWrapper(localName = "ResponseMessage", targetNamespace = "http://hjs.com/schema/atob/common/", className = "com.hjs.schema.atob.common.ResponseMessageType")
public void cargoArrival(
@WebParam(name = "Head", targetNamespace = "http://hjs.com/schema/atob/logistics/")
com.hjs.schema.atob.logistics.BaseMessageType.Head head,
@WebParam(name = "LGS", targetNamespace = "http://hjs.com/schema/atob/logistics/")
List lgs,
@WebParam(name = "REFF_NO", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder reffNO,
@WebParam(name = "SENDER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder sender,
@WebParam(name = "RECEIVER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder receiver,
@WebParam(name = "RECEIVED_DTTM", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder receivedDTTM,
@WebParam(name = "ACKNSTAT", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder acknstat,
@WebParam(name = "ACKNREMARK", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder acknremark);
@WebMethod(operationName = "CargoPreannounce", action = "http://hjs.com/services/atob/lgsservice/v1.0/CargoPreannounce")
@RequestWrapper(localName = "CargoPreannounce", targetNamespace = "http://hjs.com/schema/atob/logistics/", className = "com.hjs.schema.atob.logistics.CargoPreannounce")
@ResponseWrapper(localName = "ResponseMessage", targetNamespace = "http://hjs.com/schema/atob/common/", className = "com.hjs.schema.atob.common.ResponseMessageType")
public void cargoPreannounce(
@WebParam(name = "Head", targetNamespace = "http://hjs.com/schema/atob/logistics/")
com.hjs.schema.atob.logistics.BaseMessageType.Head head,
@WebParam(name = "LGS", targetNamespace = "")
List lgs,
@WebParam(name = "REFF_NO", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder reffNO,
@WebParam(name = "SENDER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder sender,
@WebParam(name = "RECEIVER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder receiver,
@WebParam(name = "RECEIVED_DTTM", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder receivedDTTM,
@WebParam(name = "ACKNSTAT", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder acknstat,
@WebParam(name = "ACKNREMARK", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder acknremark);
}
再做一个类LGSServiceImpl实现此接口
@WebService(name = "LGSService", targetNamespace = "http://hjs.com/services/atob/lgsservice/v1.0/")
@BindingType(value = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class LGSServiceImpl implements LGSService {
@Override
public void cargoArrival(Head head, List lgs, Holder reffNO, Holder sender,
Holder receiver, Holder receivedDTTM, Holder acknstat,
Holder acknremark) {
// 代码省略。。。
}
@Override
public void cargoPreannounce(Head head, List lgs, Holder reffNO, Holder sender,
Holder receiver, Holder receivedDTTM, Holder acknstat,
Holder acknremark) {
// 代码省略。。。
}
}
发布此服务
LGSService ls = new LGSServiceImpl();
Endpoint.publish("http://localhost:8090/services/atob/lgsservice/v1.0/", ls);
可以正常发布,打开http://localhost:8090/services/atob/lgsservice/v1.0/?wsdl,可以看到wsdl,但那是系统生成的,看起来别扭,也不方便客户端查看。
为了能让客户端查看原装的wsdl和其它schema,可以以META-DATA方式发布,如
LGSService ls = new LGSServiceImpl();
Endpoint lgsendpoint = Endpoint.create(ls);
List metadataFile = new ArrayList();
metadataFile.add( new File("src/META-INF/wsdl/LGSService.wsdl"));
metadataFile.add( new File("src/META-INF/wsdl/BaseMessage.xsd"));
metadataFile.add( new File("src/META-INF/wsdl/ABAWBS.xsd"));
metadataFile.add( new File("src/META-INF/wsdl/CONTAINER.xsd"));
metadataFile.add( new File("src/META-INF/wsdl/ABLGS.xsd"));
metadataFile.add( new File("src/META-INF/wsdl/ResponseMessage.xsd"));
List metadata = new ArrayList();
try {
for(File file : metadataFile){
Source source = new StreamSource(new FileInputStream(file));
source.setSystemId(file.toURI().toURL().toExternalForm());
metadata.add(source);
}
lgsendpoint.setMetadata(metadata);
lgsendpoint.publish("http://localhost:8090/services/atob/lgsservice/v1.0/");
} catch (FileNotFoundException | MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
不能成功发布,系统报错:
服务器运行时错误: More than one schema for the target namespace http://hjs.com/schema/atob/logistics/
想了好久,什么问题?查看JAX-WS文档及网上资料,感觉是系统无法辨别是生成的wsdl和xsd还是原装META的,应该在类上指定,加上注释
serviceName = "LGSService", portName = "LGSServiceSOAP",
再发布,系统报:
Method cargoPreannounce is exposed as WebMethod,
but there is no corresponding wsdl operation with name {http://hjs.com/services/atob/lgsservice/v1.0/}cargoPreannounce in the wsdl:portType{http://hjs.com/services/atob/lgsservice/v1.0/}LGSService
原来是方法上没有加注释,那就加上吧
@WebMethod(operationName = "CargoArrival", action = "http://hjs.com/services/atob/lgsservice/v1.0/CargoArrival")
@RequestWrapper(localName = "CargoArrival", targetNamespace = "http://hjs.com/schema/atob/logistics/", className = "com.hjs.schema.atob.logistics.CargoArrival")
@ResponseWrapper(localName = "ResponseMessage", targetNamespace = "http://hjs.com/schema/atob/common/", className = "com.hjs.schema.atob.common.ResponseMessageType")
再发布,还有错:
javax.xml.ws.WebServiceException: class com.hjs.schema.atob.logistics.CargoPreannounce do not have a property of the name arg0
再找资料,认为类内的方法参数与xsd不一致。参考接口方法的参数,全部复制到实现类里
public void cargoArrival(
@WebParam(name = "Head", targetNamespace = "http://hjs.com/schema/atob/logistics/")
com.hjs.schema.atob.logistics.BaseMessageType.Head head,
@WebParam(name = "LGS", targetNamespace = "http://hjs.com/schema/atob/logistics/")
List lgs,
@WebParam(name = "REFF_NO", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder reffNO,
@WebParam(name = "SENDER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder sender,
@WebParam(name = "RECEIVER", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder receiver,
@WebParam(name = "RECEIVED_DTTM", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder receivedDTTM,
@WebParam(name = "ACKNSTAT", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder acknstat,
@WebParam(name = "ACKNREMARK", targetNamespace = "http://hjs.com/schema/atob/common/", mode = WebParam.Mode.OUT)
Holder acknremark
) {
// 省略代码。。。
}
发布!OK啦!打开wsdl,与原装的一致。
分别打开每一个xsd,也与原装发布的一致。算是成功发布了吧。
总结:在写实现类时,要按JAX-WS的要求,或参考接口,分别加上相应的注释,不只是简单实现。