1、定义Service
Jax-ws的WebService定义是通过注解进行的,我们必须在其WebService类的接口上使用@WebService注解进行标记
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface IWebService {
@WebMethod
public void calData(@WebParam(name = "num") int num);
@WebMethod
public String getString(@WebParam(name = "message") String message);
}
@WebService的其它注解属性可以获取默认值,@WebParam 可以使XML生成的参数名更直观,此处加了@WebParam之后,在客户端写接口的时候也需要加上。
实现webService的接口:
@WebService(endpointInterface = "test.interfaces.IWebService")
public class WebServiceImpl implements IWebService {
@Override
public void calData(int num) {
int data = 0;
for (int i = 0; i < num + 1; i++) {
data = num + data;
}
System.err.println("运行结果为 " + data);
}
@Override
public String getString(String message) {
if (message == null || "".equals(message)) {
return null;
} else {
return "the message is :" + message;
}
}
}
实现类中需要指定实现接口的路径 @WebService(endpointInterface = "test.interfaces.IWebService")
2、服务端发布WebService
private final static String ADDRESS = "http://127.0.0.1:8899/test/webservice";
public static void main(String[] args) {
IWebService service = new WebServiceImpl();
Endpoint.publish(ADDRESS, service);
}
发布完之后访问路径 http://127.0.0.1:8899/test/webservice?wsdl,可以看到
<definitions targetNamespace="http://impl.test/" name="WebServiceImplService">
<import namespace="http://interfaces.test/"
location="http://127.0.0.1:8899/test/webservice?wsdl=1" />
<binding name="WebServiceImplPortBinding" type="ns1:IWebService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="rpc" />
<operation name="getString">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" namespace="http://interfaces.test/" />
</input>
<output>
<soap:body use="literal" namespace="http://interfaces.test/" />
</output>
</operation>
<operation name="calData">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" namespace="http://interfaces.test/" />
</input>
<output>
<soap:body use="literal" namespace="http://interfaces.test/" />
</output>
</operation>
</binding>
<service name="WebServiceImplService">
<port name="WebServiceImplPort" binding="tns:WebServiceImplPortBinding">
<soap:address location="http://127.0.0.1:8899/test/webservice" />
</port>
</service>
</definitions>
因为是实现的接口,所以继续访问http://127.0.0.1:8899/test/webservice?wsdl=1,可以看到具体的方法和方法的参数
<definitions targetNamespace="http://interfaces.test/">
<types />
<message name="getString">
<part name="message" type="xsd:string" />
</message>
<message name="getStringResponse">
<part name="return" type="xsd:string" />
</message>
<message name="calData">
<part name="num" type="xsd:int" />
</message>
<message name="calDataResponse" />
<portType name="IWebService">
<operation name="getString" parameterOrder="message">
<input message="tns:getString" />
<output message="tns:getStringResponse" />
</operation>
<operation name="calData" parameterOrder="num">
<input message="tns:calData" />
<output message="tns:calDataResponse" />
</operation>
</portType>
</definitions>
3、客户端访问WebService
对于非本服务访问该WebService,需要重新定义一个接口,此处注解的@WebService 需要指定 targetNamespace,为http://127.0.0.1:8899/test/webservice?wsdl=1中生成的XML的targetNamespace,targetNamespace也可以在服务端指定;
@WebService(targetNamespace = "http://interfaces.test/")
public interface ILocalWebService {
@WebMethod
public void calData(@WebParam(name = "num") int num);
@WebMethod
public String getString(@WebParam(name = "message") String message);
}
在使用Jax-ws时我们可以通过JaxWsProxyFactoryBean来访问服务
public static void main(String[] args) {
JaxWsProxyFactoryBean jwpFactory = new JaxWsProxyFactoryBean();
jwpFactory.setAddress("http://127.0.0.1:8899/test/webservice?wsdl");
jwpFactory.setServiceClass(ILocalWebService.class);
ILocalWebService hw = (ILocalWebService) jwpFactory.create();
hw.calData(29);
}
也可以使用Service来访问服务
public static void main(String[] args) {
try {
URL url= new URL("http://127.0.0.1:8899/test/webservice?wsdl");
// Qname qname是qualified name 的简写
// 2.构成:由名字空间(namespace)前缀(prefix)以及冒号(:),还有一个元素名称构成
// 由发布的wsdl可知namespace为 http://impl.test/
QName sname = new QName("http://impl.test/","WebServiceImplService");
Service service = Service.create(url, sname);
// 获取Service对应的port,从wsdl中获取的
QName pname = new QName("http://impl.test/", "WebServiceImplPort");
ILocalWebService pservice = service.getPort(pname, ILocalWebService.class);
pservice.calData(29);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
4、异常处理
(1)、服务端发布WebService时报错 runtime modeler error: Wrapper class test.interfaces.jaxws.GetString is not found. Have you run APT to generate them?
需要在WebService注解下加上 @SOAPBinding(style = SOAPBinding.Style.RPC)
(2)、客户端访问WebService时报错 java.lang.NoClassDefFoundError: org/apache/ws/commons/schema/utils/NamespacePrefixList
客户端使用 JaxWsProxyFactoryBean 访问远程WebService时,需要添加额外的jar包,XmlSchema-1.4.7.jar和 wsdl4j-1.6.2.jar。