JAX-WS - Soap詳解
一、建立Soap
程式碼示例如下:
@Test
public void createSoap() throws Exception{
// 建立訊息工廠
MessageFactory factory = MessageFactory.newInstance();
// 通過工廠建立Soap的訊息
SOAPMessage message = factory.createMessage();
// 獲取SoapPart
SOAPPart part = message.getSOAPPart();
// 獲取Soap信封Envelope
SOAPEnvelope envelope = part.getEnvelope();
// 通過Soap信封獲取body和header的資訊
SOAPBody body = envelope.getBody();
// 根據QName建立相應的節點(QName就是一個帶有名稱空間的節點:<ns:add xmls="http://www.xilen.com/webservice"/> )
QName qname = new QName("http://webservice.xilen.com", "add", "ns");
//通過soapBody傳入QName新增body元素
SOAPBodyElement bodyElement = body.addBodyElement(qname);
// 對body新增子元素 (或者直接對body元素設定值:bodyElement.setValue("5"); )
SOAPElement childElement = bodyElement.addChildElement("a");
// 對body子元素設定值
childElement.setValue("7");
// 繼續新增第二個子元素 (或者繼續對子元素新增子元素:childElement.addChildElement("acn").setValue("acv");)
bodyElement.addChildElement("b").setValue("5");
// 列印最終得到的Soap訊息
message.writeTo(System.out);
}
得到的Soap訊息如下:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns:add xmlns:ns="http://webservice.xilen.com">
<a>7</a>
<b>5</b>
</ns:add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
二、傳送Soap訊息
1、基於MESSAGE的方式
程式碼示例如下:
@Test
public void sendSoapByMessage() throws Exception{
/**
* 定義相關變數(wsdl文件的路徑、介面的名稱空間、實現的名稱空間)
*/
String wsdlUrl = "http://localhost:8888/user?wsdl";
String implNS = "http://impl.soap.xilen.com/";
String inteNS = "http://soap.xilen.com/";
/**
* 建立服務
*/
URL url = new URL(wsdlUrl);
// 通過wsdl實現部分的名稱空間建立服務的QNane,因為Service的描述在實現部分的名稱空間中(詳見 六、附錄 中的截圖)
QName serviceQname = new QName(implNS, "UserServiceImplService");
Service service = Service.create(url, serviceQname);
/**
* 建立Dispatch (通過SOAPMessage傳遞)
*/
Dispatch<SOAPMessage> dispatch =
// portName:wsdl檔案中Service節點中的prot的name屬性值的QName; type:訊息型別; mode:訊息傳遞的型別(message|payLoad)
service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
/**
* 建立SoapMessage
*/
SOAPMessage message = MessageFactory.newInstance().createMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
// 通過wsdl介面部分的名稱空間建立訊息的QNane,因為Message的描述在介面部分的名稱空間中<span style="font-family: Arial, Helvetica, sans-serif;">(詳見 六、附錄 中的截圖)</span>
QName soapQname = new QName(inteNS, "login", "ns");
SOAPBodyElement bodyElement = body.addBodyElement(soapQname);
bodyElement.addChildElement("name").setValue("admin");
bodyElement.addChildElement("pass").setValue("12345");
/**
* 輸出即將傳送的Soap訊息
*/
message.writeTo(System.out);
System.out.println("-------------------------- out 分隔線 in ----------------------------------");
/**
* 通過dispatch傳遞訊息
*/
SOAPMessage responseMessage = dispatch.invoke(message);
/**
* 輸出返回的Soap訊息
*/
responseMessage.writeTo(System.out);
/**
* 處理返回的Soap訊息得到需要的資訊
*/
String result = responseMessage.getSOAPBody().getElementsByTagName("loginResult").item(0).getTextContent();
// 或者採用如下方式得到需要的資訊
// String result = responseMessage.getSOAPPart().getEnvelope().getBody().extractContentAsDocument().
// getElementsByTagName("addResult").item(0).getTextContent();
/**
* 輸出通過返回Soap訊息得到的資訊
*/
System.out.println("return-->" + result);
}
Soap訊息如下:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns:login xmlns:ns="http://soap.xilen.com/">
<name>admin</name>
<pass>12345</pass>
</ns:login>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<!-------------------------- out 分隔線 in ---------------------------------->
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header/>
<S:Body>
<ns2:loginResponse xmlns:ns2="http://soap.xilen.com/">
<loginResult>admin, welcome!</loginResult>
</ns2:loginResponse>
</S:Body>
</S:Envelope>
2、基於PAYLOAD的方式
程式碼示例如下:
@Test
public void sendSoapByPayload() throws Exception{
/**
* 定義相關變數(wsdl文件的路徑、介面的名稱空間、實現的名稱空間)
*/
String wsdlUrl = "http://localhost:8888/user?wsdl";
String implNS = "http://impl.soap.xilen.com/";
String inteNS = "http://soap.xilen.com/";
/**
* 建立服務
*/
URL url = new URL(wsdlUrl);
// 通過wsdl實現部分的名稱空間建立服務的QNane,因為Service的描述在實現部分的名稱空間中
QName serviceQname = new QName(implNS, "UserServiceImplService");
Service service = Service.create(url, serviceQname);
/**
* 建立Dispatch (通過Source傳遞)
*/
Dispatch<Source> dispatch =
// portName:wsdl檔案中Service節點中的prot的name屬性值的QName; type:訊息型別; mode:訊息傳遞的型別(message|payLoad)
service.createDispatch(new QName(implNS, "UserServiceImplPort"), Source.class, Service.Mode.PAYLOAD);
/**
* 根據物件通過JAXB建立XML
*/
User user = new User(1L, "TestName", "TestPass");
JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();
// 取消xml的文件頭和尾
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(user, writer);
/**
* 組建soap的xml
*/
String payload = "<ns:register xmlns:ns=\"" + inteNS + "\">" + writer.toString() + "</ns:register>";
System.out.println(payload);
/**
* 建立Source
*/
Source outSource = new StreamSource(new StringReader(payload));
/**
* 通過dispatch傳遞負載(payLoad)
*/
Source inSource = dispatch.invoke(outSource);
/**
* 將響應的Source轉化為DOM進行操作獲取需要的資訊 (使用Transform物件轉換)
*/
Transformer transformer = TransformerFactory.newInstance().newTransformer();
DOMResult result = new DOMResult();
transformer.transform(inSource, result);
// 使用xpath查詢
XPath path = XPathFactory.newInstance().newXPath();
NodeList nl = (NodeList) path.evaluate("//registerResult", result.getNode(), XPathConstants.NODESET);
// 列印需要被獲取的資訊
System.out.println(nl.item(0).getTextContent());
}
組建的Soap內容如下:<ns:register xmlns:ns="http://soap.xilen.com/">
<user>
<id>1</id>
<name>TestName</name>
<pass>TestPass</pass>
</user>
</ns:register>
三、列表響應處理
@Test
public void returnList() throws Exception{
/**
* 定義相關變數(wsdl文件的路徑、介面的名稱空間、實現的名稱空間)
*/
String wsdlUrl = "http://localhost:8888/user?wsdl";
String implNS = "http://impl.soap.xilen.com/";
String inteNS = "http://soap.xilen.com/";
/**
* 建立服務
*/
URL url = new URL(wsdlUrl);
// 通過wsdl實現部分的名稱空間建立服務的QNane,因為Service的描述在實現部分的名稱空間中
QName serviceQname = new QName(implNS, "UserServiceImplService");
Service service = Service.create(url, serviceQname);
/**
* 建立Dispatch
*/
Dispatch<SOAPMessage> dispatch =
// portName:wsdl檔案中Service節點中的prot的name屬性值的QName type:訊息型別 mode:訊息傳遞的型別(message | payLoad)
service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
/**
* 建立SoapMessage
*/
SOAPMessage message = MessageFactory.newInstance().createMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
QName soapQname = new QName(inteNS, "list", "ns");
SOAPBodyElement bodyElement = body.addBodyElement(soapQname);
/**
* 通過dispatch傳遞訊息
*/
SOAPMessage responseMessage = dispatch.invoke(message);
// 轉換body為document
NodeList nodeList = responseMessage.getSOAPPart().getEnvelope().getBody().
extractContentAsDocument().getElementsByTagName("user");
JAXBContext ctx = JAXBContext.newInstance(User.class);
// Jaxb轉換Node為User
for (int i = 0; i < nodeList.getLength(); i++) {
User u = (User) ctx.createUnmarshaller().unmarshal(nodeList.item(i));
System.out.println(u);
}
}
四、顯示配置Header
示例程式碼如下:
@Test
public void sendSoapAddHeader() throws Exception{
/**
* 定義相關變數(wsdl文件的路徑、介面的名稱空間、實現的名稱空間)
*/
String wsdlUrl = "http://localhost:8888/user?wsdl";
String implNS = "http://impl.soap.xilen.com/";
String inteNS = "http://soap.xilen.com/";
/**
* 建立服務
*/
URL url = new URL(wsdlUrl);
QName serviceQname = new QName(implNS, "UserServiceImplService");
Service service = Service.create(url, serviceQname);
/**
* 建立Dispatch
*/
Dispatch<SOAPMessage> dispatch =
service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
/**
* 建立SoapMessage
*/
SOAPMessage message = MessageFactory.newInstance().createMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
QName soapQname = new QName("http://soap.xilen.com/", "check", "ns");
body.addBodyElement(soapQname);
/**
* 新增Header
*/
SOAPHeader header = envelope.getHeader();
// 判斷是否有Header,沒有則新增
if(header == null){
header = envelope.addHeader();
}
// 新增Header的內容
QName headerQName = new QName("http://soap.xilen.com/", "name", "nn");
SOAPHeaderElement headerElement = header.addHeaderElement(headerQName);
headerElement.setValue("admin");
header.addHeaderElement(new QName("http://soap.xilen.com/", "pass", "nn")).setValue("12345");
message.writeTo(System.out);
/**
* 通過dispatch傳遞訊息
*/
SOAPMessage responseMessage = dispatch.invoke(message);
/**
* 處理響應
*/
NodeList nodeList = responseMessage.getSOAPPart().getEnvelope().getBody().
extractContentAsDocument().getElementsByTagName("user");
JAXBContext ctx = JAXBContext.newInstance(User.class);
System.out.println("\n" + (User) ctx.createUnmarshaller().unmarshal(nodeList.item(0)));
}
傳送的Soap如下:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<nn:name xmlns:nn="http://soap.xilen.com/">admin</nn:name>
<nn:pass xmlns:nn="http://soap.xilen.com/">12345</nn:pass>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns:check xmlns:ns="http://soap.xilen.com/" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
五、服務端丟擲異常
@Test
public void throwsException() throws Exception{
/**
* 定義相關變數(wsdl文件的路徑、介面的名稱空間、實現的名稱空間)
*/
String wsdlUrl = "http://localhost:8888/user?wsdl";
String implNS = "http://impl.soap.xilen.com/";
String inteNS = "http://soap.xilen.com/";
/**
* 建立服務
*/
URL url = new URL(wsdlUrl);
QName serviceQname = new QName(implNS, "UserServiceImplService");
Service service = Service.create(url, serviceQname);
/**
* 建立Dispatch
*/
Dispatch<SOAPMessage> dispatch =
service.createDispatch(new QName(implNS, "UserServiceImplPort"), SOAPMessage.class, Service.Mode.MESSAGE);
/**
* 建立SoapMessage
*/
SOAPMessage message = MessageFactory.newInstance().createMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
QName soapQname = new QName(inteNS, "throwsException", "ns");
body.addBodyElement(soapQname);
/**
* try異常
*/
try {
dispatch.invoke(message);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
六、附錄
1、WSDL概略圖:
2、服務端程式碼如下:
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import com.xilen.entity.User;
@WebService
public interface UserService {
/**
* 通過註解@WebParam對入參設定別名
* 通過註解@WebResult對出參設定別名
*/
@WebResult(name="loginResult")
public String login(@WebParam(name="name") String name, @WebParam(name="pass") String pass);
@WebResult(name="registerResult")
public String register(@WebParam(name="user") User user);
@WebResult(name="user")
public List<User> list();
/**
* 通過註解@WebParam的header屬性設定入參為顯示的Header
*/
@WebResult(name="user")
public User check(@WebParam(name="name",header=true) String name, @WebParam(name="pass",header=true) String pass);
public void throwsException() throws Exception;
}
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import com.xilen.entity.User;
import com.xilen.soap.UserService;
@WebService(endpointInterface = "com.xilen.soap.UserService", serviceName = "UserServiceImplService")
public class UserServiceImpl implements UserService {
@Override
public String login(String name, String pass) {
System.out.println("login info : [name=" + name + ", pass=" + pass
+ "]");
return name + ", welcome!";
}
@Override
public String register(User user) {
System.out.println(user);
return user.getName() + ", registered!";
}
@Override
public List<User> list() {
List<User> list = new ArrayList<User>();
list.add(new User(1L, "admin", "12345"));
list.add(new User(2L, "super", "54321"));
return list;
}
@Override
public User check(String name, String pass) {
System.out.println(name + "--->" + pass);
return new User(1L, "admin", "12345");
}
@Override
public void throwsException() throws Exception {
throw new Exception("使用者不存在!");
}
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class User {
private Long id;
private String name;
private String pass;
public User() {
}
public User(Long id, String name, String pass) {
super();
this.id = id;
this.name = name;
this.pass = pass;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", pass=" + pass + "]";
}
}
import javax.xml.ws.Endpoint;
import com.xilen.soap.impl.UserServiceImpl;
public class StartMain {
public static void main(String[] args) {
Endpoint.publish("http://localhost:8888/user", new UserServiceImpl());
}
}
七、資源
http://download.csdn.net/detail/u013379717/7453709
相關文章
- JAX-WS - Handler詳解
- Webservice呼叫方式:axis,soap詳解Web
- Spring整合JAX-WSSpring
- JAX-WS - 基礎示例
- SOAP及WebServicesWeb
- SOAP簡介
- SOAP快取問題快取
- SOAP 節點基礎
- SOAP和WebService真是垃圾。Web
- PHP 以 SOAP 方式呼叫介面PHP
- 瞭解下SOAP HTTP 協議HTTP協議
- WebService Soap架構設計Web架構
- SOAP(Simple Object Access Protocol) (轉)ObjectProtocol
- SOAP協議規範(一)協議
- SOAP協議規範(二)協議
- HttpClient 進行soap請求HTTPclient
- [解決]電信彩信閘道器開發錯誤-SOAP_VERSIONMISMATCH
- JAX-WS - 通過xjc命令把Schema生成JavaJava
- (文摘)徹底理解webservice SOAP WSDLWeb
- soap協議的web服務協議Web
- 請教banq大哥SOAP和HTTPHTTP
- XML SOAP應用簡介 (轉)XML
- webservice快速入門-SOAP和WSDL(三)Web
- REST是否會步SOAP的後塵?REST
- 什麼是SOAP,有哪些應用
- 如何解決soap的效能問題?
- web服務中soap、wsdl、uddi理解Web
- Restful是什麼,SOAP Webservice和RESTful WebserviceRESTWeb
- Web Service和SOAP以及HTTP的關係? .WebHTTP
- 翻譯-使用Spring呼叫SOAP Web ServiceSpringWeb
- 發展中的SOAP互操作性
- PHP使用SOAP呼叫.net的WebService資料PHPWeb
- Http get,post,soap協議的區別HTTP協議
- onvif soap 協議的錯誤程式碼協議
- http協議/cookie詳解/session詳解HTTP協議CookieSession
- Lombok 註解詳解Lombok
- Java註解詳解Java
- Java 註解詳解Java