开发过程如下:
- 保证使用的是jdk6。
编写开放出来的接口并实现,如下
public interface UserService { public String saveUser(String username,String password); } import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.sql.DataSource; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; @WebService(name = "UserService", serviceName = "UserService", targetNamespace = "http://cas.webservice.user/client") @SOAPBinding(style = SOAPBinding.Style.RPC) public class UserServiceImpl implements UserService { private DataSource dataSource; private SimpleJdbcTemplate jdbcTemplate; private UserServiceImpl() { } private UserServiceImpl(DataSource dataSource) { this.dataSource = dataSource; this.jdbcTemplate = new SimpleJdbcTemplate(dataSource); } public String saveUser(String username, String password) { int count = jdbcTemplate.update( "insert userinfo(userName,password) values(?,?)", username, password); return username + " : " + password; } }
发布webservice。如下
Endpoint.publish("http://127.0.0.1:9527/UserService", ctx.getBean("wsUserService"));
注:这里假如不用spring的话 直接new UserServiceImpl()。
在你的客户端位置键入命令:
wsimport -keep http://127.0.0.1:9527/UserService?wsdl
此时会在此目录生成 cas/webservice/user/client/ 此文件夹,里面生成了你需要的客户 端调用类 UserService, UserService_Service。
调用方式如下:
UserService_Service userService=new UserService_Service(); UserService user=userService.getUserServicePort(); System.out.println(user.saveUser("afei2","yes ido"));
注意的地方:
- 在发布的类(userServiceImpl)中假如带有接口属性,并且有其getter/setter,那么发 布会失败。
- 发布的ip假如是127.0.0.1的话localhost是不能访问的,是多少就是多少,不过实际项 目也不会这样的。
- 有的客户端调用的时候也会报错,比如Provider com.sun.xml.ws.spi.ProviderImpl not found这个异常,我跟踪代码进去,发觉报错的那个jdk版本的Provider和我成功的 jdk版本是不一样的,在网上搜无答案,直说缺包,我感觉是个小bug。其他的没什么问 题。
- 因为这里没用任何webservice框架,没有把它嵌入tomcat(假如你需要在tomcat环境中), 所以端口另开,不能是8080。
资料 JDK1.6 中自带了 webservice 的功能
因为集成了JAX-WS,这非常方便,不用再用第三方包来开发了。
下面我们开始构建:
- 先用Eclipse建立一个动态网站,注意需要生成web.xml,建工程的时候不要忘记勾选;
- 建立类实现Web Services接口,下面是一个简单定义Web Services接口的实现类:
代码
package javaWebServiceTest; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.WebParam.Mode; import javax.jws.soap.SOAPBinding; import javax.jws.soap.SOAPBinding.Style; import javax.jws.soap.SOAPBinding.Use; import webServiceInterface.Person; @WebService(name="SayHello", portName="SayHellowServicePort", serviceName="SayHelloServiceName", targetNamespace="http://www.webservice.com") @SOAPBinding(style = Style.RPC,use = Use.LITERAL) public class ChService { @WebMethod(action="sayHello", operationName="saySomeWord") @WebResult(name="Person", partName="PersonName") public Person sayHelloWord(@WebParam(name="paramA", partName="p1", mode = Mode.IN)String name){ Person persons = new Person(); persons.setName("My name is " +name); return persons; } } // Person类 package webServiceInterface; public class Person { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
这样,我们基本上就实现了 webservice 的构建,是不是感觉不是很难,跟写普通的java方 法一样,其实 jdk 自带的 webservice 是通过注释注入方法实现的。所以上面那些以"@"符 号开头的都是非常重要的,也是必须的。
下面我们来配置我们写的WebService到Apache中:
上面第一步,我们生成了一个 web.xml 类,我们向 <web-app> 节点里面加入以下内容:
<listener> <listener-class> com.sun.xml.ws.transport.http.servlet.WSServletContextListener </listener-class> </listener> <servlet> <servlet-name>TestService</servlet-name> <servlet-class> com.sun.xml.ws.transport.http.servlet.WSServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>TestService</servlet-name> <url-pattern>/jdkService</url-pattern> </servlet-mapping>
在 web.xml 的目录中再建立一个 sun-jaxws.xml 来配置 endpoint 的相关内容。
<?xml version="1.0" encoding="UTF-8"?> <endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'> <endpoint name='TestService' implementation='javaWebServiceTest.ChService' binding="http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/" url-pattern='/jdkService'/> </endpoints>
好了,配置完了。把我们建立的项目加入到apache7.0中,然后启动。
在浏览器输入:http://localhost:8080/TestWebService/jdkService?wsdl,便可 以访问到。
如图:
现在我们来说说那些以"@"符号开头的内容。
@WebService(name="SayHello", portName="SayHellowServicePort", serviceName="SayHelloServiceName", targetNamespace="http://www.possystem.com")
name: SayHello
用户实例化用,例:
private WinService.SayHelloClient win = new winformService.WinService.SayHelloClient();
WSDL中:<portType name="SayHello">
serviceName: SayHelloServiceName
指定Web Service的名称 ,
WSDL中:<service name="SayHelloServiceName">
portName: SayHellowServicePort
WSDL中:<port name="SayHellowServicePort" binding="tns:SayHellowServicePortBinding">
wsdlLocation:wsdlLocation 是引用预先存在的 WSDL 文件的 URL(相对或绝对)。
targetNamespace:wsdl命名空间
@SOAPBinding(style = Style.RPC,use = Use.LITERAL)
style: 定义发送到 Web Service 的消息和从 Web Service 发送的消息的编码样式。
Document和RPC两种形式
默认值: javax.jws.soap.SOAPBinding.Style.DOCUMENT
use: 定义发送到 Web Service 的消息和从 Web Service 发送的消息的格式样式。
ENCODED和 LITERAL两种形式
默认值: javax.jws.soap.SOAPBinding.Use.LITERAL
@WebMethod(action="sayHello", operationName="saySomeWord")
action: sayHello
此操作的动作。 对于 SOAP 绑定,此方法可确定 soap 动作的值。
WSDL中: <soap12:operation soapAction="sayHello" />
operationName: sayHelloWord1
与此方法匹配的 wsdl:operation 的名称。
此名称也用于客户端调用的方法的名称。
exclude: 将某一方法标记为不作为一个 web 方法公开。
@WebResult(name="Person", partName="PersonName")
name: Person
返回值的名称。 如果操作是 rpc 样式,并且partName尚未指定, 表示此返回值的 wsdl:part 的名称
WSDL中:<part name="Person" type="tns:person" />
partName: PersonName
表示此返回值的 wsdl:part 的名称。
此名称只在操作是 rpc 样式,或者操作是文档样式且参数样式为 BARE 时使用。
WSDL中:<part name="PersonName" type="tns:person" />
public Person sayHelloWord(@WebParam(name="paramA", partName="p1", mode = Mode.IN)String name){……}
name: paramA
如果该操作是 rpc 样式的,并且尚未指定 @WebParam.partName,则此名称是表示参数的 wsdl:part 的名称。
如果该操作是文档样式的,或者参数映射到某一个头,则此名称是表示参数的 XML 元素的本地名称。
如果操作是文档样式的,参数样式为 BARE 并且模式为 OUT 或 INOUT,则必须指定一个名称。
客户端调用时参数名称显示该值。
partName: p1
表示此参数的 wsdl:part 的名称。
此名称仅在操作是 rpc 样式,或者操作是文档样式且参数样式为 BARE 时使用。
WSDL中:
<message name="sayHelloWord1">
<part name="p1" type="xsd:string" />
</message>
客户端调用时参数名称显示该值。
这个主要是根据样式来。
mode:参数的流向(IN、OUT 或 INOUT 之一)。