【参考: http://cxf.apache.org/docs/jax-ws-dispatch-api.html 】
【参考: http://cxf.apache.org/docs/provider-services.html 】
除了第一节介绍的jax-ws的方式和第二节介绍的simple的方式,CXF也支持Provide-Dispatch的请求-服务的方式。
和前两节每个operation有一个对应的method响应的方式不同,P-D模式是把整个请求信息做为处理对象来响应的,提供服务的类需要添加@WebServiceProvider注释,并实现javax.xml.ws.Provider<T>接口,支持MESSAGE和PAYLOAD两种服务模式,T类型有以下选项:
- javax.xml.transform.Source: DOMSource or SAXSource or StreamSource
- javax.xml.soap.SOAPMessage: SOAP + MESSAGE
- javax.activation.DataSource : HTTP + MESSAGE
用P-D模式,就不需要有Service接口定义了。
一、Provider的实现
@WebServiceProvider(wsdlLocation = "DemoProvider.wsdl") //specify wsdl path
@ServiceMode(value = Mode.MESSAGE) //specify service mode
public class OrderProcessDomProvider implements Provider<DOMSource> {
@Resource
WebServiceContext context; //inject context
public DOMSource invoke(DOMSource request) {
try {
System.out.println(context.getMessageContext().get(Message.WSDL_OPERATION)); //get request operation
//get request
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
message.getSOAPPart().setContent(request);
message.writeTo(System.out);
//construct response
SOAPMessage response = factory.createMessage();
SOAPElement bodyElement = response.getSOAPBody().addChildElement(new QName("<namespace>", "<responseElement>", "<localpart>"));
SOAPElement outElement = bodyElement.addChildElement("<reponseChildElement");
outElement.setTextContent("output");
DOMSource domSource = new DOMSource();
domSource.setNode(response.getSOAPPart());
return domSource;
} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
上示代码中,注入了WebServiceContext用于访问与请求相关的各种信息,例如operation name,然后打印了请求信息,接下来根据wsdl中response schema的信息构造返回结果。注意这里的DomSource即是请求信息格式,也是返回信息格式。
二、Dispatch端
和Provider端类,在Dispatch端需要根据request schema的结构构造请求信息内容,然后使用Dispatch将信息发送:
URL wsdlURL = new URL("DemoProvider.wsdl");
Service service = Service.create(wsdlURL, new QName(
"<namespace>", "<serviceName>"));
Dispatch<DOMSource> dispatch = service.createDispatch(new QName(
"<namespace>", "<portName>"),
DOMSource.class, Service.Mode.MESSAGE);
//set endpoint address
dispatch.getRequestContext().put(Dispatch.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8090/orderProcessProvider");
//create request message
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage soapMessage = factory.createMessage();
SOAPBody soapBody = soapMessage.getSOAPBody();
SOAPElement requestElement = soapBody.addChildElement(new QName(
"<namespace>",
"<requestElement>", "<localpart>"));
SOAPElement inElement = requestElement.addChildElement(new QName("<child>"));
inElement.setTextContent("Input");
DOMSource source = new DOMSource();
source.setNode(soapMessage.getSOAPPart());
//invoke
DOMSource result = dispatch.invoke(source);
//show result
SOAPMessage responseMsg = factory.createMessage();
responseMsg.getSOAPPart().setContent(result);
responseMsg.writeTo(System.out);
三、启动服务
Endpoint.publish("http://localhost:8090/orderProcessProvider",
new OrderProcessDomProvider());