一、对比Axis2和CXF
jws的发布对java webservice框架产生了巨大的影响,经过大浪淘沙,目前java开发webservice的框架主要包括axis2和cxf。
axis2和cxf都是apache旗下的产品,但是其目的不同,导致webservice开发方法也不一样。两个框架都得到了开发者的支持。有必要对二者进行以下对比。
Axis2 | CXF | |
---|---|---|
目标 | WebService引擎 | 简易的SOA框架,可以作为ESB |
ws* 标准支持 | 不支持WS-Policy | WS-Addressing,WS-Policy, WS-RM, WS-Security,WS-I Basic Profile |
数据绑定支持 | XMLBeans、JiBX、JaxMe 、JaxBRI、ADB | JAXB, Aegis, XMLBeans, SDO, JiBX |
spring集成 | 不支持 | 支持 |
应用集成 | 困难 | 简单 |
多语言 | 支持C/C++ | 不支持 |
部署 | web应用 | 嵌入式 |
服务监控和管理 | 支持 | 不支持 |
结论:
- 如果希望以一种一致的方式实现webservice,特别是有跨语言的需求时,应该使用Axis2
- 如果需要在现有的java程序(包括web应用)中增加webservice支持,应该使用CXF
二、编写服务类
从Java6开始,WebService API从Java EE复制到了Java SE。并遵循了一系列的标准,比如JSR181(Web Service 元数据),JSR224(JAX-WS,基于XML的WebService API),JSR67(SAAJ,SOAP附件标准)等。 并分别定义到javax.jws, javax.xml.ws 和 javax.xml.soap包中。
JSR181支持使用标注(annotation)来定义WebService。在javax.jws中主要的标注类包括:
标注 | 说明 |
---|---|
WebService | 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口 |
WebMethod | 定制Web Service方法 |
WebParam | 定制Web Service方法的参数 |
WebResult | 定制Web Service方法的返回值 |
SOAPBinding | 指定WebService的SOAP映射样式 |
使用标注可以在不改变代码逻辑的前提下让外部代码能够获得更多的元数据。下面就用javax.jws定义的标注来声明一个WebService
- pom增加CXF依赖
<
dependencies
>
<
dependency
>
<
groupId
>
org.apache.cxf
</
groupId
>
<
artifactId
>
apache-cxf
</
artifactId
>
<
version
>
${cxf.version}
</
version
>
<
type
>
pom
</
type
>
</
dependency
>
</
dependencies
>
<
properties
>
<
cxf.version
>
2.2.4
</
cxf.version
>
</
properties
>
- 增加接口服务
package
com.dogiant.demo;
import
javax.jws.WebService;
@WebService
public
interface
CXFDemo {
public
String sayHello(String
foo
);
}
- 实现服务类
package
com.dogiant.demo;
import
javax.jws.WebService;
@WebService
(endpointInterface =
"com.dogiant.demo.CXFDemo"
, serviceName =
"cxfDemo"
)
public
class
CXFDemoImpl
implements
CXFDemo {
@Override
public
String sayHello(String
foo
) {
return
"hello "
+
foo
;
}
}
三、
以endpoint发布
到目前为止,使用的都是标准Java SE中的东西。下面要开始依赖CXF实现一些功能。
首先是服务的发布。CXF不仅支持通过Web容器发布WebService,也可以在嵌入式代码中通过jetty发布WebService。
下面的测试类包含了发布服务和客户端调用的代码:
<
dependency
>
<
groupId
>
junit
</
groupId
>
<
artifactId
>
junit
</
artifactId
>
<
version
>
4.12
</
version
>
<
scope
>
test
</
scope
>
</
dependency
>
package
com.dogiant.demo;
import
javax.xml.ws.Endpoint;
import
org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import
org.junit.Assert;
import
junit.framework.TestCase;
public
class
TestEndpoint
extends
TestCase {
private
static
final
String
ADDRESS
=
"http://localhost:9000/cxfdemo"
;
protected
void
setUp()
throws
Exception {
super
.setUp();
System.
out
.println(
"Starting Server"
);
CXFDemoImpl
demo
=
new
CXFDemoImpl();
Endpoint. publish(
ADDRESS
,
demo
);
System.
out
.println(
"Start success"
);
}
public
void
testSayHello() {
JaxWsProxyFactoryBean
factory
=
new
JaxWsProxyFactoryBean();
factory
.setServiceClass(CXFDemo.
class
);
factory
.setAddress(
ADDRESS
);
CXFDemo
client
= (CXFDemo)
factory
.create();
Assert. assertEquals(
client
.sayHello(
"foo"
),
"hello foo"
);
}
}
信息: Creating Service {http://demo.dogiant.com/}CXFDemoImplService from class com.dogiant.demo.CXFDemo
2016-3-28 10:49:48 org.apache.cxf.endpoint.ServerImpl initDestination
信息: Setting the server's publish address to be http://localhost:9000/cxfdemo
2016-3-28 10:49:48 org.mortbay.log.Slf4jLog info
信息: Logging to org.slf4j.impl.JDK14LoggerAdapter(org.mortbay.log) via org.mortbay.log.Slf4jLog
2016-3-28 10:49:48 org.mortbay.log.Slf4jLog info
信息: jetty-6.1.21
2016-3-28 10:49:48 org.mortbay.log.Slf4jLog info
信息: Started SelectChannelConnector@0.0.0.0:9000
Start success
2016-3-28 10:49:48 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
信息: Creating Service {http://demo.dogiant.com/}CXFDemoService from class com.dogiant.demo.CXFDemo
四、在webapp中发布
web.xml
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
web-app
xmlns
=
"http://java.sun.com/xml/ns/javaee"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd "
version
=
"2.5"
>
<
display-name
>
spring- cxf-demo
</
display-name
>
<
context-param
>
<
param-name
>
contextConfigLocation
</
param-name
>
<
param-value
>
classpath*:spring/spring-config*. xml
</
param-value
>
</
context-param
>
<
listener
>
<
listener-class
>
org.springframework.web.context.ContextLoaderListener
</
listener-class
>
</
listener
>
<
servlet
>
<
servlet-name
>
CXFServlet
</
servlet-name
>
<
servlet-class
>
org.apache.cxf.transport.servlet.CXFServlet
</
servlet-class
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
CXFServlet
</
servlet-name
>
<
url-pattern
>
/services/*
</
url-pattern
>
</
servlet-mapping
>
</
web-app
>
spring-config-cxf.xml
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws
=
"http://cxf.apache.org/jaxws"
xsi:schemaLocation
=
"http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
>
<
import
resource
=
"classpath:META-INF/cxf/cxf.xml"
/>
<
import
resource
=
"classpath:META-INF/cxf/cxf-extension-soap.xml"
/>
<
import
resource
=
"classpath:META-INF/cxf/cxf-servlet.xml"
/>
<
jaxws:endpoint
id
=
"cxfDemo"
implementor
=
"com.dogiant.demo.CXFDemoImpl"
address
=
"/cxfdemo"
/>
</
beans
>
http://localhost:8080/services/cxfdemo
<
dependency
>
<
groupId
>
javax.servlet
</
groupId
>
<
artifactId
>
servlet-api
</
artifactId
>
<
version
>
2.5
</
version
>
<scope >provided </scope > //此处不注意会报错
</
dependency
>
http://localhost:8080/services/cxfdemo?wsdl
五、客户端
package
com.dogiant.demo;
import
org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public
class
CXFClient {
public
static
void
main(String[]
args
) {
JaxWsProxyFactoryBean
proxy
=
new
JaxWsProxyFactoryBean();
proxy
.setServiceClass(CXFDemo.
class
);
proxy
.setAddress(
"http://localhost:8080/services/cxfdemo"
);
CXFDemo
cxf
= (CXFDemo)
proxy
.create();
System.
out
.println(
cxf
.sayHello(
"haha"
));
}
}
与spring集成
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws
=
"http://cxf.apache.org/jaxws"
xsi:schemaLocation
=
"http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
>
<
bean
id
=
"clientFactory"
class
=
"
or
g.apache.cxf.jaxws.JaxWsProxyFactoryBean"
>
<
property
name
=
"serviceClass"
value
=
"com.dogiant.demo.CXFDemo"
/>
<
property
name
=
"address"
value
=
"http://localhost:8080/services/cxfdemo"
/>
</
bean
>
<
bean
id
=
"client"
class
=
"com.dogiant.demo.CXFDemo"
factory-bean
=
"clientFactory"
factory-method
=
"create"
/>
</
beans
>
测试用例
package
com.dogiant.demo;
import
org.junit.Test;
import
org.junit.runner.RunWith;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.test.context.ContextConfiguration;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith
(SpringJUnit4ClassRunner.
class
)
@ContextConfiguration
(locations = {
"classpath:spring/spring-config-cxf-client.xml"
})
public
class
TestCXFClient {
@Autowired
private
CXFDemo
client
;
@Test
public
void
test() {
System.
out
.println(
client
.sayHello(
"hello"
));
}
}
附:
cxf官网
February 8, 2016 - Apache CXF 3.1.5/3.0.8 released!
cxf-demo例子
https://github.com/dogiant/cxf-demo