1. 程式人生 > >Axis2用法(3)soap訊息攜帶訊息頭

Axis2用法(3)soap訊息攜帶訊息頭

1、訊息頭定義

一般soap訊息中,訊息體是攜帶訊息的核心內容;訊息頭中的欄位,多數用於校驗。定義訊息頭,就相當於定義一個bean物件。本例中,在上一篇的繼承上,為訊息增加訊息頭,其中訊息頭核心內容包括三個欄位:serviceId,servPassWord和timeStamp。原始碼如下:
package com.yht.msg.header;

/**
 * 定義訊息頭中包含哪些內容的bean。
 * @author Administrator
 *
 */
public class AttachHeader 
{
	/**
	 * 訊息節點標籤。
	 */
	public static final String NODEFLAG = "tns";
	
	/**
	 * 訊息頭標籤。
	 */
	public static final String HEADFLAG = "RequestHeader";
	
	/**
	 * 名稱空間。
	 */
	public static final String NAMESPACE = "http://com.yht.msg";
	
	/**
	 * 時間戳標籤。
	 */
	public static final String TIMESTAMP = "timeStamp";
	
	/**
	 * 業務編號標籤。
	 */
	public static final String SERVICEID = "serviceId";
	
	/**
	 * 業務對於的校驗密碼標籤。
	 */
	public static final String SERVPASSWORD = "servPassWord";
	
	/**
	 * 時間戳。
	 */
	private String timeStamp;
	
	/**
	 * 業務編號。
	 */
	private String serviceId;
	
	/**
	 * 業務對於的校驗密碼。
	 */
	private String servPassWord;

	/**
	 * 獲取時間戳。
	 * @return 時間戳。
	 */
	public String getTimeStamp() 
	{
		return timeStamp;
	}

	/**
	 * 設定時間戳。
	 * @param timeStamp 時間戳。
	 */
	public void setTimeStamp(String timeStamp) 
	{
		this.timeStamp = timeStamp;
	}

	/**
	 * 獲取業務編號。
	 * @return 業務編號。
	 */
	public String getServiceId() 
	{
		return serviceId;
	}

	/**
	 * 設定業務編號。
	 * @param serviceId 業務編號。
	 */
	public void setServiceId(String serviceId) 
	{
		this.serviceId = serviceId;
	}

	/**
	 * 獲取校驗密碼。
	 * @return 校驗密碼。
	 */
	public String getServPassWord() 
	{
		return servPassWord;
	}

	/**
	 * 設定校驗密碼。
	 * @param servPassWord 校驗密碼。
	 */
	public void setServPassWord(String servPassWord) 
	{
		this.servPassWord = servPassWord;
	}
	
}

2、打包與解析訊息頭方法

訊息頭中欄位定義好了,那麼對於demo作為:客戶端,傳送出去的訊息攜帶訊息頭,需要一個大包訊息頭的方法;服務端,接受別處來的訊息,需要一個解析訊息頭的方法。這重新定義一個類:DealHeader繼承訊息頭定義的類AttachHeader。該類中,有兩個方法:packSoapHeader和parseSoapHeader。原始碼如下:
package com.yht.msg.header;

import java.util.Iterator;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.client.ServiceClient;

/**
 * 提供上下行訊息中,處理訊息頭的方法。
 * 作為服務端,需要解析訊息中的訊息頭;作為客戶端,需要在訊息頭中加入訊息頭。
 * @author Administrator
 *
 */
public class DealHeader extends AttachHeader
{
	/**
	 * 打包訊息頭。將設定到AttachHeader中的各欄位的內容,打包到訊息中傳送出去。
	 * @param serviceClient
	 */
	public void packSoapHeader(ServiceClient serviceClient)
	{
		//獲取建立工廠。
		OMFactory oMFactory = OMAbstractFactory.getOMFactory();
		SOAPFactory sOAPFactory = OMAbstractFactory.getSOAP11Factory();
		
		//利用工廠,建立名稱空間和訊息頭。
		OMNamespace oMNamespace = oMFactory.createOMNamespace(NAMESPACE, NODEFLAG);
		SOAPHeaderBlock soapHeader = 
				sOAPFactory.createSOAPHeaderBlock(HEADFLAG, oMNamespace);
		
		//訊息頭中的時間錯節點。
		String timeStamp = (getTimeStamp() == null) ? "" : getTimeStamp();
		SOAPHeaderBlock timeBlock = 
				sOAPFactory.createSOAPHeaderBlock(TIMESTAMP, oMNamespace);
		timeBlock.addChild(sOAPFactory.createOMText(timeStamp));
		
		//訊息頭中的業務表示節點。
		String serviceId = (getServiceId() == null) ? "" : getServiceId();
		SOAPHeaderBlock serviceIdBlock = 
				sOAPFactory.createSOAPHeaderBlock(SERVICEID, oMNamespace);
		serviceIdBlock.addChild(sOAPFactory.createOMText(serviceId));
		
		//訊息頭中的業務校驗密碼節點。
		String servPassWord = (getServPassWord() == null) ? "" : getServPassWord();
		SOAPHeaderBlock servPassWordBlock = 
				sOAPFactory.createSOAPHeaderBlock(SERVPASSWORD, oMNamespace);
		servPassWordBlock.addChild(sOAPFactory.createOMText(servPassWord));
		
		//將各個節點加入到訊息頭中。
		soapHeader.addChild(serviceIdBlock);
		soapHeader.addChild(servPassWordBlock);
		soapHeader.addChild(timeBlock);
		
		//將訊息頭加入到當前訊息中。
		serviceClient.addHeader(soapHeader);
	}
	
	/**
	 * 解析訊息頭。作為服務端接受訊息時,將當前訊息中的訊息頭取出,單獨解析成AttachHeader中設定的欄位的值。
	 * @param soapHeader
	 */
	public void parseSoapHeader(SOAPHeader soapHeader)
	{
		//訊息頭非空判斷。
		if(soapHeader == null)
		{
			return ;
		}
		
		//獲取訊息流中的訊息頭列表,並做非空判斷。
		Iterator<?> headerList = soapHeader.examineHeaderBlocks(null);
		if(headerList == null)
		{
			return ;
		}
		
		//獲取第一個訊息頭,並獲取訊息頭中的元素。
		SOAPHeaderBlock header = (SOAPHeaderBlock)headerList.next();
		Iterator<?> elementList = header.getChildElements();
		
		OMElement element = null;
		String key = null;
		String value = null;
		if(elementList != null)
		{
			//解析非空列表中的所有節點。
			while(elementList.hasNext())
			{
				//獲取節點key和value值。
				element = (OMElement)elementList.next();
				key = element.getLocalName();
				value = element.getText().trim();
				
				//如果是業務標籤,將值設定。
				if(SERVICEID.equals(key))
				{
					setServiceId(value);
				}
				
				//如果是校驗密碼,將值設定。
				if(SERVPASSWORD.equals(key))
				{
					setServPassWord(value);
				}
				
				//如果是時間戳,將值設定。
				if(TIMESTAMP.equals(key))
				{
					setTimeStamp(value);
				}
			}
		}
	}
}

3、客戶端服務端攜帶訊息頭

客戶端大包訊息頭和服務端解析訊息頭的方法都定義好了,那麼如何大包解析呢?

(1)客戶端

對於上篇中封裝的客戶端類SendAttachClient,要實現打包需要做如下步驟: 一、SendAttachClient繼承DealHeader。 二、根據服務地址,建立一個傳送訊息的客戶端時,打包訊息頭。如下程式碼:
		//1、根據服務地址,建立一個傳送訊息的客戶端。
		try
		{
			stub = new SendAttachServiceStub(serviceAddress);
			packSoapHeader(stub._getServiceClient());
		}
		catch (AxisFault e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
三、測試程式碼,增加設定訊息頭欄位的程式碼。原始碼如下:
package main;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import com.yht.msg.client.SendAttachClient;

/**
 * 客戶端測試類。
 * @author Administrator
 *
 */
public class Test 
{
	/**
	 * 入口方法。
	 * @param args
	 */
	public static void main(String[] args)
	{
		//獲取系統時間,為日曆物件。  
	    Calendar calendar = Calendar.getInstance(); 
	    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
	    String time = simpleDateFormat.format(calendar.getTime());
		
		String result = null;
		String subject = "Hello Axis2-1.6.2!";
		String serviceAddress = "http://127.0.0.1:8088/SendAttachService";
		String serviceId = "12345";
		String servPassWord = "54321";
		String timeStamp = time;
		
		//建立客戶端類。
		SendAttachClient client = new SendAttachClient();
		
		client.setServiceId(serviceId);
		client.setServPassWord(servPassWord);
		client.setTimeStamp(timeStamp);
		
		//設定訊息體內容。
		client.setSubject(subject);
		
		//設定服務地址。
		client.setServiceAddress(serviceAddress);
		
		//傳送訊息獲取,結果。
		result = client.sendAttach();
		
		//列印結果。
		System.out.println(result);
	}
}

(2)服務端

作為服務端,只要獲取當前訊息中的訊息頭;new一個打包訊息的類物件,將訊息頭放到物件中解析;訊息中的值就訊息到該物件中。對於上一篇中的服務端類GetAttachService,增加解析訊息頭能力後,原始碼如下:
package com.yht.msg.service;

import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.context.MessageContext;

import com.yht.msg.SendAttach;
import com.yht.msg.SendAttachResponse;
import com.yht.msg.SendAttachServiceSkeletonInterface;
import com.yht.msg.header.DealHeader;

/**
 * 服務端,接受訊息。
 * @author Administrator
 *
 */
public class GetAttachService 
	implements SendAttachServiceSkeletonInterface
{
	/**
	 * 接受訊息並返回相應的相應。
	 */
	public SendAttachResponse sendAttach(SendAttach arg0) 
	{
		//獲取上下行訊息中的訊息頭。
		MessageContext context = MessageContext.getCurrentMessageContext();
		SOAPHeader soapHeader = context.getEnvelope().getHeader();
		
		//解析訊息頭。
		DealHeader dealHeader = new DealHeader();
		dealHeader.parseSoapHeader(soapHeader);
		
		// TODO Auto-generated method stub
		System.out.println(dealHeader.getServiceId());
		System.out.println(dealHeader.getServPassWord());
		System.out.println(dealHeader.getTimeStamp());
		System.out.println(arg0.getArgs0());
		
		//響應。
		SendAttachResponse response = new SendAttachResponse();
		response.set_return("success");
		return response;
	}
	
}