天天看點

JAX-WS - Handler詳解

一、Handler說明

    Handler用于處理Soap消息,如控制Header(如隐式的添加使用者資訊等)

    Handler分成LogicalHandler和SOAPHandler,常用為SOAPHandler;用戶端先處理LogicalHeader再處理SOAPHandler,伺服器反之

二、開始前的準備

    1、服務端

        (1)接口:

@WebService
public interface UserService {

	@WebResult(name="registerResult")
	public String register(@WebParam(name="user") User user);
}
           

        (2)實作:

@WebService(endpointInter, serviceName="UserServiceImplService")
public class UserServiceImpl implements UserService{

	@Override
	public String register(User user) {
		System.out.println(user);
		return user.getName() + ", registered!";
	}

}
           

        (3)啟動:

public class StartMain {
	public static void main(String[] args) {
		Endpoint.publish("http://localhost:8888/userinfo", new UserServiceImpl());
	}
}
           

    2、用戶端

       (1) 通過wsimport生成相關代碼後,調用服務端編碼:

public class Client {
	
	public static void main(String[] args) {
		
		UserServiceImplService usis = new UserServiceImplService();
		UserService service = usis.getUserServiceImplPort();

		User user = new User();
		user.setId(1);
		user.setName("admin");
		user.setPass("12345");
		
		System.out.println(service.register(user));
	}
}
           

        (2)執行

/**
* 可以完成調用并傳回
*/
admin, registered!
           

三、添加Handler

    1、服務端

        (1)自定義Handler繼承SOAPHandler<T>

public class HeaderHandlerServer implements SOAPHandler<SOAPMessageContext> {

	@Override
	public boolean handleMessage(SOAPMessageContext context) {

		try {
			/**
			 * True表示Out消息,False表示In消息
			 */
			Boolean messageTag = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
			/**
			 * 服務端驗證,In的時候
			 */
			if(messageTag == false){
				
				SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
				
				SOAPHeader header = envelope.getHeader();
				/**
				 * 如果header為空或者沒有元素,這裡判斷是否沒有元素用的是examineAllHeaderElements()方法
				 */
				if(header == null || ! header.examineAllHeaderElements().hasNext()){
					
					SOAPFault fault = envelope.getBody().addFault();
					fault.setFaultString("驗證資訊為空!");
					
					throw new SOAPFaultException(fault);
					
				}else{
					/**
					 * 将header的所有元素提取為Iterator。需要注意的是,extractAllHeaderElements()隻能在Header中提取一次
					 */
					Iterator<SOAPHeaderElement> iterator = header.extractAllHeaderElements();
					
					if(iterator.hasNext()){
						
						SOAPHeaderElement headerEle = iterator.next();
						
						/**
						 * 擷取用戶端傳遞過來的需要驗證的資訊
						 */
						System.out.println(headerEle.getTextContent());
						
						/**
						 * 後續的驗證處理
						 */
					}
				}
			}
			/**
			 *  如果Catch Exception,SOAPFaultException将不能到用戶端
			 */
		} catch (SOAPException e) {
			e.printStackTrace();
		}
		
		return true;
	}

	@Override
	public boolean handleFault(SOAPMessageContext context) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void close(MessageContext context) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Set<QName> getHeaders() {
		// TODO Auto-generated method stub
		return null;
	}

}
           

        (2)編輯handler-chains配置檔案

<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>com.xilen.handler.HeaderHandlerServer</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
	
</javaee:handler-chains>
           

        (3)在服務上添加Handler

/**
 * 添加Header,通過在服務的實作類上注解@HandlerChain并指定其配置
 */
@WebService(endpointInter, serviceName="UserServiceImplService")
@HandlerChain(file="jax-handler.xml")
public class UserServiceImpl implements UserService{

	@Override
	public String register(User user) {
		System.out.println(user);
		return user.getName() + ", registered!";
	}

}
           

        (4)測試這個Handler的效果

/**
* 在用戶端沒有添加相關Header以攜帶使用者資訊時調用服務端,将在用戶端抛出如下異常
*/
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: 驗證資訊為空!
	at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(Unknown Source)
	at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(Unknown Source)
	at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(Unknown Source)
	at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(Unknown Source)
	at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(Unknown Source)
	at com.sun.proxy.$Proxy21.register(Unknown Source)
	at com.xilen.Client.main(Client.java:19)
           

    2、用戶端

        (1)自定義Handler繼承SOAPHandler<T>

public class HeaderHandlerClient implements SOAPHandler<SOAPMessageContext> {

	@Override
	public boolean handleMessage(SOAPMessageContext context) {
		
		try {
			/**
			 * True表示Out False表示In
			 */
			Boolean messageTag = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
			
			/**
			 *如果是Out 
			 */
			if(messageTag){
				
				SOAPMessage message = context.getMessage();
				SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
				SOAPHeader header = envelope.getHeader();
				
				if(header == null){
					/**
					 * 通過envelope方式擷取hander,主要是為了能夠在Header為空的時候,通過envelope.addHeader()方法添加Header
					 */
					header = envelope.addHeader();
				}

				/**
				 * 添加Header資訊
				 */
				QName headerQName = new QName("http://impl.jws.xilen.com/", "info", "ns");
				header.addHeaderElement(headerQName).setValue("admin");
				
				/**
				 * 列印整個SOAP消息
				 */
				message.writeTo(System.out);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return true;
	}

	@Override
	public boolean handleFault(SOAPMessageContext context) {
		System.out.println("fault");
		return false;
	}

	@Override
	public void close(MessageContext context) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Set<QName> getHeaders() {
		// TODO Auto-generated method stub
		return null;
	}

}
           

        (2)編輯handler-chains配置檔案

<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>com.xilen.HeaderHandlerClient</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
	
</javaee:handler-chains>
           

        (3)在服務上添加Handler

<pre name="code" class="java">/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2.4-b01
 * Generated source version: 2.2
 * 
 * 在通過wsimport指令生成的服務實作類(繼承了Service)的類上添加@HandlerChain以配置用戶端Handler
 */
@WebServiceClient(name = "UserServiceImplService", targetNamespace = "http://impl.jws.xilen.com/", 
	wsdlLocation = "http://localhost:8888/userinfo?wsdl")
@HandlerChain(file="jax-handler.xml")
public class UserServiceImplService extends Service
{
    ……
}
           

        (4)再次測試Handler

/**
* 此時已經可以正确通路服務并傳回結果
*/
admin, registered!
           

四、一些補充

    如果需要針對某一些服務即操作才做驗證,可以在Handler中通過SoapBody擷取part以判斷目前服務

@Override
	public boolean handleMessage(SOAPMessageContext context) {

		try {
			Boolean messageTag = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

			if(messageTag == false){
				
				SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
				
				/**
				 *  如果需要針對某一些操作才做驗證,可以通過SoapBody擷取part做判斷
				 */
				String partName = envelope.getBody().getChildNodes().item(0).getLocalName(); 
				
				if("list".equals(partName)){
					/**
					 *  驗證header的邏輯
					 */
					SOAPHeader header = envelope.getHeader();
					
					if(header == null || ! header.examineAllHeaderElements().hasNext()){
						
						SOAPFault fault = envelope.getBody().addFault();
						fault.setFaultString("驗證資訊為空!");
						
						throw new SOAPFaultException(fault);
						
					}else{
						
						Iterator<SOAPHeaderElement> iterator = header.extractAllHeaderElements();
						
						if(iterator.hasNext()){
							
							SOAPHeaderElement headerEle = iterator.next();
							
							System.out.println(headerEle.getTextContent());
							
						}
					}
				}
				
			}
		} catch (SOAPException e) {
			e.printStackTrace();
		}
		
		return true;
	}
           

五、資源下載下傳

    http://download.csdn.net/detail/u013379717/7463923

繼續閱讀