服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

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


为什么使用处理链?

  一个处理程序可以在客户端或服务器端用来创建一个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
























                          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服务中。

扫描关注微信公众号