WEB开发网
开发学院WEB开发Jsp 处理链处理WEB服务中的请求/响应消息 阅读

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

 2008-01-05 10:30:09 来源:WEB开发网   
核心提示: 为什么使用处理链?一个处理程序可以在客户端或服务器端用来创建一个SOAP的请求消息和响应消息,例如一个使用消息处理程序的简单例子,处理链处理WEB服务中的请求/响应消息,在SOAP消息中的实体部分对数据进行加密和解密,客户端在他向WEB服务发送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响应之前
消息处理链可以使用后台组件也可以不使用,下面主要针对各种处理情况?

处理链处理WEB服务中的请求/响应消息(图一)
(图1)
图一描述了使用后台组件进行处理链操作。当客户端调用WEB服务时,SOAP请求到达处理链中的处理请求部分,一旦处理通过,处理程序将消息传送到WEB服务中并且执行。处理响应程序被WEB服务调用并且将SOAP响应发送到客户端。

处理链处理WEB服务中的请求/响应消息(图二)
图2使用后台组件的处理链模型

举例:

  这个例子我们采用的服务为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.java


import 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="http://www.bea.com">
   
                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
























             BalanceEnquiryService.java" srcdir="${source}">             destdir="${build}/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 = "http://www.bea.com";
  private static QName xsdFloat = new
         QName("http://www.w3.org/2001/XMLSchema", "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 =
   "http://localhost:7001/BalanceEnquiry/BalanceEnquiryService";
   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","",
               "http://schemas.xmlsoap.org/soap/
                   envelope/");
   SOAPHeaderElement headerElement =
     header.addHeaderElement(headerElementName);
   headerElement.setMustUnderstand(false);
   headerElement.addNamespaceDeclaration("soap",
     "http://schemas.xmlsoap.org/soap/envelope/");
   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","",
               "http://schemas.xmlsoap.org/soap/
                   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( "http://bea.com/", 
              "HelloWorldServicePort");
HandlerRegistry registry = service.getHandlerRegistry();
List handlerList = new ArrayList();
handlerList.add( new HandlerInfo( ClientHandler.class, null,null ) );
registry.setHandlerChain( portName, handlerList );


结论:
  我们希望能让大家更多的了解关于处理链机制并且应用到WEB服务中。

Tags:处理 处理 WEB

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接