简单的Jax-WS WebService实现-cxf
目录 ? 1???????定义Service 2???????服务端发布Service 2.1??????排除WebService中的某个方法 3???????客户端访问Service 4???????java2ws工具的使用 4.1??????命令行使用java2ws 4.2??????Maven使用java2ws 5???????基于Spring的Jax-ws WebService 5.1??????Service定义 5.2??????服务端发布Service 5.3??????客户端获取Service 6???????WSDL生成Java代码 6.1??????wsdl2java工具 6.2??????cxf-codegen-plugin ? ???????Jax-ws是WebService的一种规范。 1???????定义Service???????Jax-ws的WebService定义是通过注解进行的,我们必须在其WebService类的接口上使用@WebService注解进行标记。
Java代码??
? ???????如上,我们把HelloWorld定义为一个WebService,其对应有一个sayHi操作。其对应的实现类如下: ?
Java代码??
2???????服务端发布Service???????对于Jax-ws WebService而言,发布Service有两种方式。 第一种: ?
Java代码??
class?Server?{??
? 第二种:
Java代码??
new?HelloWorldImpl();??
? ???????发布之后我们就可以通过发布地址?wsdl查看WebService的定义了(WSDL是Web Service Description Language的简称,即网络服务描述语言)。通过在浏览器输入http://localhost:8080/test/jaxws/services/HelloWorld?wsdl我们可以看到如下内容: ? ?
Xml代码??
? ???????我们可以看到在上面我们的sayHi操作的参数who变成了arg0,这是因为接口在被编译为class文件的时候不能保存参数名,有时候这会影响可读性。如果需要参数名显示的可读性强一些的话,我们可以使用@WebParam来指定,如: ?
Java代码??
@WebService(serviceName="!@#$%^",?name="123456")??
??? @WebService的serviceName可以用来指定service的名称,默认情况下如果Service是通过Endpoint.publish()方法发布的则serviceName为实现类的简单名称+Service(如HelloWorldImplService),如果是通过JaxWsServerFactoryBean的create方法发布的则为接口的简单名称+Service(如HelloWorldService)。name属性可以用来指定service对应的portName,默认情况下如果Service是通过Endpoint.publish()方法发布的则portName为实现类的简单名称+Port(如HelloWorldImplPort),如果是通过JaxWsServerFactoryBean的create方法发布的则为接口的简单名称+Port(如HelloWorldPort)。 ???????除了@WebService、@WebParam之外,Jax-ws还为我们提供了一系列的注解,如@WebMethod、@OneWay。 ???????@WebMethod是用来标注在WebService的方法即操作上的,通过它我们可以指定某一个操作的操作名、使用SOAP绑定时的Action名称,以及该方法是否允许发布为WebService。@WebMethod有三个属性:operationName、action和exclude。@WebMethod还是挺有用的,当你发布的WebService中有方法不希望WebService访问的时候就可以通过@WebMethod来指定将其排除在外。下面我们来介绍一下使用WebMethod排除WebService中的一个方法。 ???????@Oneway是标注在Service接口的操作方法上的。使用@Oneway标注的方法表示它不需要等待服务端的返回,也不需要预留资源来处理服务端的返回。 ? 2.1?????排除WebService中的某个方法???????首先我们往我们的HelloWorld接口中新增一个方法sayHello。 ?
Java代码??
@WebParam(name="who")?String?who);??
? ???????对于有接口的WebService而言,@WebMethod的exclude定义必须指定在其实现类对应的需要排除的方法上,而其他属性则必须在接口方法上定义。所以我们的实现类定义如下: ?
Java代码??
?+?who;??
? ???????这样,在服务发布时就会把sayHello方法排除在外。有兴趣的朋友可以通过查看指定exclude前后的wsdl文件验证一下sayHello方法是否在exclude为true时被排除了。客户端在访问sayHello方法的时候也是不会成功的。 ? 3???????客户端访问Service ? 类似于WebService简单实现里面的ClientProxyFactoryBean,在使用Jax-ws时我们可以通过JaxWsProxyFactoryBean来访问服务,如: ? ?
Java代码??
class?Client?{??
??? 除了上面的方式之外,我们还可以这样获取Service: ?
Java代码??
? ???????在上面的代码中我们只需要有一个Service实例,就能通过它来获取真正的WebService,所以,我们如果把上面的代码改成如下形式也是可以的。 ?
Java代码??
void?main(String?args[])?{??
? ??????? 上面这种通过Service来获取WebService的方法是不适用前面介绍的简单WebService实现的,即不适用获取通过ServerFactoryBean发布的WebService。 ? 4???????java2ws工具的使用???????Cxf为我们提供了一个java2ws工具。通过该工具我们可以根据SEI(Service Endpoint Implementation的缩写)类及其相关的类来生成WebService的服务端、客户端和wsdl文件等。SEI需要是使用了@WebService标注的Service接口或类。 4.1?????命令行使用java2ws???????在Cxf根目录下的bin目录下有一个java2ws工具,我们可以在命令行下使用该指令生成相应代码。Java2ws指令后面可以接很多参数,主要有:
???????在使用java2ws指令时className是必须给定的,其他的参数都可选。java2ws将会到classpath路径下或使用-cp参数指定的classpath路径下寻找SEI类及其相关类型。 ???????示例: ???????java2ws –server com.tiantian.cxftest.sample.jaxws.HelloWorld(生成服务端代码) ???????java2ws –wsdl –cp . com.tiantian.cxftest.sample.jaxws.HelloWorld(在当前目录下寻找HelloWorld类生成wsdl文件) ? 4.2?????Maven使用java2ws???????Cxf为java2ws工具提供了一个Maven的插件,叫cxf-java2ws-plugin。所以当我们的项目是使用Maven的时候我们可以在项目的pom.xml文件中加入Cxf提供的cxf-java2ws-plugin,这样当我们执行Maven的某个操作的时候就会触发java2ws指令生成对应的代码。如:
Xml代码??
plugin>??
? ? ???????对于java2ws指令的参数可以通过configuration元素下的元素来指定。可以配置的参数如下:
? ???????使用cxf-java2ws-plugin插件生成的Java代码默认会放在项目的根目录下。 ? 5???????基于Spring的Jax-ws WebService ? 5.1?????Service定义????????Service定义跟之前的定义是一样的。 ? 5.2?????服务端发布Service???????首先在web.xml文件中定义一个CXFServlet,用于发布和拦截WebService请求。 ?
Xml代码??
<!--?Jax-ws实现?-->??
? ???????接下来在我们的WebService配置文件里面定义我们的WebService发布,即CXFServlet指定的jaxws-cxf-servlet.xml文件(默认是cxf-servlet.xml文件)。这里我们定义如下:
Xml代码??
beans?xmlns="http://www.springframework.org/schema/beans"??
5.3?????客户端获取Service???????客户端可以直接从Spring的bean配置文件中把WebService配置为一个个普通的Spring bean对象进行使用。这主要有两种方式,第一种是使用Jaxws命名空间,第二种是使用JaxWsProxyFactoryBean。 ? ? 第一种: ???????在定义之前需要往bean配置文件中引入Jax-ws的命名空间。这里我们在classpath下定义一个jaxws-cxf-client.xml文件,其内容如下所示: ?
Xml代码??
jaxws:client?id="hw"??
?? 第二种:
Xml代码??
bean?id="factoryBean"?class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"property?name="address"?value="http://localhost:8080/test/jaxws/services/HelloWorld"property?name="serviceClass"?value="com.tiantian.cxftest.sample.jaxws.HelloWorld"/>??
? ? ? ? ? ?之后我们就可以把这些定义好的WebService当做一个普通的bean对象来使用了,如: ?
Java代码??
class?SpringClient?{??
? 6???????WSDL生成Java代码 ? ???????如果我们已经有了wsdl定义文件的话,我们就可以通过wsdl文件生成对应的Java代码,包括WebService的Service类定义、服务端代码、客户端代码等。这里主要介绍两种WSDL生成Java代码的方式。 6.1?????wsdl2java工具???????wsdl2java是CXF自带的工具,在CXF根目录下的bin目录下。我们可以在命令行使用这一工具。wsdl2java命令后可以接很多参数,主要有:
? ???????如:wsdl2java –all http://localhost:8080/test/services/HelloWorld?wsdl ???????wsdl2java在生成Service实现类的时候只会生成基本的代码结构,至于里面的操作的具体逻辑还需要我们自己来实现。 6.2?????cxf-codegen-plugin???????cxf-codegen-plugin是cxf针对于maven的一个插件。当我们的项目是基于Maven的项目时,我们可以在pom.xml文件中引入cxf-codegen-plugin,如: ?
Xml代码??
>cxf-codegen-plugin>2.7.6>??
? ??????? 在上面例子中,当我们执行mvn generate-sources时就会运行wsdl2java这个指令。其配置信息是通过configuration元素来指定的。通过sourceRoot可以指定生成的Java代码的存放位置,上面我们指定了生成代码的存放位置为target目录下的generated-sources/cxf目录,该目录也是在没有指定sourceRoot时,cxf-codegen-plugin存放生成的Java代码的默认位置。每个wsdlOption元素对应于一个用来生成代码的WSDL定义。wsdl元素用于指定wsdl文件的存放位置。wsdl2java指令的其他参数可以通过wsdlOption元素下的extraargs元素来指定。如: ?
Xml代码??
extraargs>??
? ???????每一个extraarg元素代表一个参数,如果使用extraarg元素指定wsdl2java参数后面还带有参数值时,参数值也用一个extraarg来表示。如我们需要指定生成代码的包名时,我们的cxf-codegen-plugin应该这样声明: ?
Xml代码??
>-p<!--?指定包名,后面紧跟着的extraarg为对应的值?-->??
? 使用serviceName元素指定要生成Java代码的service ???????通过serviceName元素我们可以指定要针对当前wsdl文件里面的哪个service定义来生成文件。如:
Xml代码??
<!--?指定要生成代码的service名称?-->??
? 使用wsdlRoot来指定wsdl文件存放的目录 ? ???????我们知道在使用cxf-codegen-plugin的时候一个wsdlOption元素代表要生成的一个wsdl定义,当我们有多个wsdl文件时就需要定义多个wsdlOption,如: ?
Xml代码??
>${basedir}/src/main/resources/wsdl/HelloWorld.wsdl>${basedir}/src/main/resources/wsdl/HelloWorld2.wsdl>??
? ???????当我们的wsdl文件少的时候这样做还可以,但是当wsdl文件比较多的时候这样做就有点麻烦了。这个时候我们可以通过wsdlRoot元素来指定我们的wsdl文件存放的目录,cxf-codegen-plugin在扫描的时候只会扫描wsdlRoot指定的目录,而不会扫描其子目录。光指定了wsdlRoot还不能起作用,wsdlRoot必须和includes元素或者excludes元素配合使用。includes元素表示要包含哪些文件,而excludes元素表示要排除哪些文件。所以当我们要使用wsdl2java指定对wsdlRoot下的所有文件生成java代码时,我们可以这样做:
Java代码??
? ???????或者这样做: ?
Xml代码??
wsdlRoot>${basedir}/src/main/resources/wsdlexcludesexclude>null>??
? 使用defaultOptions来指定公共的选项 ???????当我们使用wsdlRoot元素来指定wsdl文件存放目录时,我们就不能再指定wsdl2java指令执行时的可选参数了。这个时候我们可以通过defaultOptions元素来指定。defaultOptions元素下指定的选项对所有的wsdlOption元素都会产生作用。如: ?
Xml代码??
defaultOptions>-allincludesinclude>helloWorld.wsdl>??
?原文 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |