?
服务器端的Java类若要成为一个实现了Web Service的bean,它需要遵循下边这些原则:这个类必须是public类、不能是final的或者abstract、必须有一个公共的默认构造函数、绝对不能有finalize()方法。若要成为一个实现了Web Service的Bean的方法必须遵循这些原则:
这个方法必须是public,它的参数、返回值、和异常在每个JAX RPC规范中都描述了Java转化成XML/WSDL映射文件的规则,参数和返回值可以是原始类型、数组等等。
这个方法必须是public,它的参数、返回值、和异常在每个JAX RPC规范中都描述了Java转化成XML/WSDL映射文件的规则,参数和返回值可以是原始类型、数组等等。
下面是服务器端的类HelloWorld.java:
package test.jws.service; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; @WebService(targetNamespace = "http://www.jwstest.org") @SOAPBinding(style = SOAPBinding.Style.RPC) publicclass HelloWorld { @WebMethod(action="toSayHello",operationName="toSayHello",exclude=false) @WebResult(name="returnWord")//自定义该方法返回值在WSDL中相关的描述 public String sayHello(@WebParam(name="userName")String userName) { return"Hello:" + userName; } @WebMethod publicint getExp(int i, int j) { return i / j; } }?
这是服务器端普通的业务类,通过@WebService、@WebMethod等注释描述来生成WSDL文件。
STEP 2,执行wsgen命令
本例中到HelloWorld类所在的目录中新建一个命名为wsdl的文件夹,运行:wsgen -cp ./bin -r ./wsdl -s ./src -d ./bin -wsdl test.jws.service.HelloWorld。执行后会在wsdl文件夹中生成HelloWorld的wsdl描述文件,src文件夹中生成依赖类,如异常说明类,bin中生成依赖类的class文件
STEP 3,发布Web Service Bean
启动服务类StartService.java:
package test.jws.service; import javax.xml.ws.Endpoint; publicclass StartService { publicstaticvoid main(String[] args) { Endpoint.publish("http://localhost:8080/webservice/hws", new HelloWorld()); } }? ? ?此类很简单,能过Endpoint类的publish()方法发布实例发布地址为:
http://localhost:8080/webservice/hws,必需明确指明http协议,主机IP 地址及端口号,在IE上输入?http://localhost:8080/webservice/hws?wsdl返回以下内容说明发布成功
<?xml version="1.0" encoding="UTF-8" ?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://www.jwstest.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://www.jwstest.org" name="HelloWorldService"> <types /> <message name="toSayHello"> <part name="userName" type="xsd:string" /> </message> <message name="toSayHelloResponse"> <part name="returnWord" type="xsd:string" /> </message> <message name="getExp"> <part name="arg0" type="xsd:int" /> <part name="arg1" type="xsd:int" /> </message> <message name="getExpResponse"> <part name="return" type="xsd:int" /> </message> <portType name="HelloWorld"> <operation name="toSayHello" parameterOrder="userName"> <input message="tns:toSayHello" /> <output message="tns:toSayHelloResponse" /> </operation> <operation name="getExp" parameterOrder="arg0 arg1"> <input message="tns:getExp" /> <output message="tns:getExpResponse" /> </operation> </portType> <binding name="HelloWorldPortBinding" type="tns:HelloWorld"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> <operation name="toSayHello"> <soap:operation soapAction="toSayHello" /> <input> <soap:body use="literal" namespace="http://www.jwstest.org" /> </input> <output> <soap:body use="literal" namespace="http://www.jwstest.org" /> </output> </operation> <operation name="getExp"> <soap:operation soapAction="" /> <input> <soap:body use="literal" namespace="http://www.jwstest.org" /> </input> <output> <soap:body use="literal" namespace="http://www.jwstest.org" /> </output> </operation> </binding> <service name="HelloWorldService"> <port name="HelloWorldPort" binding="tns:HelloWorldPortBinding"> <soap:address location="http://localhost:8080/webservice/hws" /> </port> </service> </definitions>?
STEP 4,生成客户端执行类
在cmd命令中执行 wsimport -d ./bin -s ./src - p test.jws.client.ref
http://10.168.189.182:8080/webservice/hws?wsdl?后在在src目录下生成客户端调用的两个类:
?????? test.jws.client.ref.HelloWorld.java?根据wsdl描述生成的客户端执行类
test.jws.client.ref.HelloWorldServices.java 通过此类负责解悉wsdl初始化客户端HelloWorld实例
在bin目录下生成对应的类文件。
???????注意:执行wsimport命令时STEP 3的服务必需启动,否则无法生成
STEP 4,客户端调用
客户端调用过程ClientRun.java:
package test.jws.client; import test.jws.client.ref.*; publicclass ClientRun { /** *@paramargs */ publicstaticvoid main(String[] args) { HelloWorldService hws = new HelloWorldService(); HelloWorld hw = hws.getHelloWorldPort(); System.out.println(hw.getExp(9, 3)); System.out.println(hw.toSayHello("zhuoshiyao")); } }?
启动STEP 3中的服务,运行ClientRun后,制控台输出:
3
Hello:zhuoshiyao
注意:经测试,用Endpoint.publish("http://localhost:8080/webservice/hws", new HelloWorld())方式在Tomcat6中发布,不会存在端口号与路径冲突。
JKD6?中定义的Web Service注释
1.????????@WebService 标注要暴露为Web Services的类或接口 ,用于申修饰类或接口,包含属性
targetNamespace 定义命名空间,默认为”http://”+”包名倒排”
name?Web Service?的名称,默认为类名,例如:
<definitions targetNamespace="http://service.jws.test/"
name="HelloWorldService">
portName?Web Service?的端口名称
serviceName?Web Service?的服务名称,例如
????????????? ????? <service name="HelloWorldService">
<port name="HelloWorldPort"
binding="tns:HelloWorldPortBinding">
????? ...
??????????? ????? </port>
????? ????? </service>
wsdlLocation描述服务的预定义 WSDL 的位置
endpointInterface定义服务抽象 Web Service 协定的服务端点接口的完整名称????
2.????????@SOAPBinding 定义Web Service 在SOAP中的消息协议,用于申修饰类或接口,包含属性
style 定义消息的编码类型
user 定义消息的格式化类型
3.????????@WebMethod 定义Web Service运作的方法,包含属性
action 操作的活动
operationName与此方法匹配的 wsdl:operation 的名称
exclude 标注此方法是否被暴露,默认为false
4.????????@WebResult 定义返回值,返回值类型不能为接口类或抽象类,而且必须有个不带参的构造函数,包含属性
name返回值的名称
partName表示此返回值的 wsdl:part 的名称
targetNamespace返回值的 XML 名称空间
header如果为 true,则结果是从消息头而不是消息正文获取的
5.????????@WebParam 定义方法的参数,参数类型不能为接口类或抽象类,而且必须有个不带参的构造函数,包含属性
name参数名称
partName表示此参数的 wsdl:part 的名称
targetNamespace参数的 XML 名称空间
header如果为 true,则结果是从消息头而不是消息正文获取的
mode参数的流向(IN、OUT 或 INOUT 之一)
wsgen与wsimport命令说明
wsgen命令的主要功能是用来生成合适的JAX-WS。它读取Web Service的终端类文件,在我们的例子中就是test.jws.service.HelloWorld,同时生成所有用于发布Web Service所依赖的源代码文件和经过编译过的二进制类文件,通常Web Service Bean中用到的异常类会另外生成一个描述Bean。它还能生成WSDL和符合规范的HelloWorld类Web Service。wsgen从资源文件生成一个完整的操作列表并验证是合法的。如果Web Service Bean中的主法有申明抛出异常,这一步是必需的,否则服务器无法绑定该对像。
命令参数说明:
-cp 定义classpath
-r 生成 bean的wsdl文件的存放目录
-s 生成发布Web Service的源代码文件的存放目录(如果方法有抛出异常,则会生成该异常的描述类源文件)
-d 生成发布Web Service的编译过的二进制类文件的存放目录(该异常的描述类的class文件)
?????? wsimport命令的主要功能是根据wsdl文件生成客户端存根及框架,负责与Web Service 服务器通信,并在将其封装成实例,客户端可以直接使用,就像使用本地实例一样。
命令参数说明:
-d 生成客户端执行类的class文件的存放目录
-s 生成客户端执行类的源文件的存放目录
-p 定义生成类的包名