什么是CXF:
Apache CXF = Celtix + Xfire
????????????支持多种协议:
????????????SOAP1.1,1.2
????????????XML/HTTP
????????????CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。????????????????????C,c++,C#)?
????????????并可以与Spring进行快速无缝的整合
????????????灵活的部署:可以运行在Tomcat,Jboss,Jetty(内置),IBMWS,BeaWL上面。
?
安装CXF的其他支持项目:
Ant
Tomcat
并设置以下环境变量:
????????????JAVA_HOME ?
????????????CXF_HOME
????????????ANT_HOME
????????????CATALINA_HOME
????????????Path = %JAVA_HOME%bin;%CXF_HOME%bin;%CATALINA_HOME%bin;%ANT_HOME%bin
????????????CLASSPATH=.;%CXF_HOME%libcxf-manifest.jar;.buildclasses
在Eclipse中开发CXF的JavaSE应用:
导入CXF中的 所有jar文件。可以通过WACH_JARS来观察各jar文件的用途。
建立好之后的项目如图所示:

CXF发布服务的类:
用两个不同的类发布应用:
????????????ServerFactoryBean ? -- FacotryBean
????????????JaxWsServerFactoryBean(建议使用此类)

使用ServerFactoryBean发布服务:
/**
* 使用ServerFactoryBean发布CXF的javase应用
* @author zhaoqx
*
*/
public class HelloService {
public String sayHello(String name){
System.out.println("sayHello called...");
return "hello " + name;
}
static void main(String[] args) {
ServerFactoryBean bean = new ServerFactoryBean();
bean.setAddress("http://192.168.1.24:9999/Hello");
bean.setServiceClass(HelloService.class);
bean.setServiceBean(new HelloService());
bean.create();
System.err.print("启动成功");
}
}
使用ClientProxyFactoryBean客户端调用
使用ServerFactoryBean发布服务以后,在没有接口的情况下,可以使用wsimport生成的客户端代码调用成功。
但如果要使用ClientProxyFactoryBean客户端去调用服务器,则必须要先在服务器端创建一个接口。(一直以来,Spring都要 求面向接口编程,而cxf与Spring能很好的整合,也就在此。),所以,必须要重写服务器端的代码。这将导致刚才使用wsimport生成的调用代码 失效。
同时, ClientProxyFactoryBean由于要用到CXF环境,所以要导入CXF的所有包。
同时,如果是在本项目中调用,则可以直接使用本项目的接口。
如果在其他项目中调用,仍然需wsimport生成的类,但只需要一个接口。

0
使用JaxWsServerFactoryBean发布服务: (建议使用此类)
????JaxWsServerFactoryBean是ServerFactoryBean的子类,也是功能扩展类。但在CXF的API文档中没有提供此类API,请通过查看源代码的方式获取此类的帮助。此类,必须要在被发布为服务的类上添加@WebService注解,如果不加注解,虽然不出错,但也不会对外暴露任何方法。使用此类生成的wsdl文件更加规范。
?
@WebService
//@javax.xml.ws.BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
class HiService {
public String sayHi(String name){
System.out.println("服务调用");
return "Hi"+name;
}
void main(String[] args) {
JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean();
bean.setAddress("http://localhost:9999/two");
bean.setServiceClass(HiService.new HiService());
bean.create();
System.err.print("服务启动成功");
}
}
使用JaxWsProxyFactoryBean客户端调用:
此调用过程与ClientProxyFactoryBean的要求一样,也必须要拥有一个接口。
此时,仍然可以使用wsimport生成接口,在其他项目的调用。
规范的做法应该是先书写一个接口,如下:
@WebService
interface IHelloService {
public String sayHello(String name);
}
class IHelloServiceImpl implements IHelloService {
public String sayHello(String name) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date())+"=== hello=====" + name;
}
new JaxWsServerFactoryBean();
bean.setAddress("http://192.168.1.24:8888/sayHi");
bean.setServiceClass(IHelloService.new IHelloServiceImpl());
加入请求消息拦截器
bean.getInInterceptors().add(new LoggingInInterceptor());
加入响应消息拦截器
bean.getOutInterceptors().add(new LoggingOutInterceptor());
bean.create();
System.err.print("服务启动成功");
}
}
wsdl2java生成客户代码:
在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。
先让我们了解一下cxf的wsdl2java工具,可以生成一堆客户端调用的代码。
此工具位于cxf_home/bin目录下。参数与wsimport有所不同。
它包含以下参数:
-d参数,指定代码生成的目录。
-p参数,指定生成的新的包结构。
需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。
在命令行执行:
wsdl2java –d . http://127.0.0.1:6666/helloworld?wsdl
?调用端代码:?

使用JavaScript也可以访问WebServie:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>使用jquery的ajax调用Web服务 </title>
<script type="text/javascript" src="js/jquery-1.6.2.js"></script>
<script type="text/javascript">
$(function(){
$("#but1").click(function(){
指定访问服务的地址
var wsUrl = "http://localhost:8090/CXF03/cxf/hi";
构造请求体
var soap = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHi xmlns:ns2="http://kaiyi/"><arg0>abc</arg0></ns2:sayHi></soap:Body></soap:Envelope>';
$.ajax({
url:wsUrl,type:'post',dataType:'xml',contentType:'text/xml;charset=UTF-8',data:soap,success:function(data){
alert('OK!');
var o = $(data);
alert(o.find('return').eq(0).text());
},error:function(){
alert('error!');
}
});
});
});
</script>
</head>
<body>
<input type="button" value="发送jquery的ajax请求" id="but1">
</body>
</html>
以上均是非WEB的开发下面介绍基于web的cxf
由于cxf的web项目已经集成了Spring所以,cxf的服务类都是在spring的配置文件中完成的。以下是步骤:
第一步:建立一个web项目。
第二步:准备所有jar包。将cxf_homelib项目下的所有jar包全部copy到新项目的lib目录下,里面已经包含了spring3.0的jar包。
第三步:在web.xml中配置cxf的核心servlet,CXFServlet。
第四步:创建(最好是Copy)cxf-servlet.xml文件。这是一个spring的配置文件。
cxf-servlet.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"
xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http:www.springframework.org/schema/beans/spring-beans.xsd
http:cxf.apache.org/bindings/soap
http:cxf.apache.org/schemas/configuration/soap.xsd
http:cxf.apache.org/jaxws
http:cxf.apache.org/schemas/jaxws.xsd
http:cxf.apache.org/jaxrs
http:cxf.apache.org/schemas/jaxrs.xsd
">
<!-- 引入CXF Bean定义如下,早期的版本中使用 -->
<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" />
<!-- 通过spring配置文件发布CXF的服务 -->
<!-- 第一种发布方式:没有接口的发布(简单发布) -->
<!--
id:唯一标识
address:访问url
implementor:提供服务的类型
-->
<jaxws:endpoint id="helloService" address="/hello"
implementor="kaiyi.HelloService">
<!-- 加入消息拦截器 -->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:endpoint>
<!-- 第二种发布方式:带有接口的发布 -->
<jaxws:server id="hiService" address="/hi" serviceClass="kaiyi.IHiService">
<jaxws:serviceBean>
<!-- 提供服务的实现类 -->
<bean class="kaiyi.IHiServiceImpl"></bean>
</jaxws:serviceBean>
<!-- 加入消息拦截器 -->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:server>
<!-- 配置restful方式的web服务 -->
<bean id="ps" class="restful.PersonServiceImpl"></bean>
<jaxrs:server id="personService" address="/p">
<jaxrs:serviceBeans>
<ref bean="ps"/>
</jaxrs:serviceBeans>
<jaxrs:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxrs:inInterceptors>
<jaxrs:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxrs:outInterceptors>
</jaxrs:server>
</beans>
web.xml
<?
xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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">
<!-- 通过上下文参数指定spring配置文件的位置 -->
context-param>
param-name>contextConfigLocation
</param-value>classpath:cxf-servlet.xml
>
listenerlistener-class>org.springframework.web.context.ContextLoaderListener
配置CXF框架的核心Servlet servletservlet-name>cxf
servlet-class>org.apache.cxf.transport.servlet.CXFServlet
通过初始化参数指定配置文件的位置 -->
<init-param>
<param-name>config-location</param-name>
<param-value>classpath:cxf-servlet.xml</param-value>
</init-param>-->
>
servlet-mappingurl-pattern>/cxf/*
>
welcome-file-listwelcome-file>index.jsp
>
>
web-app>
这是我的包结构

*/
@WebService
return "hello " +
name;
}
}
package
kaiyi;
import javax.jws.WebService;
@WebService
interface IHiService {
public String sayHi(String name);
}
class IHiServiceImpl
implements IHiService{
public String sayHi(String name) {
System.out.println("sayHi...."
);
return "hi " +
name;
}
}
在地址栏访问:
Java项目代码调用服务:
使用纯Java项目调用
1、根据客户端生成的代码来调用。(优选这种方式)请先生成然后在任意的Java项目中调用 。
2、客户端只拥有一个接口,使用JaxWsProxyFactoryBean来调用。
因为以下使用了JaxWsProxyFactoryBean,所以,仍然需要CXF的环境,而使用此环境就会造成Jar文件的大量冗余,所以大家要谨慎选择(一下的地址是随便贴的)。
在Spring项目中,通过配置文件调用:
以下是使用Spring的配置文件调用:
新建立一个Java项目,并加载cxf的所有包。
只需要生成的接口文件.
在classpath下新建立一个ClientBeans.xml文件.
优点与缺点:
????????此种情况,适合于一个Javaweb项目已经集成了Spring。并希望通过CXF配置的方式调用Web服务。
????????此种情况,仍然需要导入CXF的大量jar包。
????????这种情况也存在一定优点,如可以将外部的Web服务通过配置文件注入(DI)到Action类中。

ClientBeans.xml文件的内容:
beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd" 配置客户端bean
id:唯一标识
address:请求的服务地址
serviceClass:客户端接口
jaxws:client id="hiService" address="http://localhost:8090/CXF03/cxf/hi" serviceClass="kaiyi.IHiService"></jaxws:client>
beans 以下是调用代码:
package
test;
import kaiyi.IHiService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
class test {
void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("ClientBeans.xml"
);
IHiService ihi = (IHiService) ctx.getBean("hiService"
);
ihi.sayHi("abc"
);
System.out.println(ihi.getClass().getName());
}
}
通过JS来调用WebService:
POJO类:
package
pojo;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "person"
)
class Person
implements Serializable{
*
*/
private final long serialVersionUID = 1L
;
private String id;
private String name;
private String desc;
@XmlElement(name = "id"
)
public String getId() {
return id;
}
void setId(String id) {
this.id =
id;
}
@XmlElement(name = "name"
)
public String getName() {
return name;
}
void setName(String name) {
this.name =
name;
}
@XmlElement(name = "desc"
)
public String getDesc() {
return desc;
}
void setDesc(String desc) {
this.desc =
desc;
}
@Override
public String toString() {
return "Person [desc=" + desc + ",id=" + id + ",name=" + name + "]"
;
}
}
现在一般来说用URL的方式调用restful服务比较流行:
它与WSDL方式完全不同,采用的是一种新型的方式,企业开发使用较为常见:
Available RESTful services:
Endpoint address: http://localhost:8090/CXF03/cxf/p WADL : http://localhost:8090/CXF03/cxf/p?_wadl&type=xml |
访问后返回的是json或者XML数据
此种方式只需要在cxf-servlet.xml配置一下即可:
配置restful方式的web服务
bean ="ps" class="restful.PersonServiceImpl"beanjaxrs:server ="personService"="/p"jaxrs:serviceBeans>
ref ="ps"/>
jaxrs:inInterceptorsclass="org.apache.cxf.interceptor.LoggingInInterceptor"jaxrs:outInterceptors="org.apache.cxf.interceptor.LoggingOutInterceptor"jaxrs:server 以下是访问方式:
import
java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.junit.Test;
import pojo.Person;
使用URL的方式调用restful服务
class UrlConnectionTest {
@Test
void test1()
throws Exception {
String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons/id0"
;
URL url =
new URL(wsUrl);
URLConnection conn =
url.openConnection();
HttpURLConnection con =
(HttpURLConnection)conn;
con.setRequestMethod("GET"
);
int code =
con.getResponseCode();
if(code == 200
){
InputStream in =
con.getInputStream();
byte[] b =
new byte[1024
];
int len = 0
;
StringBuffer sb =
new StringBuffer();
while((len=in.read(b))!=-1
){
String s =
new String(b,len,"UTF-8"
);
sb.append(s);
}
String json =
sb.toString();
JSONObject o =
JSONObject.fromObject(json);
json = o.getString("person"
).toString();
将String转换为Person对象
Person person = (Person) JSONObject.toBean(JSONObject.fromObject(json),Person.
class);
System.out.println("----"+
person);
}
con.disconnect();
}
@Test
void test2()
throws Exception {
String wsUrl = "http://localhost:8090/CXF03/cxf/p/persons"
;
URL url =
);
sb.append(s);
}
String json =
sb.toString();
JSONObject o =
JSONObject.fromObject(json);
Object obj = o.get("person"
);
json =
obj.toString();
List<Person> list = (List<Person>)JSONArray.toCollection(JSONArray.fromObject(json),255); font-size:12px!important; line-height:1.5!important">class
);
for(Person p:list){
System.out.println(p);
}
}
con.disconnect();
}
}
我们可以根据被调用服务的接口上的注解来决定返回值的数据格式
//@Produces( { MediaType.APPLICATION_XML })
@Produces( { MediaType.APPLICATION_JSON })
public interface IPersonService extends Serializable?
以下是服务代码:
package
restful;
import java.io.Serializable;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Produces( { MediaType.APPLICATION_XML })
@Produces( { MediaType.APPLICATION_JSON })
interface IPersonService
extends Serializable {
@GET
@Path(value="/persons/{id}"
)
public Person findPersonById(
@PathParam("id"
)
String id);
@GET
@Path(value="/persons"
)
public List<Person>
findAllPerson();
}
package restful;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import pojo.Person;
class PersonServiceImpl
implements IPersonService {
static Map<String,Person> ps =
new HashMap<String,Person>
();
static {
for(
int i=0;i<5;i++
){
Person p =
new Person();
p.setId("id" +
i);
p.setName("person" +
i);
p.setDesc("desc" +
i);
ps.put(p.getId(),p);
}
}
public List<Person>
findAllPerson() {
return new ArrayList<Person>
(ps.values());
}
public Person findPersonById(String id) {
return ps.get(id);
}
}
以下是调用代码:
for
(Person p:list){
System.out.println(p);
}
}
con.disconnect();
}
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!