文档章节

在SOAP1.2下实现HelloWord服务

柳哥
 柳哥
发布于 2014/05/06 12:27
字数 1900
阅读 1273
收藏 3

还是以前面的HelloWord服务为例子。

服务端:

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(注意:这里添加了@BindingType注解

package ch03.ts;

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

@WebService(endpointInterface = "ch03.ts.HelloWord")
@HandlerChain(file = "handler-chain-server.xml")
@BindingType(value = "http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")
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 = "同学们";
    }
}

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>

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());
    }
}

我们再通过wsimport命令生成客户端代码:

% wsimport -keep -extension -p hw5 http://localhost:7654/ts?wsdl

注意上面 -extension 这个参数

生成的客户端代码有:

HelloWord.java

package hw5;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.Action;
import javax.xml.ws.Holder;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2.4-b01
 * Generated source version: 2.2
 */
@WebService(name = "HelloWord", targetNamespace = "http://ts.ch03/")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface HelloWord {
    /**
     * @param wh
     * @param name
     * @param hf
     */
    @WebMethod
    @RequestWrapper(localName = "sayHello", targetNamespace = "http://ts.ch03/", 
        className = "hw5.SayHello")
    @ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://ts.ch03/", 
        className = "hw5.SayHelloResponse")
    @Action(input = "http://ts.ch03/HelloWord/sayHelloRequest", 
        output = "http://ts.ch03/HelloWord/sayHelloResponse")
    public void sayHello(
        @WebParam(name = "name", targetNamespace = "")
        String name,
        @WebParam(name = "wh", targetNamespace = "", mode = WebParam.Mode.INOUT)
        Holder<String> wh,
        @WebParam(name = "hf", targetNamespace = "", mode = WebParam.Mode.OUT)
        Holder<String> hf);
}

HelloWordImplService.java

package hw5;

import java.net.MalformedURLException;
import java.net.URL;
import javax.jws.HandlerChain;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2.4-b01
 * Generated source version: 2.2
 */
@WebServiceClient(name = "HelloWordImplService", targetNamespace = "http://ts.ch03/", 
    wsdlLocation = "http://localhost:7654/ts?wsdl")
@HandlerChain(file = "handler-chain.xml")
public class HelloWordImplService extends Service {

    private final static URL HELLOWORDIMPLSERVICE_WSDL_LOCATION;
    private final static WebServiceException HELLOWORDIMPLSERVICE_EXCEPTION;
    private final static QName HELLOWORDIMPLSERVICE_QNAME = 
        new QName("http://ts.ch03/", "HelloWordImplService");

    static {
        URL url = null;
        WebServiceException e = null;
        try {
            url = new URL("http://localhost:7654/ts?wsdl");
        } catch (MalformedURLException ex) {
            e = new WebServiceException(ex);
        }
        HELLOWORDIMPLSERVICE_WSDL_LOCATION = url;
        HELLOWORDIMPLSERVICE_EXCEPTION = e;
    }

    public HelloWordImplService() {
        super(__getWsdlLocation(), HELLOWORDIMPLSERVICE_QNAME);
    }

    public HelloWordImplService(WebServiceFeature... features) {
        super(__getWsdlLocation(), HELLOWORDIMPLSERVICE_QNAME, features);
    }

    public HelloWordImplService(URL wsdlLocation) {
        super(wsdlLocation, HELLOWORDIMPLSERVICE_QNAME);
    }

    public HelloWordImplService(URL wsdlLocation, WebServiceFeature... features) {
        super(wsdlLocation, HELLOWORDIMPLSERVICE_QNAME, features);
    }

    public HelloWordImplService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public HelloWordImplService(URL wsdlLocation, QName serviceName, 
        WebServiceFeature... features) {
        super(wsdlLocation, serviceName, features);
    }

    /**
     * @return
     * returns HelloWord
     */
    @WebEndpoint(name = "HelloWordImplPort")
    public HelloWord getHelloWordImplPort() {
        return super.getPort(new QName("http://ts.ch03/", "HelloWordImplPort"), 
            HelloWord.class);
    }

    /**
     * @param features
     * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  
     * Supported features not in the <code>features</code> parameter will have 
     * their default values.
     * @return
     * returns HelloWord
     */
    @WebEndpoint(name = "HelloWordImplPort")
    public HelloWord getHelloWordImplPort(WebServiceFeature... features) {
        return super.getPort(new QName("http://ts.ch03/", "HelloWordImplPort"), 
            HelloWord.class, features);
    }

    private static URL __getWsdlLocation() {
        if (HELLOWORDIMPLSERVICE_EXCEPTION!= null) {
            throw HELLOWORDIMPLSERVICE_EXCEPTION;
        }
        return HELLOWORDIMPLSERVICE_WSDL_LOCATION;
    }
}

SayHello.java

package hw5;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;

/**
 * <p>Java class for sayHello complex type.
 * <p>The following schema fragment specifies the expected content 
 * contained within this class.
 * <pre>
 * &lt;complexType name="sayHello">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string" 
 *            minOccurs="0"/>
 *         &lt;element name="wh" type="{http://www.w3.org/2001/XMLSchema}string" 
 *            minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sayHello", propOrder = {
    "name",
    "wh"
})
public class SayHello {

    protected String name;
    protected String wh;

    /**
     * Gets the value of the name property.
     * @return
     * possible object is
     * {@link String }  
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the value of the name property.
     * @param value
     * allowed object is
     * {@link String } 
     */
    public void setName(String value) {
        this.name = value;
    }

    /**
     * Gets the value of the wh property.
     * @return
     * possible object is
     * {@link String }
     */
    public String getWh() {
        return wh;
    }

    /**
     * Sets the value of the wh property.
     * @param value
     * allowed object is
     * {@link String }
     */
    public void setWh(String value) {
        this.wh = value;
    }
}

SayHelloResponse.java

package hw5;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;

/**
 * <p>Java class for sayHelloResponse complex type.
 * <p>The following schema fragment specifies the expected content contained 
 * within this class.
 * <pre>
 * &lt;complexType name="sayHelloResponse">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="wh" type="{http://www.w3.org/2001/XMLSchema}string" 
 *            minOccurs="0"/>
 *         &lt;element name="hf" type="{http://www.w3.org/2001/XMLSchema}string" 
 *            minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sayHelloResponse", propOrder = {
    "wh",
    "hf"
})
public class SayHelloResponse {

    protected String wh;
    protected String hf;

    /**
     * Gets the value of the wh property.
     * @return
     * possible object is
     * {@link String } 
     */
    public String getWh() {
        return wh;
    }

    /**
     * Sets the value of the wh property.
     * @param value
     * allowed object is
     * {@link String }
     */
    public void setWh(String value) {
        this.wh = value;
    }

    /**
     * Gets the value of the hf property.
     * @return
     * possible object is
     * {@link String }
     */
    public String getHf() {
        return hf;
    }

    /**
     * Sets the value of the hf property.
     * @param value
     * allowed object is
     * {@link String } 
     */
    public void setHf(String value) {
        this.hf = value;
    }
}

ObjectFactory.java与package-info.java省略。

UUIDHandler.java(注意代码中helem.setMustUnderstand(true)这句代码

package fibC;

import java.io.IOException;
import java.util.Set;
import java.util.UUID;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
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;

/**
 * SOAP处理程序(Handler)
 * @author FUHD
 */
public class UUIDHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean request = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if(request){
            UUID uuid = UUID.randomUUID();
            try {
                SOAPMessage msg = context.getMessage();
                SOAPEnvelope env = msg.getSOAPPart().getEnvelope();
                SOAPHeader hdr = env.getHeader();
                if(hdr == null) hdr = env.addHeader();
                QName qname = new QName("http://ts.ch03/","uuid");
                SOAPHeaderElement helem = hdr.addHeaderElement(qname);
                helem.setActor(SOAPConstants.URI_SOAP_ACTOR_NEXT);
                helem.setMustUnderstand(true);
                helem.addTextNode(uuid.toString());
                msg.saveChanges();
                msg.writeTo(System.out);
                System.out.println();
            } catch (SOAPException e1) {
                e1.printStackTrace();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        try {
            context.getMessage().writeTo(System.out);
        } catch (SOAPException e1) {
            e1.printStackTrace();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
        return true;
    }

    @Override
    public void close(MessageContext context) {
    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }
}

handler-chain.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.UUIDHandler</javaee:handler-class>
        </javaee:handler>
    </javaee:handler-chain>        
</javaee:handler-chains>

HelloWordClient.java

package hw5;

import javax.xml.ws.Holder;

public class HelloWordClient {
    public static void main(String[] args) {
        String name = "老板";
        Holder<String> wh = new Holder<String>();
        wh.value = "你好";
        Holder<String> hf = new Holder<String>();
        HelloWordImplService service = new HelloWordImplService();
        HelloWord port = service.getPort(HelloWord.class);
        port.sayHello(name, wh, hf);
        System.out.println(hf.value + "," + wh.value);
    }
}

如上例,我们只需要很少的几个步骤就可以将HelloWord服务对SOAP版本的支持由1.1版转换到1.2版。比较重要的一步就是在SIB增加注解@BindingType。

JWS还拥有一个针对标准的SOAP1.2绑定常量:

javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING

但是端点发布程序却不能够在此标准绑定版本下生成WSDL文档。变通方法就是使用非标准绑定,正如我们这个例子所演示的。当服务发布后,端点提示有下面的非致命警告:

五月 06, 2014 2:32:13 下午 com.sun.xml.internal.ws.server.EndpointFactory generateWSDL
警告: Generating non-standard WSDL for the specified binding

在前面,wsgen工具也是利用了此种方法,但是现在wsimport通过“-extension”标识指明该命令将以非标准的方式生成客户端代理程序。如上例中:

% wsimport -keep -extension -p hw5 http://localhost:7654/ts?wsdl

另外,我们在服务端使用了UUIDValidator这个Handler程序,因此修改UUIDvalidator,展示SOAP1.2的关键特点。通常在一个SOAP1.2报头中使用属性mustUnderstand。如上例,直接在setActor方法调用的后面:

 helem.setActor(SOAPConstants.URI_SOAP_ACTOR_NEXT);
 helem.setMustUnderstand(true);        //SOAP1.2

根据这个例子抓取它的一个请求消息内容:

<?xml version="1.0" ?>
    <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
        <S:Header>
            <uuid xmlns="http://ts.ch03/" 
                    xmlns:env="http://www.w3.org/2003/05/soap-envelope" 
                    env:mustUnderstand="true" 
                    env:role="http://schemas.xmlsoap.org/soap/actor/next">
                03d7d564-b1b1-457a-9129-069a82acb8d6
            </uuid>
        </S:Header>
        <S:Body>
            <ns2:sayHello xmlns:ns2="http://ts.ch03/">
                <name xmlns="">老板</name>
                <wh xmlns="">你好</wh>
            </ns2:sayHello>
        </S:Body>
</S:Envelope>

从上面请求消息可以看到:env:nustUnderstand="true"已经存在于uuid的属性中。

另外,在端点程序生成的WSDL文档的绑定部分反映了SOAP1.1改为SOAP1.2后发生的变化:

<binding name="HelloWordImplPortBinding" type="tns:HelloWord">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <operation name="sayHello">
        <soap12:operation soapAction=""/>
        <input>
            <soap12:body use="literal"/>
        </input>
        <output>
            <soap12:body use="literal"/>
        </output>
    </operation>
</binding>

考虑到SOAP1.1和SOAP1.2之间差别不大,以及SOAP1.1已经是事实上的标准,除非不得已采用SOAP1.2版外,持续支持SOAP1.1版本是非常有意义的。最后,SOAP1.2向后兼容SOAP1.1版。

© 著作权归作者所有

柳哥
粉丝 207
博文 405
码字总数 347782
作品 0
杭州
技术主管
私信 提问
添加一个服务器端SOAP Handler

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

柳哥
2014/05/05
1K
0
SOAP1.1与SOAP1.2

目前SOAP协议有两个版本,分别是1.1和1.2。通常开发web服务时,SOAP1.1和SOAP1.2之间的差异影响有限,尤其是基于JAX-WS。当然也有例外,比如,在这两个版本中,SOAP消息头结构上的差异,可能...

柳哥
2014/04/12
1K
0
JDK6开发原生webservice

webservice接口开发有用到Axis2、XFire、CXF等框架发布通过获取相关的wsdl文件即可实现远程通讯数据交互。 Axis2配合相关的IDE生成服务并发布到服务器上面相当简单和根据选择其中之一的wsdl引...

stellarzhou
2013/06/27
617
3
零配置socket消息通讯容器EC

EC全称是elastic communication,是基于c#实现的Socket网络通讯服务容器,支持windows .Net和mono。通过EC容器可以让开发人员在不了解Socket网络通讯知识和不进行任何配置的情况即可把逻辑应用...

泥水佬
2014/09/22
204
0
Web服务框架--Apache Axis2

对Axis1进行了重新设计,支持SOAP1.2/REST以及更多 在线API doc:http://tool.oschina.net/apidocs/apidoc?api=axis-1.6.2...

匿名
2008/09/13
24.1K
4

没有更多内容

加载失败,请刷新页面

加载更多

CSS盒子模型

一、什么叫框模型 页面元素皆为框(盒子) 定义了元素框处理元素内容,内边距,外边距以及边框的计算方式 二、外边距 围绕在元素边框外的空白距离(元素与元素之间的距离) 语法:margin,定...

wytao1995
今天
4
0
Replugin借助“UI进程”来快速释放Dex

public static boolean preload(PluginInfo pi) { if (pi == null) { return false; } // 借助“UI进程”来快速释放Dex(见PluginFastInstallProviderProxy的说明) return PluginFastInsta......

Gemini-Lin
今天
4
0
Hibernate 5 的模块/包(modules/artifacts)

Hibernate 的功能被拆分成一系列的模块/包(modules/artifacts),其目的是为了对依赖进行独立(模块化)。 模块名称 说明 hibernate-core 这个是 Hibernate 的主要(main (core))模块。定义...

honeymoose
今天
4
0
精华帖

第一章 jQuery简介 jQuery是一个JavaScript库 jQuery具备简洁的语法和跨平台的兼容性 简化了JavaScript的操作。 在页面中引入jQuery jQuery是一个JavaScript脚本库,不需要特别的安装,只需要...

流川偑
今天
7
0
语音对话英语翻译在线翻译成中文哪个方法好用

想要进行将中文翻译成英文,或者将英文翻译成中文的操作,其实有一个非常简单的工具就能够帮助完成将语音进行翻译转换的软件。 在应用市场或者百度手机助手等各大应用渠道里面就能够找到一款...

401恶户
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部