天天看点

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

继续阅读