cxf笔记
一、CXF框架入门
1、概述-功能强大,支持多种协议,嵌入式WebService,可以发布到各种web服务器中
、如何发布一个WebService---Endpoint.publish()---开一个web服务器 jax-ws---Web应用--专业的Web服务器中。---嵌入式WebService
、如何调用别人的WebService---wsimport生成客户端代码/HttpUrlConnection 封装SOAP调用信息
Axis/CXF--xFire
jax-ws==>@WebService
2、示例入门,使用Maven来帮助把示例导入Eclipse
ant
pom.xml===>maven
A、使用Ant来运行示例
在命令行切换到\samples\java_first_pojo目录
执行ant server 运行webservice服务器端,可以改HelloWorldImpl.java
执行ant client 运行客户端代码
直接使用wsimport来生成客户端,用自己的写客户端代码去调用,cxf所发布的WebService。
B、使用mvn来生成各个示例的eclipse项目文件
根据pom.xml来生
(1)、maven的bin目录加到path路径中,在命令行运行mvn可以.
(2)、在document-setting\administarto\.m2文件放repository目录放置各种开源jar包。
(3)、在示例项目目录下,运行mvn eclipse:eclipse来生eclipse项目文件,并把目录导入eclipse中.
(4)、在eclipse环境中配置M2_REPO变量,把他指向.m2/repository目录
3、使用CXF发布WebService
使用cxf框架的最小依赖包:
/gzitcast1008-cxf-client/WebContent/WEB-INF/lib/cxf-2.3.8.jar
/gzitcast1008-cxf-client/WebContent/WEB-INF/lib/wsdl4j-1.6.2.jar
/gzitcast1008-cxf-client/WebContent/WEB-INF/lib/XmlSchema-1.4.7.jar
如果要发布WebService,需要web服务器(默认用的jetty)
/gzitcast1008-cxf-server/WebContent/WEB-INF/lib/jetty-continuation-7.4.5.v20110725.jar
/gzitcast1008-cxf-server/WebContent/WEB-INF/lib/jetty-http-7.4.5.v20110725.jar
/gzitcast1008-cxf-server/WebContent/WEB-INF/lib/jetty-io-7.4.5.v20110725.jar
/gzitcast1008-cxf-server/WebContent/WEB-INF/lib/jetty-security-7.4.5.v20110725.jar
/gzitcast1008-cxf-server/WebContent/WEB-INF/lib/jetty-server-7.4.5.v20110725.jar
/gzitcast1008-cxf-server/WebContent/WEB-INF/lib/jetty-util-7.4.5.v20110725.jar
A、发布POJO,普通JavaBean---使用ServerFactoryBean
public interface IHello {
String sayHello(String name);
}
public class HelloImpl implements IHello {
@Override
public String sayHello(String name) {
System.out.println("hello:"+name);
return name+"---"+new Date();
}
}
public static void main(String[] args) {
//使用CXF框架把一个PoJO发布成WebService
ServerFactoryBean factory=new ServerFactoryBean();
//指定业务接口
factory.setServiceClass(IHello.class);
//指定把webservice绑定哪一个URI
factory.setAddress("http://localhost:9001/hello");
//指定ServiceBean的名称
factory.setServiceBean(new HelloImpl());
//创建服务,发布
factory.create();
System.out.println("服务已经启动....");
}
B、使用CxF发布基于Jax-ws协议的JavaBean==>生成wsdl更加规范。使用JaxWsServerFactoryBean
@WebService(targetNamespace="http://cxf2.test.sanfy.cn")
public interface IHello {
String sayHello(String name);
}
public class HelloImpl implements IHello {
@Override
public String sayHello(String name) {
System.out.println("hello:"+name);
return name+"---"+new Date();
}
}
public static void main(String[] args) {
//使用CXF框架把一个PoJO发布成WebService
//JaxWsServerFactoryBean-->更加规范,必须要求ServiceClass必须使用jax-ws的提供注解来标注
JaxWsServerFactoryBean factory=new JaxWsServerFactoryBean();
//指定业务接口
factory.setServiceClass(IHello.class);
//指定把webservice绑定哪一个URI
factory.setAddress("http://localhost:9002/hello");
//指定ServiceBean的名称
factory.setServiceBean(new HelloImpl());
//创建服务,发布
factory.create();
System.out.println("服务已经启动....");
}
4、如何使用CXF帮助调用WebService
A、使用cxf框架提供的工具来帮助生成客户端的代码
wsdl2java -d . http://localhost:9002/hello?wsdl
根据wsdl文件来生成客户端调用WebService的代码。
B、直接调用CXF所发布的WebService--使用ClientProxyFactoryBean
接口文件:
public interface IHello {
public String sayHello(String name);
}
调用代码:
//创建一个cxf的客户端代理Bean工厂
ClientProxyFactoryBean factory=new ClientProxyFactoryBean();
//通过address属性指定webserive的url
factory.setAddress("http://localhost:9001/hello");
//调用create方法来创建本地接口的代理
IHello hello= factory.create(IHello.class);
System.out.println(hello.getClass());
System.out.println(hello.sayHello("gzitcast"));
C、调用CXF所发布基于jax-ws的webservice---JaxWsProxyFactoryBean
接口文件:http://cxf2.test.sanfy.cn
@WebService(targetNamespace = "http://cxf2.test.sanfy.cn", name = "IHello")
public interface IHello {
@WebResult(name = "return", targetNamespace = "")
@RequestWrapper(localName = "sayHello", targetNamespace = "http://cxf2.test.sanfy.cn", className = "cn.sanfy.test.cxf2.SayHello")
@WebMethod
@ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://cxf2.test.sanfy.cn", className = "cn.sanfy.test.cxf2.SayHelloResponse")
public java.lang.String sayHello(
@WebParam(name = "arg0", targetNamespace = "")
java.lang.String arg0
);
}
调用代码
//创建一个cxf的客户端代理Bean工厂
JaxWsProxyFactoryBean factory=new JaxWsProxyFactoryBean();
//通过address属性指定webserive的url
factory.setAddress("http://localhost:9002/hello");
//调用create方法来创建本地接口的代理
IHello hello= factory.create(IHello.class);
System.out.println(hello.getClass());
System.out.println(hello.sayHello("gzitcast"));
二、使用CXF实现基于RESTful的WebService
1、发布基于RESTFul的WebService
A、概述
HTPP协议
描述一个资源:
http://localhost:9002/person
http://localhost:9002/person/5
表示对资源的操作(CRUD)
使用针对Http调用的方法(Http头)。method值,来判断用户对某一个资源进行什么样的操作。
就是普通的web应用,
http://localhost:9002/hello
RESTful
B、CXF框架发布RESTful Web Services
获得调用说明,在服务后面根?_wadl&_type=xml的请求参数
http://localhost:9004/person?_wadl&_type=xml
C、服务器端的代码:
@Path表示资源的映射路径
@Produces可以输出什么的样的结果---WebService会根据客户端的请求的accept头来返回不同的结果。
@PathParam用来指定个参数,注意参数是在地址栏中进行传递的
http:URL url=new URL("http://localhost:9004/person/java/6");
服务
@Path("/person")
@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
public class PersonService {
//返回的类型,必须使用@XmlRootElement来标识,jaxb
@GET
public User get(){
System.out.println("执行数据的查询....");
User u=new User();
return u;
}
@PUT
@Path("/{name}/{age}/")
@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
public String save(@PathParam("name") String name,@PathParam("age") Integer age){
System.out.println("执行数据的添加...."+name+":"+age);
return "添加已经成功"+new Date();
}
@POST
public void update(){
System.out.println("执行数据的修改...");
}
@DELETE
public void delete(){
System.out.println("执行数据的删除...");
}
}
发布基于RESTFul的服务
public static void main(String[] args) {
JAXRSServerFactoryBean factory=new JAXRSServerFactoryBean();
factory.setServiceBean(new PersonService());
factory.setServiceClass(PersonService.class);
//地址里面不要包含路径信息,路径信息是由服务类中的Path标签指定
factory.setAddress("http://localhost:9004");
factory.create();
}
2、使用客户端调用
@Test
public void doGet() throws Exception{
URL url=new URL("http://localhost/person");
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
//通过设置请求头,让客户端发送特定结果,比如下面的请求,要求服务器发送json的结果
conn.setRequestProperty("Accept", "application/json");
//设置请求头,实现不同的操作
conn.setRequestMethod("GET");
System.out.println("调用WebService....");
//发起请求,并读取返回的结果
InputStream in= conn.getInputStream();
printResult(in);
}
private void printResult(InputStream in) throws IOException {
ByteOutputStream out=new ByteOutputStream();
byte[] buffer=new byte[1024];
int len=-1;
while(((len=in.read(buffer))>0)){
out.write(buffer,0,len);
}
in.close();
out.close();
System.out.println(out.toString());
}
@Test
public void doPost() throws Exception{
URL url=new URL("http://localhost:9004/person");
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
//设置请求头,实现不同的操作
conn.setRequestMethod("POST");
System.out.println("调用WebService....");
//发起请求,并读取返回的结果
InputStream in= conn.getInputStream();
printResult(in);
}
@Test
public void doPut() throws Exception{
URL url=new URL("http://localhost:9004/person/java/6");
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
//设置请求头,实现不同的操作
conn.setRequestMethod("PUT");
System.out.println("调用WebService....");
//发起请求,并读取返回的结果
InputStream in= conn.getInputStream();
printResult(in);
}
@Test
public void doDelete() throws Exception{
URL url=new URL("http://localhost:9004/person/3");
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
//设置请求头,实现不同的操作
conn.setRequestMethod("DELETE");
System.out.println("调用WebService....");
//发起请求,并读取返回的结果
InputStream in= conn.getInputStream();
printResult(in);
}
三、CXF与Spring及Struts2的集成应用
1、使用Spring_CXF来发布WebService
A、拷cxf及spring的jar包
B、配置web.xml,配置CXF的主控Servlet,让/ws/*的由CXF这个框架处理
<!-- 配置CXF的Servlet -->
<servlet>
<servlet-name>cxfservlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<!-- 配置加载的文件信息 -->
<init-param>
<param-name>config-location</param-name>
<param-value>/WEB-INF/cxf-servlet.xml</param-value>
</init-param>
<!-- web应用起动时,初始化cxfservlet -->
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxfservlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
C、编写cxf-servlet.xml文件,这是一个Spring的配置文件
导入cxf相关的schema
可以使用http://localhost:8080/test/ws,得到没有WebService的提示。
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
</beans>
D、在配置文件中配置发布一个webservice
接口
@WebService
public interface HelloService {
String sayHello(String name);
}
实现类
@WebService
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
//CXFServlet
System.out.println("调用sayHello方法...");
return name+"---"+new Date();
}
}
配置方式1;
<!-- 方法一,直接指定类来发布WebService -->
<!-- 直接发布一个webservice address:指定webService的标识路径,不用包含主机及应用信息 implementor:指定WebService的实现类
implementorClass:指定WebService的实现接口 -->
<jaxws:endpoint address="/hello"
implementor="cn.sanfy.test.service.HelloServiceImpl" implementorClass="cn.sanfy.test.service.HelloService">
</jaxws:endpoint>
配置方式2:
<!-- 方法二,把一个Spring的Bean发布成WebService -->
<bean id="helloService" class="cn.sanfy.test.service.HelloServiceImpl">
<property name="welcome" value="欢迎到传智播客...."></property>
</bean>
<!-- 把一个Spring管理Bean发布成WebService -->
<jaxws:server address="/hello2" serviceClass="cn.sanfy.test.service.HelloService">
<!-- 用serviceBean来包含一个Spring管理的Bean -->
<jaxws:serviceBean>
<!-- 使用ref标签引用另外一个Bean -->
<ref bean="helloService" />
</jaxws:serviceBean>
</jaxws:server>
2、CXF框架中的拦截器应用
JaxWsServerFactoryBean factory=new JaxWsServerFactoryBean();
//添加拦截器
//输入拦截器--接收到客户端请求时,写日志
factory.getInInterceptors().add(new LoggingInInterceptor());
//输出拦截器--往客户端发结果时,写日志
factory.getOutInterceptors().add(new LoggingInInterceptor());
//指定业务接口
factory.setServiceClass(IHello.class);
//指定把webservice绑定哪一个URI
factory.setAddress("http://localhost:9002/hello");
//指定ServiceBean的名称
factory.setServiceBean(new HelloImpl());
//创建服务,发布
factory.create();
3、在Spring配置文件中给WebService配置拦截器
<!-- 把一个Spring管理Bean发布成WebService -->
<jaxws:server address="/hello2" serviceClass="cn.sanfy.test.service.HelloService">
<!-- 用serviceBean来包含一个Spring管理的Bean -->
<jaxws:serviceBean>
<!-- 使用ref标签引用另外一个Bean -->
<ref bean="helloService" />
</jaxws:serviceBean>
<!-- 配置WebService的拦截器 -->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:server>
4、在Spring中使用cxf客户端
A、客户端代码
WebService接口
@WebService(name = "HelloService", targetNamespace = "http://service.test.sanfy.cn/")
public interface HelloService {
/**
*
* @param arg0
* @return
* returns java.lang.String
*/
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "sayHello", targetNamespace = "http://service.test.sanfy.cn/", className = "cn.itcast.gz.service.SayHello")
@ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://service.test.sanfy.cn/", className = "cn.sanfy.test.service.SayHelloResponse")
public String sayHello(
@WebParam(name = "arg0", targetNamespace = "")
String arg0);
}
测试Bean,依赖于一个WebService组件
public class TestBean {
private HelloService helloService;
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
public void test() {
String ret = helloService.sayHello("this is testBean");
System.out.println(ret);
}
}
B、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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 配置了HelloService的Bean,他是一个WebService的引用
address:指定WebService的全路径http://www.baiudi.com/person/
serviceClass:是一个本地接口,可以根据wsdl文件来生成
-->
<jaxws:client id="helloService1"
address="http://localhost:8080/test/ws/hello2"
serviceClass="cn.sanfy.test.service.HelloService"></jaxws:client>
<!-- 配置一个Spring的普通Bean,他依赖于前面配置WebService实现 -->
<bean id="testBean" class="cn.sanfy.test.service.TestBean">
<property name="helloService" ref="helloService1"></property>
</bean>
</beans>
C、客户端测试代码
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("/beans.xml");
TestBean bean=(TestBean) context.getBean("testBean");
bean.test();
}
5、在web项目中引入struts2
A、让CXF框不要起动spring容器。也就不要让配置文件名字叫WEB-INF/cxf-servlet.xml
B、使用Spring提供监听器来启动容器,必须在Spring配置文件中加入下面的配置。导入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"/>
6、在Ajax中访问基于SOAP协议的WebService,使用jQuery的ajax方法
$(function() {
var s='<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:sayHello xmlns:ns1="http://service.gz.itcast.cn/"><arg0>this is testBean</arg0></ns1:sayHello></soap:Body></soap:Envelope>';
$("#test").click(function() {
$.ajax({
url:"http://localhost:8080/test/ws/hello2",
type:"POST",
contentType:"text/xml; charset=UTF-8",
data:s,
success:function(ret){
//alert(ret);
//返回的ret对象是一个xml文档,变成 一个XMLDocument对象
var doc=ret;
//查询return节点
var r=doc.getElementsByTagName("return")[0];
alert(r.textContent);
}
});
})
});
注意:第2种方法服务端的接口要加注解@webService,否则就不会调用接口中的方法