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_home\lib项目下的所有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", targetNamespace = "http://cxf.itcast.cn/", 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, HttpServletResponse response) throws ServletException, 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请求。