添加一个服务器端SOAP Handler

原创
2014/05/05 22:06
阅读数 1.3K

我们接着以前面的blog【HelloWord例子:客户端向请求SOAP消息中注入报头块(使用配置方式)】为例。在该例子基础上添加服务端的Handler,用来验证UUID值。

为了使例子更完整,我们需要一个服务端的SOAP Handler来处理客户端向出站SOAP消息中插入的报头块。我们来看看服务端都有什么变化。

HelloWord.java:

package ch03.ts;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.Holder;

@WebService
public interface HelloWord {

    @WebMethod
    void sayHello(@WebParam(name="name") String name,
            @WebParam(name="wh",mode=WebParam.Mode.INOUT) Holder<String> wh,
            @WebParam(name="hf",mode=WebParam.Mode.OUT) Holder<String> hf);
}

HelloWordImpl.java(注意:这里添加了@HandlerChain(file="handler-chain-server.xml")注解,也就是服务器端的注解是添加在SIB上的):

package ch03.ts;

import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.xml.ws.Holder;

@WebService(endpointInterface = "ch03.ts.HelloWord")
@HandlerChain(file = "handler-chain-server.xml")
public class HelloWordImpl implements HelloWord {

    @Override
    public void sayHello(String name, Holder<String> wh, Holder<String> hf) {
        System.out.println(name + "!" + wh.value);
        wh.value = "你们好";
        hf.value = "同学们";
    }
}

HelloWordPublisher.java:

package ch03.ts;

import javax.xml.ws.Endpoint;

public class HelloWordPublisher {
    public static void main(String[] args) {
        Endpoint.publish("http://localhost:7654/ts", new HelloWordImpl());
    }
}

新增加的服务器端Handler:UUIDValidator.java

package fibC;

import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import javax.xml.namespace.QName;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;

/**
 * 服务器端验证UUID值
 * @author fuhd
 */
public class UUIDValidator implements SOAPHandler<SOAPMessageContext> {
    
    private static final int UUIDVARIANT = 2;    //layout
    private static final int UUIDVERSION = 4;    //version

    @SuppressWarnings({ "rawtypes"})
    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean resp = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if(!resp){
            try {
                SOAPMessage msg = context.getMessage();
                SOAPEnvelope env = msg.getSOAPPart().getEnvelope();
                SOAPHeader hdr = env.getHeader();
                if(hdr == null)
                    generateSOAPFault(msg, "No message header.");
                Iterator it = hdr.extractHeaderElements(SOAPConstants.URI_SOAP_ACTOR_NEXT);
                if(it == null || !it.hasNext())
                    generateSOAPFault(msg, "No header block for next actor.");
                Node next = (Node)it.next();
                String value = (next == null)?null:next.getValue();
                if(value == null)
                    generateSOAPFault(msg, "No UUID in header block.");
                UUID uuid = UUID.fromString(value.trim());
                if(uuid.variant() != UUIDVARIANT || uuid.version() != UUIDVERSION)
                    generateSOAPFault(msg, "Bad UUID variant or version");
                System.out.println(value.trim());
            } catch (SOAPException e) {
                e.printStackTrace();
            } 
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return true;
    }

    @Override
    public void close(MessageContext context) {}

    @Override
    public Set<QName> getHeaders() {
        return null;
    }
    
    private void generateSOAPFault(SOAPMessage msg,String reason){
        try {
            SOAPBody body = msg.getSOAPPart().getEnvelope().getBody();
            SOAPFault fault = body.addFault();
            fault.setFaultString(reason);
            throw new SOAPFaultException(fault);
        } catch (SOAPException e) {
            e.printStackTrace();
        }
    }
}

handler-chain-server.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<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>fibC.UUIDValidator</javaee:handler-class>
        </javaee:handler>
    </javaee:handler-chain>        
</javaee:handler-chains>

UUIDValidator在服务层校验入站的SOAP消息。这个校验器需要访问整个SOAP消息,而不仅仅是SOAP消息体,因此它必须实现SOAPHandler接口,而不是一个LogicalHandler接口。

注意,上例中任何一部分校验失败均会抛出一个SOAPFaultException异常,重新包装为SOAP1.1和SOAP1.2错误。通过对错误的重新包装,我们可以忽略SOAP两个不同版本之间的差异。

展开阅读全文
打赏
1
2 收藏
分享
加载中
更多评论
打赏
0 评论
2 收藏
1
分享
返回顶部
顶部