1??????WebService-CXF-Spring 基于web的cxf
1.1????开发cxf的web项目:--源码eclipse无法访问请使用myeclipse
l? 由于cxf的web项目已经集成了Spring所以,cxf的服务类都是在spring的配置文件中完成的。以下是步骤:
1.1.1?第一步:建立一个web项目。
1.1.2?????????第二步:准备所有jar包。
l? 将cxf_homelib项目下的所有jar包全部copy到新项目的lib目录下,里面已经包含了spring3.0的jar包。
1.1.3?第三步:在web.xml中配置cxf的核心servlet,CXFServlet。
可以将头描叙文件替换为:
?
?
?
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> ??? ??? <!-- 通过上下文参数指定spring配置文件的位置 --> ??? <context-param> ??????? <param-name>contextConfigLocation</param-name> ??????? <param-value>classpath:cxf-servlet.xml</param-value> ??? </context-param> ??? <listener> ??????? <listener-class> ??????????? org.springframework.web.context.ContextLoaderListener ??????? </listener-class> ??? </listener> ??? ??? <!-- 配置CXF的核心Servlet --> ??? <servlet> ??????? <servlet-name>cxf</servlet-name> ??? <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> ??????? <!-- 通过初始化参数指定cxf配置文件的位置 --> ??????? <!-- ??????? <init-param> ??????????? <param-name>config-location</param-name> ??????????? <param-value>classpath:cxf-servlet.xml</param-value> ??????? </init-param> ??????? ?--> ??? </servlet> ??? <servlet-mapping> ??????? <servlet-name>cxf</servlet-name> ??????? <url-pattern>/cxf/*</url-pattern> ??? </servlet-mapping> ? <welcome-file-list> ??? <welcome-file>index.jsp</welcome-file> ? </welcome-file-list> </web-app> ? |
1.1.4?第四步:创建(最好是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: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-3.0.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"> ??? <!-- 引入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" /> ??? ??? <!-- 第一种发布方式:简单发布(没有接口的发布) --> ??? <!-- id:唯一标示? implementor:提供服务的类 address:服务的请求url--> ??? <jaxws:endpoint id="helloService" implementor="cn.itcast.cxf.HelloService" address="/hello"> ??????? <!-- 加入请求的消息拦截器 --> ??????? <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> ??? ??? <!-- 第二种发布方式:带有接口的发布 --> ??? <!-- id:唯一标示 serviceClass:接口类型 address:服务的请求url--> ??? <jaxws:server id="hiService" serviceClass="cn.itcast.cxf.IHiService" address="/hi"> ??????? <jaxws:serviceBean> ??????????? <!-- 服务的实现类 --> ??????????? <bean class="cn.itcast.cxf.HiServiceImpl"></bean> ??????? </jaxws:serviceBean> ??????? <!-- 加入请求的消息拦截器 --> ??????? <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:server> ??? ??? <jaxws:server id="personService" serviceClass="cn.itcast.cxf.service.IPersonService" address="/person"> ??????? <jaxws:serviceBean> ??????????? <!-- 服务的实现类 --> ??????????? <bean class="cn.itcast.cxf.service.PersonServiceImpl"></bean> ??????? </jaxws:serviceBean> ??????? <!-- 加入请求的消息拦截器 --> ??????? <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:server> </beans> ? ? |
?
cxf-servlet.xml文件说明:
l? Cxf-servlet.xml文件,就是一个spring的配置文件。一个空的配置文件如下。
?
<?xmlversion="1.0"encoding="UTF-8"?> <beansxmlns="http://www.springframework.org/schema/beans" ?? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"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.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"> ?? <!-- 引入CXF Bean定义如下,早期的版本中使用 --> ?? <importresource="classpath:META-INF/cxf/cxf.xml"/> ?? <importresource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> ?? <importresource="classpath:META-INF/cxf/cxf-servlet.xml"/> ? ?? <!-- 直接发布一个类,无接口 --> ?? <jaxws:endpointid="one"implementor="cn.itcast.ws1.OneService" ????? address="/one"> ?? </jaxws:endpoint> ?? <!-- 发布一个服务,没有指定接口 --> ?? <jaxws:serverid="two"address="/two"serviceClass="cn.itcast.ws2.ITwoService"> ????? <jaxws:serviceBean> ???????? <!-- 指定发布类,下面类必须添加@WebService注解 --> ???????? <beanclass="cn.itcast.ws2.TwoServiceImpl"></bean> ????? </jaxws:serviceBean> ?? </jaxws:server> </beans> ? ? |
1.1.5?第五步访问:
输入:http://localhost:8080/CXF_3/cxf
?
?
?
?
?
1、通过MyEclipse发布我们的项目。并在地址栏访问http://localhost:9999/cxf2.4_spring_web/ws.应该出现以上的界面。
2、上面的程序是说,没有发现任何已经发布的WebService,确实如此。请同学们重复上面的过程,看能否搭建一个cxf+spring环境出来。
3、接下来,我们将开始在此环境下,发布我们的WebService.
?
配置说明:
l? CXFServlet类,通过读取config-location的配置项读取cxf-servlet.xml配置文件。并在内部读取自己的配置文件cxf.xml文件。
l? 在CXFServlet读取配置文件后,将文件信息全部读取到ApplicationContext的Spring类中。
l? 以下是它的源代码:
通过配置给服务添加消息拦截器:
l? LoggingInInterceptor
l? LogginOutInterceptor
<jaxws:inInterceptors>
<beanclass="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<beanclass="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
</jaxws:outInterceptors>
?
在地址栏访问
?
?
1.2???? Java项目代码调用服务:
l? 使用纯Java项目调用
1.2.1? 1、根据客户端生成的代码来调用。(优选这种方式)
请先生成然后在任意的Java项目中调用 。
?
1.2.1.1 ?保证服务发布成功:
?
1.2.1.2 ?使用:wsdl2java生产客户端代码??-位于cxf框架中
?
注意:1:如果出现 wsdl2java不是内部或外部命令进行如下操作
????? 新建:CXF_HOME: ? ??CXF解压更目录;
???????????PATH中添加?:???????%CSF_HOME%bin
????? 2:如果使用的是JDK1.6 需要将”super(WSDL_LOCATION,SERVICE,features)“;
??????????? 改为:
?? ???????????? super(WSDL_LOCATION,SERVICE);
?
?
客服端代码:
?
App.java
package com.test.cxf.client; ? public class App { ? ??? public static void main(String[] args) { ??????? IHiServiceService hss = new IHiServiceService(); ??????? IHiService hs = hss.getIHiServicePort(); ??????? String ret = hs.sayHi("aaa"); ??????? System.out.println(ret); ??? } } ? |
?
?
?
结果如下图:
?
?
1.2.2? 2、客户端只拥有一个接口,使用JaxWsProxyFactoryBean来调用。
因为以下使用了JaxWsProxyFactoryBean,所以,仍然需要CXF的环境,而使用此环境就会造成Jar文件的大量冗余,所以大家要谨慎选择。
?
1、注意,此处所说的是在Java项目中调用Spring的服务,
并不是在JavaEE项目中调用。后期将会讲到如何在JavaEE项目中调用。
?
2、建议从wsdl地址获取接口文件,也仅需要接口文件。
??JaxWsProxyFactoryBean client =
new JaxWsProxyFactoryBean();
client.setAddress("http://localhost:7777/xcxf2_web/ws/one");
client.setServiceClass(IOneService.class);
IOneService one =client.create(IOneService.class);
String ss = one.sayHi("OK你好");
System.err.println(ss);
?
?
1.2.3??在Spring项目中,通过配置文件调用:
l? 以下是使用Spring的配置文件调用:
新建立一个Java项目,并加载cxf的所有包。只需要生成的接口文件。
在classpath下新建立一个ClientBeans.xml文件.
优点与缺点:
此种情况,适合于一个Javaweb项目已经集成了Spring。并希望通过CXF配置的方式调用Web服务。此种情况,仍然需要导入CXF的大量jar包。
这种情况也存在一定人优点,如可以将外部的Web服务通过配置文件注入(DI)到Action类中。
?
建立好以后Java项目如下图
?
1.2.3.1 1、说明:IHiService.java是通过wsimport生成的接口,我们只需要这个接口。
?
package cn.itcast.cxf; ? import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.ws.RequestWrapper; import javax.xml.ws.ResponseWrapper; ? /** ?* This class was generated by Apache CXF 2.4.2 ?* 2013-01-08T15:41:01.883+08:00 ?* Generated source version: 2.4.2 ?* ?*/ @WebService(targetNamespace = "http://cxf.itcast.cn/",name = "IHiService") @XmlSeeAlso({}) public interface IHiService { ? ??? @WebResult(name = "return",targetNamespace = "") ??? @RequestWrapper(localName = "sayHi",targetNamespace = "http://cxf.itcast.cn/",className = "cn.itcast.cxf.SayHi") ??? @WebMethod ??? @ResponseWrapper(localName = "sayHiResponse",className = "cn.itcast.cxf.SayHiResponse") ??? public java.lang.String sayHi( ??????? @WebParam(name = "arg0",targetNamespace = "") ??????? java.lang.String arg0 ??? ); } |
?
1.2.3.2 2、通过ClientBeans.xml文件,调用WebService。
?1: http://localhost:8080/CXF_3/cxf/hi:服务发布地址
? 2:serviceClass="cn.itcast.cxf.IHiService" :服务接口类
?
<?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: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-3.0.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"> ??? ??? <jaxws:client id="hiService" address="http://localhost:8080/CXF_3/cxf/hi" serviceClass="cn.itcast.cxf.IHiService"> ??? </jaxws:client> </beans> ? ? |
?
1.2.3.3 3、调用源代码:
?
package cn.itcast.cxf; ? import javax.jws.WebService; ? import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; ? /** ?* ?spring调用web service服务 ?* ?*/ @WebService public class App { ??? public static void main(String[] args) { ??????? ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/itcast/cxf/ClientBeans.xml"); ??????? IHiService s = (IHiService) ctx.getBean("hiService"); ??????? System.out.println(s); ??????? String ret = s.sayHi("123"); ??????? System.out.println(ret); ??????? System.out.println(s.getClass().getName()); ??? } ? } |
?
?
1.3????关于web项目配置的说明1:
<servlet>
<!-- 配置cxf -->
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<!-- 配置Spring的配置文件 -->
<param-name>config-location</param-name>
<param-value>/WEB-INF/cxf-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
?
?
关于web项目配置的说明2:
<?xmlversion="1.0"encoding="UTF-8"?> <web-appversion="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"> <context-param> ?? <param-name>contextConfigLocation</param-name> ?? <param-value> ????? /WEB-INF/cxf-itcast.xml ?? </param-value> </context-param> <listener> ?? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> ?? <servlet-name>cxf</servlet-name> ?? <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> ?? <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> ?? <servlet-name>cxf</servlet-name> ?? <url-pattern>/ws/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> ? ? |
?
关于web项目配置的说明3:
l? 在上页中出现的重复引入问题,可以修改cxf-servlet.xml文件。
l? 修改后,CXFServlet类将不能自动加载cxf-servlet.xml文件,此时将导致名为cxf的bean加载不成功。
l? 为解决此问题必须在重新命名的配置文件中加入以下代码,以启动CXF:
即:如果你是用contextConfigLocation加载的配置文件,则必须要加入以下代码。
?
?
<!-- 关于cxf配置的注意事项
?? 如果没有提供给cxf默认的/WEB-INF/cxf-servlet.xml配置文件,则必须要在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"/>
?
?
关于web项目配置的说明4:
l? 在增加了Spring的监听器之后,即可以使用以下代码在Servlet中获取Spring的配置:
?
package cn; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** ?* 获取Spring的配置 ?*/ publicclass TT extends HttpServlet { ?? publicvoid doGet(HttpServletRequest request,HttpServletResponse response) ???????? throws ServletException,IOException { ????? doPost(request,response); ?? } ?? publicvoid doPost(HttpServletRequest request,IOException { ????? ApplicationContext ctx = ????? ?? WebApplicationContextUtils.getWebApplicationContext(getServletContext()); ????? Object o = ctx.getBean("one"); ?? } } ? |
?
?
?
1.4????通过JS(ajax)来调用WebService:
l? 通过jQuery的ajax方法向服务器发送xml数据。
l? 必须要先了解xml的数据格式,通过拦截器获取。
???? 可以从LoggingInInterceptor中获取发出的数据格式。
???? 可以从LoggingOutInterceptor中获取返回的数据。
l? 导入jQuery1.5.js文件,放到js/jquery1.5.js
?
?
?
l? 使用jQuery-本域
l? $.ajax({
???? url:..
???? type:’post’,
???? dataType:’xml’,
???? contentType:’application/soap+xml;charset=“UTF-8”’
???? data:someXml,
???? Success:fun()…
l? })
?
在本域使用jquery访问:? --查询所有用户:
?
?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ? <head> ??? <title>jquery_ws.html</title> ??? <script type="text/javascript" src="js/jquery-1.6.2.js"></script> ??? <script type="text/javascript"> ??????? function sendMsg(){ ??????????? $.ajax({ ??????????????????? url:'http://localhost:8080/CXF_3/cxf/hi?wsdl', ??????????????????? type:'get', ??????????????????? dataType:'xml', ??????????????????? contentType:'text/xml;charset=utf-8', ??????????????????? data:'<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Body><ns2:sayHiResponse xmlns:ns2="http://cxf.itcast.cn/"><return>hi aaa</return></ns2:sayHiResponse></soap:Body></soap:Envelope>', ??????????????????? success:function(data,status,xhr){ ??????????????????????? alert('success!'); ??????????????????????? var v = $(data).find('return').eq(0).text(); ??????????????????????? alert(data); ??????????????????? }, ??????????????????? error:function(){ ??????????????????????? alert('error!'); ??????????????????? } ??????????????????? }); ? ??????? } ??? </script> ? </head> ? <body> ??? <input type="button" value="jquery_Ajax_Use_webservice" onclick="sendMsg();"> ? </body> </html> |
?
?
?
1.5????总结:
l? 什么是WebService?
l? 在Jdk6上使用Endpoint发布WebService。
l? 使用wsimport生成客户端代码。及各种监控工具的使用。
l? CXF的安装。
l? wsdl2java工具的使用。
l? CXF与spring进行整合。*
l? 使用Ajax直接发送SOAP请求。