最近做的项目要完成与第三方系统进行webservice对接。首先我系统成为A系统,第三方系统成为B系统。A系统用的是xfire,只有xfire的jar包,B系统用的是cxf,只有cxf的jar包。
首先A系统调用B系统,使用一个公用客户端程序,
public static Object[] callCxfWebSrv(String url, String methodName,Object[] obj) {
Client client = null;
try {
URL _url = new URL(null, url, new sun.net.www.protocol.http.Handler());
HttpURLConnection httpConnection = (HttpURLConnection) _url.openConnection();
httpConnection.setReadTimeout(Constants.WEBSERVICE_TIMEOUT);// 设置http连接的读超时,单位是毫秒
httpConnection.connect();
client = new Client(httpConnection.getInputStream(), null);
client.addOutHandler(new ClienterCxfSqHander());
client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT,
String.valueOf(Constants.WEBSERVICE_TIMEOUT));// 设置发送的超时限制,单位是毫秒;
client.setProperty(CommonsHttpMessageSender.DISABLE_KEEP_ALIVE, "true");
client.setProperty(CommonsHttpMessageSender.DISABLE_EXPECT_CONTINUE, "true");
Object[] objects = client.invoke(methodName, obj);
client.close();
client = null;
return objects;
} catch (Exception e) {
if (client != null) {
client.close();
client = null;
}
return null;
}
}
上面client.addOutHandler(new ClienterCxfSqHander());就是客户端加验证机制的过程。其中ClienterCxfSqHander类的实现方式如下:
public class ClienterCxfSqHander extends AbstractHandler {
public ClienterCxfSqHander() {
// TODO Auto-generated constructor stub
}
@Override
public void invoke(MessageContext context) throws Exception {
Element el = new Element("header");
context.getOutMessage().setHeader(el);
Element auth = new Element("AuthenticationToken");
Element ip_el = new Element("SERVER");
ip_el.addContent(new DESEncrypt("asit").encode("CXDNS"));
auth.addContent(ip_el);
el.addContent(auth);
}
}
当A系统请求B系统时,加上了上面的 验证机制。B系统按如下方式进行解析
public class AuthorInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
private SAAJInInterceptor saa = new SAAJInInterceptor();
public AuthorInterceptor() {
super(Phase.PRE_PROTOCOL);
getAfter().add(SAAJInInterceptor.class.getName());
}
/**
* 客户端请求时,此方法进行验证,可是客户端的消息头是否与服务器端规定的相同
*/
public void handleMessage(SoapMessage message) throws Fault {
System.out.println("come in ServicesAuthorInterceptor ");
SOAPMessage mess = message.getContent(SOAPMessage.class);
if (mess == null) {
saa.handleMessage(message);
mess = message.getContent(SOAPMessage.class);
}
SOAPHeader head = null;
try {
head = mess.getSOAPHeader();
} catch (Exception e) {
e.printStackTrace();
}
if (head == null) {
return;
}
NodeList token = head.getElementsByTagName("AuthenticationToken");
if(token==null){
SOAPException soapExc = new SOAPException("认证错误");
throw new Fault(soapExc);
}
NodeList node2 = token.item(0).getChildNodes();
if(node2==null){
SOAPException soapExc = new SOAPException("认证错误");
throw new Fault(soapExc);
}
String dq = node2.item(0).getTextContent();
DESEncrypt encrypt = new DESEncrypt("111");//加密机制,可以不用
try {
dq = encrypt.decode(dq);
} catch (Exception e) {
e.printStackTrace();
}
if (!dq.equals("111")){
SOAPException soapExc = new SOAPException("认证错误");
throw new Fault(soapExc);
}else{
System.out.println("认证成功");
}
}
}
当然上面的拦截器是配置在 B系统的 cxf服务端的。
cxf客户端调用xfire服务端的过程类似,cxf的前身就是xfire,所以内核机制是一样的。
我在项目过程中 cxf调用xfire的过程中一直报 命名空间的错误javax.xml.bind.UnmarshalException: unexpected element (uri:"http://", local:"out"). Expected elements are(local:"out").。问题找了很久。原来是A系统与B系统的webservcie程序的包名空间一样,导致冲突。改了B系统的package的名称,再次调用,调用成功。
以上是我做程序员以来第一篇文章,写的不好,见谅。仅此记录我的工作经历与成果。