1.分析协议文件
上一章发布了WS服务,于是在浏览器地址栏输入http://localhost:8888/msg?wsdl访问,将得到如下协议文件,该协议文件不仅是WS客户端调用程序员参考手册,同时也是生成WS客户端调用代码必不可少的依据
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://ws.cjc.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.cjc.cn/"
name="MessageImplService">
<types></types>
<message name="getMsg">
<part name="arg0" type="xsd:string"></part>
</message>
<message name="getMsgResponse">
<part name="return" type="xsd:string"></part>
</message>
<portType name="Message">
<operation name="getMsg" parameterOrder="arg0">
<input message="tns:getMsg"></input>
<output message="tns:getMsgResponse"></output>
</operation>
</portType>
<binding name="MessageImplPortBinding" type="tns:Message">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="rpc"></soap:binding>
<operation name="getMsg">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://ws.cjc.cn/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://ws.cjc.cn/"></soap:body>
</output>
</operation>
</binding>
<service name="MessageImplService">
<port name="MessageImplPort" binding="tns:MessageImplPortBinding">
<soap:address location="http://localhost:8888/msg"></soap:address>
</port>
</service>
</definitions>
对这个文件从下往上分析,service标签表示服务名称,在客户端调用代码中对应cn.cjc.ws.MessageImplService类,该标签下的子标签port在客户端调用代码中对应cn.cjc.ws.MessageImplService#getMessageImplPort方法,该方法用来获取服务接口。binding标签是连接service标签和portType标签的桥梁,portType标签在客户端调用代码中对应cn.cjc.ws.Message接口,剩下的多个message接口用来说明方法参数类型和返回值类型。
2.个性化协议文件
a)接口上的注解添加如下属性
package cn.cjc.ws;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(name = "name")
// jdk1.6.0_22版本以下的不加这个注解可能无法发布WS服务
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface Message {
String getMsg(@WebParam(name = "username") String name);
}
b)实现类上的注解添加如下属性
package cn.cjc.ws;
import javax.jws.WebService;
@WebService(endpointInterface = "cn.cjc.ws.Message", portName = "portName", serviceName = "serviceName")
public class MessageImpl implements Message {
@Override
public String getMsg(String name) {
return name + ",欢迎学习WebService";
}
}
c)发布服务然后在浏览器重新生成的协议文件如下
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://ws.cjc.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.cjc.cn/"
name="serviceName">
<types></types>
<message name="getMsg">
<part name="username" type="xsd:string"></part>
</message>
<message name="getMsgResponse">
<part name="return" type="xsd:string"></part>
</message>
<portType name="name">
<operation name="getMsg" parameterOrder="username">
<input message="tns:getMsg"></input>
<output message="tns:getMsgResponse"></output>
</operation>
</portType>
<binding name="portNameBinding" type="tns:name">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="rpc"></soap:binding>
<operation name="getMsg">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://ws.cjc.cn/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://ws.cjc.cn/"></soap:body>
</output>
</operation>
</binding>
<service name="serviceName">
<port name="portName" binding="tns:portNameBinding">
<soap:address location="http://localhost:8888/msg"></soap:address>
</port>
</service>
</definitions>
对应着之前的那份协议文件可以发现,WebService注解中的name属性改变portType标签,serviceName属性改变service标签,portName属性改变port标签
其实WebService注解共有6个属性,endpointInterface、serviceName、portName只能用在实现类上,另外3个是name、targetNamespace、wsdlLocation接口和实现类都可以用,需要注意的是,targetNamespace要么不配置,要么必须同时在接口和实现类上配置。