JaxWs基于消息编程
JaxWs 基于消息编程
2.1???? Source
2.2???? SOAPMessage
2.3???? DataSource
4.1???? Dispatch的三种请求方式
6.1???? MESSAGE和PAYLOAD的区别
import javax.xml.soap.SOAPMessage;import javax.xml.ws.Provider;import javax.xml.ws.Service.Mode;import javax.xml.ws.ServiceMode;import javax.xml.ws.WebServiceProvider; @WebServiceProvider(serviceName = "SOAPMessageService", portName = "SOAPMessagePort", targetNamespace = "http://provider.jaxws.sample.cxftest.tiantian.com/")@ServiceMode(Mode.MESSAGE)public class SOAPMessageModeProvider implements Provider<SOAPMessage> { public SOAPMessage invoke(SOAPMessage request) { SOAPMessage response = null; try { System.out.println("客户端以SOAPMessage通过MESSAGE Mode请求如下: "); request.writeTo(System.out); response = MessageUtil.getInstance().create(null, "/provider/SOAPMessageResp.xml"); } catch (Exception ex) { ex.printStackTrace(); } return response; } }
import java.io.IOException;import java.io.InputStream; import javax.xml.soap.MessageFactory;import javax.xml.soap.MimeHeaders;import javax.xml.soap.SOAPException;import javax.xml.soap.SOAPMessage; public class MessageUtil { private static MessageUtil instance = new MessageUtil(); private MessageFactory factory; private MessageUtil() { try { factory = MessageFactory.newInstance(); } catch (SOAPException e) { e.printStackTrace(); thrownew RuntimeException(e); } } public static MessageUtil getInstance() { returninstance; } /** * 创建一个默认的SOAPMessage * @return * @throws SOAPException */ public SOAPMessage create() throws SOAPException { returnfactory.createMessage(); } /** * 根据MimeHeaders和soap格式文件路径创建一个SOAPMessage * @param headers * @param filePath * @return * @throws IOException * @throws SOAPException */ public SOAPMessage create(MimeHeaders headers, String filePath) throws IOException, SOAPException { InputStream is = MessageUtil.class.getResourceAsStream(filePath); SOAPMessage message = factory.createMessage(headers, is); is.close(); return message; } /** * 获取MessageFactory * @return */ public MessageFactory getMessageFactory() { returnfactory; } }
<?xml version="1.0" encoding="utf-8" ?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns4:sayHiResponse xmlns:ns4="http://provider.jaxws.sample.cxftest.tiantian.com/"> <ns4:responseType>SOAPMessage Response</ns4:responseType> </ns4:sayHiResponse> </SOAP-ENV:Body></SOAP-ENV:Envelope>
Object service = new SOAPMessageModeProvider(); Endpoint.publish("http://localhost:8080/test/jaxws/services/SOAPMessage", service);
public <T> Dispatch<T> createDispatch(QName portName, Class<T> type, Mode mode)
public static void main(String args[]) throws Exception { //定义serviceName对应的QName,第一个参数是对应的namespace QName serviceName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "SOAPMessageService"); //定义portName对应的QName QName portName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "SOAPMessagePort"); //使用serviceName创建一个Service对象,该对象还不能直接跟WebService对象进行交互 Service service = Service.create(serviceName); //创建一个port,并指定WebService的地址,指定地址后我们就可以创建Dispatch了。 service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, "http://localhost:8080/test/jaxws/services/SOAPMessage"); //创建一个Dispatch对象 Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Mode.MESSAGE); //创建一个SOAPMessage SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml"); //调用Dispatch的invoke方法,发送一个SOAPMessage请求,并返回一个SOAPMessage响应。 SOAPMessage response = dispatch.invoke(request); System.out.println("服务端返回如下: "); response.writeTo(System.out); }
//指定wsdl文件的位置 URL wsdl = new URL("http://localhost:8080/test/jaxws/services/SOAPMessage?wsdl"); Service service = Service.create(wsdl, serviceName);
<?xml version="1.0" encoding="utf-8" ?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns4:sayHi xmlns:ns4="http://provider.jaxws.sample.cxftest.tiantian.com/"> <ns4:requestType>SOAPMessage Request</ns4:requestType> </ns4:sayHi> </SOAP-ENV:Body></SOAP-ENV:Envelope>
public Response<T> invokeAsync(T msg); public Future<?> invokeAsync(T msg, AsyncHandler<T> handler);
SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml"); Response<SOAPMessage> response = dispatch.invokeAsync(request); System.out.println("开始判断调用是否已完成"); while (!response.isDone()) { Thread.sleep(200l); } SOAPMessage responseMsg = null; try { responseMsg = response.get(); } catch (Exception e) { System.out.println("调用失败"); } if (responseMsg != null) { System.out.println("服务端返回如下: "); responseMsg.writeTo(System.out); }
SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml"); Future<?> future = dispatch.invokeAsync(request, new AsyncHandler<SOAPMessage>() { @Override public void handleResponse(Response<SOAPMessage> res) { try { System.out.println("回调函数被调用了……"); SOAPMessage responseMsg = res.get(); responseMsg.writeTo(System.out); } catch (Exception e) { e.printStackTrace(); } } }); System.out.println("可以开始做其他事情了……"); while (!future.isDone()) { System.out.println("在请求完成之前,整个程序不能结束,否则回调函数不会被调用"); Thread.sleep(200l); }
SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml"); dispatch.invokeOneWay(request);
@WebServiceProvider(serviceName="UniteService", portName="UniteServicePort", targetNamespace="http://provider.jaxws.sample.cxftest.tiantian.com/")@ServiceMode(Service.Mode.MESSAGE)@BindingType(HTTPBinding.HTTP_BINDING)public class UniteServiceProvider implements Provider<DOMSource> { @Override public DOMSource invoke(DOMSource request) { DOMSource response = null; MessageUtil.getInstance().printSource(request); Document requestDoc = (Document)request.getNode(); Element commandEle = (Element)requestDoc.getElementsByTagName("command").item(0); Element paramEle = (Element)requestDoc.getElementsByTagName("param").item(0); String command = commandEle.getTextContent(); try { response = this.getResponse(command, paramEle); } catch (Exception e) { e.printStackTrace(); } MessageUtil.getInstance().printSource(response); return response; } /** * 根据指令和对应的参数进行相关操作并返回对应的操作结果 * @param command * @param paramEle * @return * @throws Exception */ private DOMSource getResponse(String command, Element paramEle) throws Exception { String responseContent = "<response><product><id>1</id><name>Apple</name></product></response>"; InputStream is = new ByteArrayInputStream(responseContent.getBytes("UTF-8")); Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is); DOMSource response = new DOMSource(doc); return response; } }
/** * 输出Source的内容 * @param source */ public void printSource(Source source) { StreamResult result = new StreamResult(System.out); try { TransformerFactory.newInstance().newTransformer().transform(source, result); System.out.println(); } catch (Exception e) { e.printStackTrace(); } }
public class UniteServiceClient { public static void main(String args[]) throws Exception { String requestContent = "<request><command>10001</command><parameter><id>1</id></parameter></request>"; InputStream is = new ByteArrayInputStream(requestContent.getBytes("UTF-8")); Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is); DOMSource requestMsg = new DOMSource(doc); MessageUtil.getInstance().printSource(requestMsg); QName serviceName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "UniteService"); QName portName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "UniteServicePort"); Service service = Service.create(serviceName); //指定绑定方式为HTTPBinding service.addPort(portName, HTTPBinding.HTTP_BINDING, "http://localhost:8080/test/jaxws/services/UniteService"); Dispatch<DOMSource> dispatch = service.createDispatch(portName, DOMSource.class, Mode.MESSAGE); DOMSource responseMsg = dispatch.invoke(requestMsg); System.out.println("服务端返回来的信息是:"); MessageUtil.getInstance().printSource(responseMsg); } }
public DOMSource invoke(DOMSource request) { SOAPPart soapPart = (SOAPPart) request.getNode(); try { SOAPEnvelope soapEnvelop= soapPart.getEnvelope(); SOAPBody soapBody = soapEnvelop.getBody(); Document preDoc = soapBody.extractContentAsDocument(); } catch (SOAPException e1) { e1.printStackTrace(); } returnnull; }
?
?????? 如果DOMSource本身持有的Document对象就是一个SOAPPart的话就可以直接发送了,不需要再做转换了。当我们的DOMSource持有的不是一个SOAPPart时,系统在生成SOAPPart时很可能会抛出异常信息:HIERARCHY_REQUEST_ERR: 尝试在不允许的位置插入节点。所以当我们配合使用SOAPBinding、DOMSource消息对象和MESSAGE模式时,我们最好给DOMSource传入一个SOAPPart对象或者是SOAPPart格式的Document对象。
?
PAYLOAD模式
?? 使用PAYLOAD模式时,我们发送的DOMSource消息会直接发送过去。对方接收到的内容和发送时的内容是一样的,注意只是内容是一样的,其持有的Document对象还是会当做一个普通的Document对象处理,如DocumentImpl。比如发送的时候DOMSource持有的是一个SOAPPart,那么接收的时候接收到的DOMSource里面的Document的内容还是发送时SOAPPart的内容,但是对象却是一个普通的Document对象,而不是发送时的SOAPPart对象;而如果发送的时候发送的是一个普通的Document对象,那么接收到的内容也只是一个普通Document的内容,不会像MESSAGE模式那样会有多余的SOAPHeader等信息。
?