基于SAAJ的客户端

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于SAAJ的客户端相关的知识,希望对你有一定的参考价值。

概述


SAAJ - SOAP with Attachments API for JAVA
结构图如下:
技术分享

正文


1. 如何获取soap请求的关键参数

关键的参数有四个:
  1. xmlns - xml命名空间
    如果你对命名空间没有概念,请参考:w3school - XML命名空间
  2. 服务的地址
  3. service的name
  4. port的name
 
获取:
  1. 在wsdl文档的root元素的targetNamespace可以获取到xmlns:
    技术分享
  2. 在service元素可以获取其他三个参数
    技术分享
    上图黄色高亮标注了三个地方,分别可以获得service的name,port的name,服务的地址。
    值得一说的是,这里的service的name和wsdl文档root元素的name是相同的,但这只是巧合;这里的才“真的是”,那里的只是“长得像”。

2. 参数声明

/** 服务的地址 */
private static final String ADDRESS = "http://localhost:6666/service/interpret";
/** 目标命名空间 */
private static final String TARGET_NAME_SPACE = "http://service.chapter1.jws.sand.ljl.cn/";
/** service的名称 */
private static final String SERVICE_NAME = "InterpretServiceImplService";
/** port的名称 */
private static final String PORT_NAME = "InterpretServiceImplPort";

 

3. 创建消息

/**
 * 创建并填充SOAP message.
 * @return
 * @throws SOAPException
 */
private SOAPMessage createMessage() throws SOAPException {
  // 1. 创建message
  SOAPMessage message = MessageFactory.newInstance().createMessage();
 
  // 2. 获取Envelope
  SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
 
  // 3. 获取body
  SOAPBody body = envelope.getBody();
 
  // 4. 构造interpret元素
  QName qname = new QName(TARGET_NAME_SPACE, "interpret", "ns");
 
  // 5. 向body中添加元素
  SOAPBodyElement bodyElement = body.addBodyElement(qname);
 
  // 6. 添加子元素
  bodyElement.addChildElement("num").setValue("112358");
 
  return message;
}

上述代码的创建结果:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header/>
<SOAP-ENV:Body>

关于QName

QName qname = new QName("http://service.chapter1.jws.sand.ljl.cn/", "interpret", "ns");

上述代码的三个参数,分别表示命名空间、本地名称、前缀。相当于创建了下述的xml元素:

<ns:interpret xmlns:ns="http://service.chapter1.jws.sand.ljl.cn/" />

关于打印SOAPMessage

使用javax.xml.soap.SOAPMessage.writeTo(OutputStream out)可以把消息打印到指定的输出流。

4. 发送消息

/**
 * 发送SOAP message,并返回响应的SOAP message.
 * @param request
 * @return
 * @throws MalformedURLException
 */
private SOAPMessage send(SOAPMessage request) throws MalformedURLException {
  // 1. 根据address、serviceName创建service
  URL url = new URL(ADDRESS);
  QName serviceName = new QName(TARGET_NAME_SPACE, SERVICE_NAME);
  Service service = Service.create(url, serviceName);
 
  // 2. 使用service,根据portName创建dispatch
  QName portName = new QName(TARGET_NAME_SPACE, PORT_NAME);
  Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
       SOAPMessage.class, Service.Mode.MESSAGE);
 
  // 3. 发送请求
  SOAPMessage response = dispatch.invoke(request);
 
  return response;
}

 

上述代码获得的响应的结果:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Header/>
  <S:Body>
     <ns2:interpretResponse xmlns:ns2="http://service.chapter1.jws.sand.ljl.cn/">
       <chnum>一一二三五八</chnum>
     </ns2:interpretResponse>
  </S:Body>
</S:Envelope>

5. 解析结果

Document doc = response.getSOAPPart().getEnvelope()
       .getBody().extractContentAsDocument();
String result = doc.getElementsByTagName("chnum").item(0)
       .getTextContent();

完整的demo


package cn.ljl.sand.jws.chapter2.client;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import org.junit.Assert;
import org.junit.Test;
import org.w3c.dom.Document;
import cn.ljl.sand.jws.chapter1.service.InterpretService;
/**
 * 基于SAAJ的客户端.<br>
 * 所访问的服务参考{@link InterpretService}.
 * 
 * @author lijinlong
 * 
 */
public class SAAJClient {
    /** 服务的地址 */
    private static final String ADDRESS = "http://localhost:6666/service/interpret";
    /** 目标命名空间 */
    private static final String TARGET_NAME_SPACE = "http://service.chapter1.jws.sand.ljl.cn/";
    /** service的名称 */
    private static final String SERVICE_NAME = "InterpretServiceImplService";
    /** port的名称 */
    private static final String PORT_NAME = "InterpretServiceImplPort";
    
    /**
     * 创建并填充SOAP message.
     * @return
     * @throws SOAPException
     */
    private SOAPMessage createMessage() throws SOAPException {
        SOAPMessage message = MessageFactory.newInstance().createMessage();
        SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
        SOAPBody body = envelope.getBody();
        
        QName qname = new QName(TARGET_NAME_SPACE, "interpret", "ns");
        SOAPBodyElement bodyElement = body.addBodyElement(qname);
        bodyElement.addChildElement("num").setValue("112358");
        
        return message;
    }
    
    /**
     * 发送SOAP message,并返回响应的SOAP message.
     * @param request
     * @return
     * @throws MalformedURLException
     */
    private SOAPMessage send(SOAPMessage request) throws MalformedURLException {
        URL url = new URL(ADDRESS);
        QName serviceName = new QName(TARGET_NAME_SPACE, SERVICE_NAME);
        Service service = Service.create(url, serviceName);
        QName portName = new QName(TARGET_NAME_SPACE, PORT_NAME);
        Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
                SOAPMessage.class, Service.Mode.MESSAGE);
        SOAPMessage response = dispatch.invoke(request);
        return response;
    }
    
    @Test
    public void test() throws SOAPException, IOException {
        SOAPMessage request = createMessage();
        request.writeTo(System.out);
        
        SOAPMessage response = send(request);
        response.writeTo(System.out);
        
        Document doc = response.getSOAPPart().getEnvelope()
               .getBody().extractContentAsDocument();
        String result = doc.getElementsByTagName("chnum").item(0)
               .getTextContent();
        Assert.assertEquals("一一二三五八", result);
    }
}

 





以上是关于基于SAAJ的客户端的主要内容,如果未能解决你的问题,请参考以下文章

SAAJ0537:无效的内容类型。可能是错误消息而不是 SOAP 消息

java.lang.LinkageError:com / sun / xml / messaging / saaj / soap / SOAPDocumentImpl

JAX-WS基础知识路线图

在有效的 SOAP SAAJ 信封中使用默认命名空间

HTTP客户端代码片段

基于散列片段的安全性究竟是如何工作的?