使用CXF框架,发布webservice服务,并使用客户端远程访问webservice
1. CXF介绍 :soa的框架
* cxf 是 Celtrix (ESB框架)和 XFire(webserivice) 合并而成,并且捐给了apache
* CxF的核心是org.apache.cxf.Bus(总线),类似于Spring的 ApplicationContext
* CXF默认是依赖于Spring的
* Apache CXF 发行包中的jar,如果全部放到lib中,需要 JDK1.6 及以上,否则会报JAX-WS版本不一致的问题
* CXF 内置了Jetty服务器 ,它是servlet容器,好比tomcat
2.CXF特点
1. 与Spring、Servlet做了无缝对接,cxf框架里面集成了Servlet容器Jetty
2. 支持注解的方式来发布webservice
3. 能够显示一个webservice的服务列表
4. 能够添加拦截器:输入拦截器、输出拦截器 :
输入日志信息拦截器、输出日志拦截器、用户权限认证的拦截器
CXF框架概念介绍
通过cxf框架发布webservice
1. ServerFactoryBean
- 不设置注解也可以发布webservice服务, 不支持注解
- 不支持拦截器的添加
2. JaxWsServerFactoryBean
- 支持注解
- 可以添加拦截器
3. webservice 访问流程:
1. 检测本地代理描述的wsdl是否与服务端的wsdl一致 ,俗称为握手
2. 通过soap协议实现通信 ,采用的是post请求 , 数据封装在满足soap规约的xml中
3. 返回数据 同样采用的是soap通信, 数据封装在满足soap规约的xml中
Apache CXF 是一个开源的 Services 框架,CXF 帮助您来构建和开发 Services 这些 Services 可以支持多种协议,比如:SOAP、POST/HTTP、RESTful HTTP CXF 大大简化了 Service可以天然地和 Spring 进行无缝集成。
0.jar包:
1.ServerFactoryBean来发布web服务
服务类代码如下:(注解无效)
接口:
package cn.it.ws.cxf.a; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; @WebService(serviceName="languageManager") public interface LanguageService { public String getLanguage(int position); }
实现类及发布:
package cn.it.ws.cxf.a; import org.apache.cxf.frontend.ServerFactoryBean; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; /**开发语言排行描述服务 * * */ public class LanguageServiceImpl implements LanguageService { /* (non-Javadoc) * @see cn.it.ws.cxf.a.LanguageService#getLanguage(int) */ @Override public String getLanguage(int position){ String language=null; switch (position) { case 1: language="java"; break; case 2: language="C"; break; case 3: language="Objective-C"; break; case 4: language="C#"; break; default: break; } return language; } /**通过cxf框架发布webservice * 1. ServerFactoryBean * - 不设置注解也可以发布webservice服务, 不支持注解 * - 不支持拦截器的添加 * 2. JaxWsServerFactoryBean * - 支持注解 * - 可以添加拦截器 * 3. webservice 访问流程: * 1. 检测本地代理描述的wsdl是否与服务端的wsdl一致 ,俗称为握手 * 2. 通过soap协议实现通信 ,采用的是post请求 , 数据封装在满足soap规约的xml中 * 3. 返回数据 同样采用的是soap通信, 数据封装在满足soap规约的xml中 * @param args*/ public static void main(String[] args) { LanguageService languageService=new LanguageServiceImpl(); ServerFactoryBean bean=new ServerFactoryBean(); //Endpoint :地址 , 实现对象 bean.setAddress("http://127.0.0.1:9999/ws/cxf/languangeService"); bean.setServiceClass(LanguageService.class);//对外提供webservcie的业务类或者接口 bean.setServiceBean(languageService);//服务的实现bean bean.create();//创建,发布webservice System.out.println("wsdl地址:http://127.0.0.1:9999/ws/cxf/languangeService?WSDL"); } }
测试:
ServerFactoryBean注意事项:
这种方式没有添加webService注解,也就是说没有注解也可以发布webService服务,但是这种方式不是很规范,比如我们不可以通过注解的方式来修改WSDL的标签信息,
2.JaxWsServerFactoryBean来发布web服务
- JaxWsServerFactoryBean是ServerFactoryBean的子类,也是功能扩展类。
- 此类,必须要在被发布为服务的类上添加@WebService注解,如果不加注解,虽然不出错,但也不会对外暴露任何方法。使用此类生成的wsdl文件更加规范
- 更重要的是可以通过添加拦截器拦截请求.
接口:
package cn.it.ws.cxf.a; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; @WebService(serviceName="languageManager") public interface LanguageService { public @WebResult(name="language")String getLanguage(@WebParam(name="position")int position); }
实现类及发布:
package cn.it.ws.cxf.a; import org.apache.cxf.frontend.ServerFactoryBean; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; /**开发语言排行描述服务 * * */ public class LanguageServiceImpl implements LanguageService { /* (non-Javadoc) * @see cn.it.ws.cxf.a.LanguageService#getLanguage(int) */ @Override public String getLanguage(int position){ String language=null; switch (position) { case 1: language="java"; break; case 2: language="C"; break; case 3: language="Objective-C"; break; case 4: language="C#"; break; default: break; } return language; } public static void main(String[] args) { LanguageService languageService=new LanguageServiceImpl(); JaxWsServerFactoryBean bean=new JaxWsServerFactoryBean(); //Endpoint :地址 , 实现对象 bean.setAddress("http://127.0.0.1:9999/ws/cxf/languangeService"); bean.setServiceClass(LanguageService.class);//对外提供webservcie的业务类或者接口 bean.setServiceBean(languageService);//服务的实现bean //添加输入拦截器 :输入显示日志信息的拦截器 bean.getInInterceptors().add(new LoggingInInterceptor()); //添加输出拦截器 :输出显示日志信息的拦截器 bean.getOutInterceptors().add(new LoggingOutInterceptor()); bean.create();//创建,发布webservice System.out.println("wsdl地址:http://127.0.0.1:9999/ws/cxf/languangeService?WSDL"); } }
测试:
3.生成本地代理以及打包测试:
C:\Users\liqiang\Desktop>wsimport http://127.0.0.1:9999/ws/cxf/languangeService? WSDL parsing WSDL... Generating code... Compiling code... C:\Users\liqiang\Desktop>jar -cvf Language.jar ./cn 已添加清单 正在添加: cn/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: cn/it/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: cn/it/ws/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: cn/it/ws/cxf/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: cn/it/ws/cxf/a/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: cn/it/ws/cxf/a/GetLanguage.class(输入 = 617) (输出 = 376)(压缩了 39%) 正在添加: cn/it/ws/cxf/a/GetLanguageResponse.class(输入 = 692) (输出 = 390)(压缩 了 43%) 正在添加: cn/it/ws/cxf/a/LanguageManager.class(输入 = 2325) (输出 = 1044)(压缩了 55%) 正在添加: cn/it/ws/cxf/a/LanguageService.class(输入 = 806) (输出 = 439)(压缩了 4 5%) 正在添加: cn/it/ws/cxf/a/ObjectFactory.class(输入 = 1647) (输出 = 673)(压缩了 59 %) 正在添加: cn/it/ws/cxf/a/package-info.class(输入 = 242) (输出 = 198)(压缩了 18%) C:\Users\liqiang\Desktop>
测试代码:
import cn.it.ws.cxf.a.LanguageManager; import cn.it.ws.cxf.a.LanguageService; public class _Main { public static void main(String[] args) { // TODO Auto-generated method stub LanguageManager lManager = new LanguageManager(); LanguageService languageServicePort = lManager.getLanguageServicePort(); String language = languageServicePort.getLanguage(1); System.out.println(language); } }
客户端console:
java
服务端console:(握手,接收请求,发送数据(soap))
九月 22, 2017 12:25:56 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log 信息: Inbound Message ---------------------------- ID: 4 Address: http://127.0.0.1:9999/ws/cxf/languangeService?WSDL Http-Method: GET Content-Type: Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Type=[null], Host=[127.0.0.1:9999], User-Agent=[Java/1.7.0_80]} -------------------------------------- 九月 22, 2017 12:25:58 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log 信息: Inbound Message ---------------------------- ID: 5 Address: http://127.0.0.1:9999/ws/cxf/languangeService Encoding: UTF-8 Http-Method: POST Content-Type: text/xml; charset=UTF-8 Headers: {Accept=[text/xml, multipart/related], connection=[keep-alive], Content-Length=[208], content-type=[text/xml; charset=UTF-8], Host=[127.0.0.1:9999], SOAPAction=[""], User-Agent=[JAX-WS RI 2.2.4-b01]} Payload: <?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getLanguage xmlns:ns2="http://a.cxf.ws.it.cn/"><position>1</position></ns2:getLanguage></S:Body></S:Envelope> -------------------------------------- 九月 22, 2017 12:25:59 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log 信息: Outbound Message --------------------------- ID: 5 Encoding: UTF-8 Content-Type: text/xml Headers: {} Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getLanguageResponse xmlns:ns2="http://a.cxf.ws.it.cn/"><language>java</language></ns2:getLanguageResponse></soap:Body></soap:Envelope> --------------------------------------