转至:http://www.blogjava.net/fool/archive/2006/11/13/80901.html
soap报头与处理
SOAPHeaderElement 对象中的属性决定了接收者怎样处理消息,可以认为header属性提供了扩展消息的方法,给出了像身份认证,支付,转发消息这样的相关的事情。JAX-RPC客户API(占位程序,动态代理,DII)均没有提供对SOAP文件头的支持,SAAJ API提供了支持。所有消息处理程序都必须实现javax.xml.rpc.handler.Handler接口,该接口有一系列的方法用以处理soap消息。javax.xml.rpc.handler.GenericHandler是一个缺省适配器类,创建我们自己的消息处理程序的时候从该类继承覆写我们自己感兴趣的方法就可以了。但每一个handler必须实现 getHeader()方法跟 handleRequest()方法.具体实现:
服务类HandlerServic:
package handler;
public class HandlerService implements HandlerServiceInterface1 {
public void testInOutHeader(String bodyMsg, String headerMsg)
{
System.out.print("testInHeader: " + bodyMsg + "," + headerMsg);
}
}
消息处理类:
package handler;
import javax.xml.rpc.handler.*;
import javax.xml.soap.*;
import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import java.util.Iterator;
public class CutomerHandler extends GenericHandler {
protected QName[] headers = new QName[] {
new QName("http://handler", "headerMsg")
};
public QName[] getHeaders() {
return headers;
}// 返回handler要处理的文件头元素名的素组.
// 处理接收到的soap消息.如果返回值为false时JAX-RPC会立即中断对SOAP消息处理并将soap消息回传。关于saaj api使用方法见j2ee web service开发(三)
public boolean handleRequest(MessageContext msgContext) {
try {
SOAPMessage soapMessage = ((SOAPMessageContext) msgContext).
getMessage();
SOAPHeader soapHeader = soapMessage.getSOAPHeader();
Iterator it = soapHeader.extractAllHeaderElements();
while (it.hasNext()) {
SOAPHeaderElement headerElement = (SOAPHeaderElement) it.next();
Name headerName = headerElement.getElementName();
System.out.println(" header name is: " +
headerName.getQualifiedName());
System.out.println(" header value is: " +
headerElement.getValue());
}
SOAPBody soapBody = soapMessage.getSOAPBody();
Iterator bodyIterator = soapBody.getChildElements();
while (bodyIterator.hasNext()) {
SOAPBodyElement soapBodyElement = (SOAPBodyElement)
bodyIterator.next();
System.out.println("soapBodyElement print: " +
soapBodyElement.getNodeName());
}
SOAPBodyElement nextSoapBodyElement = (SOAPBodyElement) soapBody.
getChildElements().next();
SOAPElement soapElement = (SOAPElement) nextSoapBodyElement.
getChildElements().next();
System.out.println("soapElement print: " + soapElement.getLocalName() +
" " + soapElement.getValue());
} catch (SOAPException e) {
throw new JAXRPCException(e);
}
return true;
}
// 返回soap应答消息,本例修改soap文件头的值再返传给客户端.
public boolean handleResponse(MessageContext msgContext) {
try {
SOAPMessage soapMessage = ((SOAPMessageContext) msgContext).
getMessage();
SOAPHeader soapHeader = soapMessage.getSOAPHeader();
SOAPBody soapBody = soapMessage.getSOAPBody();
SOAPBodyElement soapBodyElement = (SOAPBodyElement) soapBody.
getChildElements().next();
String rpcName = soapBodyElement.getElementName().getLocalName();
SOAPFactory soapFactory = SOAPFactory.newInstance();
Name headerName = soapFactory.createName("headerMsg", "ns","http://handler");
SOAPHeaderElement she = soapHeader.addHeaderElement(headerName);
she.setValue("return header message");
} catch (SOAPException e) {
throw new JAXRPCException(e);
}
return true;
}
}
用于生成布署描述符的WSTOOLS工具的配置文件:
<configuration xmlns="http://www.jboss.org/jbossws-tools"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.org/jbossws-tools http://www.jboss.org/jbossws-tools/schema/jbossws-tool_1_0.xsd">
<java-wsdl>
<service name="TestService" style="rpc" endpoint="handler.HandlerServiceInterface1">
<operation name="testInOutHeader">
<parameter type="java.lang.String"/>
<parameter type="java.lang.String"/>
</operation>
</service>
<namespaces target-namespace="http://handler" type-namespace="http://handler"/>
<mapping file="HandlerServiceInterface1.xml"/>
<webservices servlet-link="HandlerServiceInterface1"/>
</java-wsdl>
</configuration>
关于wstools工具的使用见j2ee web service开发(一).
在生成的webservice描述符文件中手工加入以下代码:
<handler>
<handler-name>CutomerHandler</handler-name>
<handler-class>handler.CutomerHandler</handler-class>
</handler> 用以配置处理soap消息头的类.
客户端代码:利用j2ee web serive开发(三)介绍的api不难写出saaj客户端代码就不再重复劳动了。这里只介绍JBOss ws利用DII实现soap消息头的处理,它扩展了标准jax-rpc api.
package handler;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.Service;
import org.jboss.ws.Constants;
import org.jboss.ws.jaxrpc.CallImpl;
import javax.xml.rpc.ServiceFactory;
import java.util.*;
public class HandlerClient {
public HandlerClient() {
}
public static void main(String[] args) throws Exception{
HandlerClient handlerclient = new HandlerClient();
handlerclient.testUnboundInOutHeader();
}
public void testUnboundInOutHeader() throws Exception{
Service service = ServiceFactory.newInstance().createService(new QName("TestService"));
CallImpl call = (CallImpl)service.createCall();
call.setOperationName(new QName("http://handler", "testInOutHeader"));
call.addParameter("String_1", Constants.TYPE_LITERAL_STRING, ParameterMode.IN);
call.addParameter("String_2", Constants.TYPE_LITERAL_STRING, ParameterMode.IN);
call.setTargetEndpointAddress("http://hechang:8082/customer-handler/services/HandlerServiceInterface1");
QName xmlName = new QName("http://handler", "headerMsg");
// xmlName = new QName("http://otherns", "HeaderValue");
call.addUnboundHeader(xmlName, Constants.TYPE_LITERAL_STRING, String.class, ParameterMode.IN);
call.setUnboundHeaderValue(xmlName, " IN header message");
// 设置消息头 可以设定多组
Object retObj = call.invoke(new Object[]{"Hello world!", "IN header message"});
String unboundRet = (String)call.getUnboundHeaderValue(xmlName);
// 处理返回的消息头的值
System.out.println(" unboundReturn: "+unboundRet);
}
}