在SOAP1.2下实现HelloWord服务

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

服务端:

HelloWord.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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注解

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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

?
1
2
3
4
5
6
7
8
9
<? 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

?
1
2
3
4
5
6
7
8
9
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命令生成客户端代码:

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

注意上面 -extension 这个参数

生成的客户端代码有:

HelloWord.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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)这句代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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

?
1
2
3
4
5
6
7
8
9
<? 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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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绑定常量:

?
1
javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING

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

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

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<? 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后发生的变化:

?
1
2
3
4
5
6
7
8
9
10
11
12
< 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版。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值