【参考: 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());