为什么使用处理链?
一个处理程序可以在客户端或服务器端用来创建一个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响应之前
消息处理链可以使用后台组件也可以不使用,下面主要针对各种处理情况?

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

图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)在
2)创建
3.使用
注意:处理链只是自执行的,没有后台组件参与执行,在这中情况下,只要使用处理链属性中的
handler-chain="mychain" />
这里有一个完整的web.xml的例子:
web-service.xml
targetnamespace="http://www.bea.com">
component="jccomp0">
style="in" type="xsd:string" />
type="xsd:float" />
这里面处理链的名字叫做authenticationhandlerchain,
这里面包含了一个authenticationhandler处理程序,注意,
在操作中包含了操作属性handler-chain="authenticationhandlerchain".
这里给出了ant脚本build.xml用来打包ear,注意在打包之前必须有web.xml 和 application.xml
build.xml
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服务中。
闽公网安备 35060202000074号