处理链处理WEB服务中的请求/响应消息

ZDNet软件频道 时间:2008-06-30 作者: | 中国IT实验室 我要评论()
本文关键词:请求 web JSP
一个处理程序可以在客户端或服务器端用来创建一个SOAP的请求消息和响应消息。


 为什么使用处理链?

  一个处理程序可以在客户端或服务器端用来创建一个SOAP的请求消息和响应消息。例如一个使用消息处理程序的简单例子,在SOAP消息中的实体部分对数据进行加密和解密,客户端在他向web服务发送SOAP请求消息前必须使用消息处理程序对消息进行加密,web服务收到请求后,在它将数据发送到后台实现web服务之前,必须使用消息处理程序对从客户端发送过来的消息进行解密。与请求消息的传输方向相反,SOAP响应消息也要执行相同的步骤。

  另外一个例子,在SOAP消息的头部分访问信息进行处理。SOAP头经常用来存储web服务详细说明信息并且使用消息处理程序来操作它。例如将用户名和密码可以放在SOAP消息的头部分中来发送到验证处理程序。

  SOAP消息处理可以用来提高web服务的使用效率。这种方法的实现可以通过使用队列缓冲SOAP响应的次序。处理程序可以使SOAP的请求信息生效并且将消息交互纪录下来。

处理链:

  处理链就是将每一个消息处理装配成一个链表形式进行处理。在web服务中实现可能需要调用多个处理类,用来提供处理请求/响应前面或后面的服务。JAX-RPC运行环境中可以在链表中调用多个处理类。这种处理消息的概念称为处理链。

处理链模型:

  一个消息处理类功能主要在客户服务器端通信中,尽可能的为终端服务和可以设置用来截取SOAP消息并且在以下几种情况下对消息执行各种操作:

1)在客户端,在SOAP请求被建立后并且在发送到web服务之前
2)在web服务端,在SOAP消息请求web服务程序处理之前
3)在web服务端,在web服务发送SOAP消息响应之前
4)在客户端,在JAX-RPC运行时处理从web服务中收到的SOAP响应之前
消息处理链可以使用后台组件也可以不使用,下面主要针对各种处理情况?
举例:

  这个例子我们采用的服务为webLOGIC8.X,这里我们通过后台组件提供查询服务的验证处理程序来详细说明。这里面的验证内容主要是帐号和个人识别码,它们被放在SOAP请求消息的头部分中,消息处理程序将重新获得帐号和个人识别码并验证,如果验证通过,一旦通过验证,后台组件将会调用余额查询来获得此帐号的余额。

以下就是写一个处理程序的步骤:
1)处理程序必须实现javax.xml.rpc.handler.Handler 接口或继承weblogic中的GenericHandler 类。
2)javax.xml.rpc.handler.Handler 接口包含了以下这些方法用来实现


init () destroy() getHeaders() handleRequest() handleResponse() handleFault()  如果使用weblogic.webservice.GenericHandler 类,只需要重写必须的方法,在这个例子中验证处理程序重写了handleRequest() 和handleResponse() 方法。如果handleRequest()方法返回true,将会调用处理链中的下一个处理程序,如果这个处理程序是处理链中最后一个元素,将会调用后台的web服务程序。如果  handleRequest()方法返回false,对应的handleResponse()方法将会被调用。验证处理程序中handleRequest() 将从SOAP的头部分中重新获得帐号和个人识别码,并且验证后要返回true 或false结果。AuthenticationHandler.javaimport java.util.Map;import java.util.Iterator;import javax.xml.rpc.JAXRPCException;import javax.xml.rpc.handler.soap.SOAPMessageContext;import javax.xml.rpc.handler.HandlerInfo;import javax.xml.rpc.handler.MessageContext;import javax.xml.namespace.QName;import javax.xml.soap.*;import weblogic.webservice.GenericHandler;public class AuthenticationHandler extends GenericHandler{   private int me = System.identityHashCode(this);   private HandlerInfo handlerInfo = null;   String accountNo                = null;   String pin                      = null;   public void init(HandlerInfo handlerInfo)   {      this.handlerInfo = handlerInfo;   }   public boolean handleRequest(MessageContext messageContext)   {      System.err.println("** handleRequest called in: "+me);      try      {         SOAPMessageContext sctx = (SOAPMessageContext)messageContext;         SOAPMessage message     = sctx.getMessage();         SOAPPart sp             = message.getSOAPPart();         SOAPEnvelope senv       = sp.getEnvelope();         SOAPHeader sh           = senv.getHeader();         Iterator iter =  sh.getChildElements();         if(iter.hasNext())         {            iter.next();                 //skip text            Object obj = iter.next();    //account details            SOAPElement elt = (SOAPElement)obj;            iter = elt.getChildElements();            iter.next();                 //skip text node            obj = iter.next();            elt = (SOAPElement)obj;            accountNo = elt.getValue();            iter.next();                 //skip text node            obj = iter.next();            elt = (SOAPElement)obj;            pin = elt.getValue();         }      }      catch (Exception e)      {         e.printStackTrace();         throw new JAXRPCException(e);      }      if(accountNo.equals("12345") && pin.equals("6789"))         return true;      else         return false;   }   public boolean handleResponse(MessageContext messageContext)   {      System.out.println("Inside HandleResponse");      return true;   }   public QName[] getHeaders()   {      return handlerInfo.getHeaders();   }}

以下就是余额查询的代码,是一个非常简单的服务返回给出已知帐号的余额。
BalanceEnquiryService.java


public class BalanceEnquiryService{   public float getBalance(String accountNo)   {      if(accountNo.equals("12345"))         return 5000f;      else         return 100f;   }}

  web服务中的web-service.xml 必须要修改为包含处理链的描述,下面几个部分需要在web-service.xml 中修改的:

1)在 的根元素中创建一个 子元素,在这个子元素中包含了web服务中一系列处理链程序的定义。
2)创建的子元素 ,在这个子元素中,显示了所有处理链中的处理程序。对于每一个处理程序,使用类名必须指定 java类的全限定名以便实现处理程序。使用元素来指定处理程序的初始化参数。

                       


3.使用(它本身是 的子元素)的子元素元素,来详细说明处理链是web服务中的一个操作。 

 注意:处理链只是自执行的,没有后台组件参与执行,在这中情况下,只要使用处理链属性中的元素并且并不需要指定组件或方法的属性,就像下面所选其中的一部分:

                          handler-chain="myChain" />  

这里有一个完整的web.xml的例子:
web-service.xml

                      uri="/BalanceEnquiryService"                targetNamespace="class-name="BalanceEnquiryService">                                                  handler-chain="AuthenticationHandlerChain"                    component="jccomp0">                                                          style="in" type="xsd:string" />                                            class-name="java.lang.Float"                                           type="xsd:float" />                这里面处理链的名字叫做AuthenticationHandlerChain,这里面包含了一个AuthenticationHandler处理程序,注意,在操作中包含了操作属性handler-chain="AuthenticationHandlerChain".  这里给出了ant脚本build.xml用来打包EAR,注意在打包之前必须有web.xml 和 application.xml build.xml                          destdir="$/web-INF/classes" />  ant脚本在创建WAR文件的同时也进行EAR打包,在webLOGIC服务器上部署打包好的EAR文件,
下面是客户端调用余额查询的程序:
Client.java


import org.apache.axis.client.Call;import org.apache.axis.client.ServiceFactory;import org.apache.axis.client.Service;import org.apache.axis.MessageContext;import org.apache.axis.attachments.Attachments;import org.apache.axis.message.SOAPEnvelope;import javax.xml.namespace.QName;import javax.xml.soap.SOAPBody;import javax.xml.soap.SOAPBodyElement;import javax.xml.soap.SOAPConnection;import javax.xml.soap.SOAPConnectionFactory;import javax.xml.soap.SOAPElement;import javax.xml.soap.SOAPHeader;import javax.xml.soap.SOAPHeaderElement;import javax.xml.soap.SOAPMessage;import javax.xml.soap.SOAPPart;import javax.xml.namespace.QName;import javax.xml.rpc.ParameterMode;import javax.xml.soap.AttachmentPart;import javax.xml.soap.MessageFactory;import javax.xml.soap.Name;import javax.xml.rpc.ParameterMode;import java.net.URL;import java.util.Iterator;public class Client{   private static String TARGET_NAMESPACE = ";   private static QName xsdFloat = new                  QName"float");   public static org.apache.axis.message.SOAPEnvelope env = null;   public static SOAPMessage message = null;   public static void main(String[] argv) throws Exception   {      Client client = new Client();      env = client.constructSOAPEnvelope();      client.constructHeader(env);      client.constructBody(env);      System.setProperty( "javax.xml.rpc.ServiceFactory",                          "org.apache.axis.client.ServiceFactory" );      String url =     ServiceFactory factory =         (org.apache.axis.client.ServiceFactory)ServiceFactory.              newInstance();      QName serviceName   = new QName(TARGET_NAMESPACE,         "BalanceEnquiryService");      Service service =          (org.apache.axis.client.Service)factory.          createService(serviceName);      Call call = (org.apache.axis.client.Call)service.createCall();      call.setTargetEndpointAddress(url);      SOAPEnvelope result = call.invoke(env);      System.out.println(result);   }   public SOAPEnvelope constructSOAPEnvelope() throws Exception   {      org.apache.axis.message.SOAPEnvelope env = new         org.apache.axis.message.SOAPEnvelope();      return env;   }   public void constructHeader(SOAPEnvelope envelope) throws Exception   {      SOAPHeader header = envelope.getHeader();      Name headerElementName =         envelope.createName("AccountDetails","",                             "                                    envelope/");      SOAPHeaderElement headerElement =         header.addHeaderElement(headerElementName);      headerElement.setMustUnderstand(false);      headerElement.addNamespaceDeclaration("soap",         ");      SOAPElement accNo = headerElement.addChildElement("accountNo");      accNo.addTextNode("12345");      SOAPElement pinNo = headerElement.addChildElement("pin");      pinNo.addTextNode("6789");   }   public void constructBody(SOAPEnvelope envelope) throws Exception   {      SOAPBody body = envelope.getBody();      Name bodyRootElementName =         envelope.createName("getBalance","",                             "                                    encoding/");      SOAPBodyElement bodyRootElement =         body.addBodyElement(bodyRootElementName);      SOAPElement bodyElement =         bodyRootElement.addChildElement("param0");      bodyElement.addAttribute(envelope.createName("xsi:type"),                                                   "xsd:string");      bodyElement.addTextNode("12");   }}


如果在客户端也有一个处理程序,以下部分要发生变化:
(1)导入import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.HandlerRegistry;两个类。

(2)在call().invoke前面加:

QName portName = new QName( ""HelloWorldServicePort");HandlerRegistry registry = service.getHandlerRegistry();List handlerList = new ArrayList();handlerList.add( new HandlerInfo( ClientHandler.class, null,null ) );registry.setHandlerChain( portName, handlerList );结论:  我们希望能让大家更多的了解关于处理链机制并且应用到web服务中。


百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134