SOAP消息头通常包含与消息体或SOAP处理(应用)方式相关的信息,比如消息路径、数字签名、认证信息,消息关联性信息、消息体的加密公匙等等。
下面我们以一个简单的权限认证的示例,来讲解如何添加和使用SOAP头信息。
(1)服务端IMyService接口中的方法为:
@WebResult(name="user")
public List<User> list(@WebParam(header=true, name="authInfo")String authInfo);
这里我们把验证信息作为方法的参数。
(2)方式一:通过SOAP方式添加header验证信息
@Test
public void test04() {
try {
//1.创建服务(Service)
URL url = new URL(wsdlUrl);
QName sName = new QName(ns, "MyServiceImplService");
Service service = Service.create(url, sName);
//2.创建Dispatch
Dispatch<SOAPMessage> dispatch = service.createDispatch(new QName(ns, "MyServiceImplPort"),
SOAPMessage.class, Service.Mode.MESSAGE);
//3.创建SOAPMessage
SOAPMessage message = MessageFactory.newInstance().createMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
SOAPBody body = envelope.getBody();
//3.2处理header信息
SOAPHeader header = envelope.getHeader(); //通过envelope得到header
if (header == null) {
header = envelope.addHeader();
}
QName hName = new QName(ns, "authInfo", "nn"); //<nn:authInfo xmlns:nn="xx"/>
header.addHeaderElement(hName).setValue("aabbcc");
//4.创建QName来指定消息中传递的数据
QName eName = new QName(ns, "list", "nn"); //<nn:list xmlns="xx" />
body.addBodyElement(eName);
message.writeTo(System.out);
System.out.println("\n invoking......");
/*
* 上面步骤3、4为添加SOAP header和body信息,打印结果为:
* <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
* <SOAP-ENV:Header>
* <nn:authInfo xmlns:nn="http://service.soap.org/">aabbcc</nn:authInfo>
* </SOAP-ENV:Header>
* <SOAP-ENV:Body>
* <nn:list xmlns:nn="http://service.soap.org/"/>
* </SOAP-ENV:Body>
* </SOAP-ENV:Envelope>
* invoking......
*/
//5.通过Dispatch传递信息,会返回响应消息
SOAPMessage response = dispatch.invoke(message);
response.writeTo(System.out);
System.out.println();
/*
* <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
* <S:Header/>
* <S:Body>
* <ns2:listResponse xmlns:ns2="http://service.soap.org/">
* <user>
* <id>1</id>
* <nickName>管理员</nickName>
* <password>111111</password>
* <userName>admin</userName>
* </user>
* </ns2:listResponse>
* </S:Body>
* </S:Envelope>
*/
//6.将响应的消息转换为dom对象
Document doc = response.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
NodeList nl = doc.getElementsByTagName("user");
JAXBContext ctx = JAXBContext.newInstance(User.class);
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
User u = (User)ctx.createUnmarshaller().unmarshal(node);
System.out.println(u.getNickName());
}
/*
* 管理员
*/
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
}
}
(3)方式二:通过JAX-WS方式添加header验证信息
首先使用wsimport导出代码(使用方法见《WebService—快速实现一个基于JAX-WS的WebService项目(二)》),然后copy到项目中,如下图
把消息头作为方法参数,通过wsimport导出的代码中,IMyService里面的该方法,参数会增加,如下:
public ListResponse list(
@WebParam(name = "list", targetNamespace = "http://service.soap.org/", partName = "parameters")
List parameters,
@WebParam(name = "authInfo", targetNamespace = "http://service.soap.org/", header = true, partName = "authInfo")
String authInfo);
调用时,参数list传null即可。
public class Test {
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:8989/ms?wsdl");
QName qName = new QName("http://service.soap.org/", "MyServiceImplService");
MyServiceImplService mis = new MyServiceImplService(url, qName);
IMyService ms = mis.getMyServiceImplPort();
List<User> users = ms.list(null, "soaptest").getUser();
for(User u : users) {
System.out.println(u.getNickName());
}
/*
* 打印结果为:soaptest
*/
}
}