WebService(2) JAX-WS、CXF、Spring3.0+
来源:互联网 发布:淘宝客服需要什么软件 编辑:程序博客网 时间:2024/05/22 21:36
引自:http://www.cnblogs.com/NF-CHH/archive/2013/02/19/WebService.html?utm_source=tuicool&utm_medium=referral
面对工作的需要,web服务这一块一直都在身边转悠着。既然工作中需要这些,作为程序员就应该去了解和学习。下面主要简述采用CXF+Spring+JAX-WS来发布WebService服务,以及创建客户端调用服务。
准备工作:
1、先了解关于WebService的相关概念以及一些专有名词的解释:
WEBSERVICE
W3C的定义是webservice是一个软件系统,用以支持网络间不同机器的互动操作。
受外部环境和实现技术影响,目前普遍认为webservice的技术核心是
soap,wsdl(一个XML格式文档,用以描述服务端口访问方式和使用协议的细节。通常用来辅助生成服务器和客户端代码及配置信息),uddi(一个用来发布和搜索WEB服务的协议,应用程序可借由 此协议在设计或运行时找到目标WEB服务)
这些标准由这些组织制订:W3C负责XML、SOAP及WSDL;OASIS负责UDDI。
JAX-WS
JAX-WS规范是一组XML web services的JAVA API。JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。
CXF
Apache CXF 是一个开源的 Services 框架,主要是帮助开发者来快速构建web服务。
webservice三种最普遍的实现方式是:
远程过程调用(RPC)
面向服务架构(SOA)
表述性状态转移(REST)
我在这里说的实现方式并不是说 这三种方式是包含于webservice,个人理解它们之间应该是存在交集,即它们是有联系的同时它们也是有不同的,应该不是从属的关系。
2、相关的开发环境与依赖的jar()
A、CXF官方网址:http://cxf.apache.org/
B、Jar包下载地址:http://www.apache.org/dyn/closer.cgi?path=/cxf/2.3.3/apache-cxf-2.3.3.zip
将下来的jar包解压后,目录大概就这样
bin目录提供的是常用的dos控制台命令工具
docs 帮助文档
lib jar包、依赖库
lib-samples 也是jar包,有jetty、httpclients、junit等jar包
modules 打包好的WebService模块
samples示例demo
C、源码下载:http://www.apache.org/dyn/closer.cgi?path=/cxf/2.3.3/apache-cxf-2.3.3-src.zip
有时候你可以看看源码,对你了解和学习CXF WebService都会有作用。
D、CXF的特性
有代码生成工具:Java to WSDL;WSDL to Java;XSD to WSDL;WSDL to XML;WSDL to SOAP;WSDL to Service;
支持 JAX-WS、 JAX-WSA、JSR-181 和 SAAJ;支持 SOAP 1.1、1.2、WS-I BasicProfile、WS-Security、WS-Addressing、WS-RM 和 WS-Policy;支持 WSDL 1.1 、2.0;支持 MTOM;通过 Yoko 支持 CORBA;通过 Tuscany 支持 SCA;通过 ServiceMix 支持 JBI;内置Jetty应用服务器(Jetty服务器也是当今web开发的一款比较好用的服务器);
开发:
开发需要的jar如下:
1、首先创建一个web项目,将得到的包拷贝到lib目录下
既然是想发布自己的服务,首先创建一个接口
1 package com.chh.service; 2 3 import javax.jws.WebParam; 4 import javax.jws.WebService; 5 import javax.jws.soap.SOAPBinding; 6 import javax.jws.soap.SOAPBinding.Style; 7 import com.chh.entity.User; 8 9 /**10 * 定制客户端请求WebService所需要的接口11 * @author chh12 *13 */14 @WebService15 @SOAPBinding(style=Style.RPC)16 public interface IComplexUserService {17 18 public User getUserByName(@WebParam(name = "name") String name);19 20 public void setUser(User user);21 22 }
接口只是用来定义,具体操作要在它下面的实现类中得以体现
1 package com.chh.service; 2 3 import java.util.Date; 4 5 import javax.jws.WebParam; 6 import javax.jws.WebService; 7 import javax.jws.soap.SOAPBinding; 8 import javax.jws.soap.SOAPBinding.Style; 9 10 import com.chh.entity.User;11 /**12 * WebService传递复杂对象,如JavaBean、Array、List、Map等13 * @author chh14 *15 */16 @WebService17 @SOAPBinding(style=Style.RPC)18 @SuppressWarnings("deprecation")19 public class ComplexUserService implements IComplexUserService {20 21 @Override22 public User getUserByName(@WebParam(name = "name") String name) {23 User user = new User();24 25 user.setId(new Date().getSeconds());26 user.setName(name);27 user.setAddress("china");28 user.setEmail(name + "@hoo.com");29 30 return user;31 }32 33 @Override34 public void setUser(User user) {35 System.out.println("############Server setUser###########");36 System.out.println("setUser:" + user);37 }38 39 }
实体
1 package com.chh.entity; 2 3 import java.io.Serializable; 4 /** 5 * 序列化user实体 6 * @author chh 7 * 8 */ 9 public class User implements Serializable {10 11 private static final long serialVersionUID = 677484458789332877L;12 private int id;13 private String name;14 private String email;15 private String address;16 17 public int getId() {18 return id;19 }20 21 public void setId(int id) {22 this.id = id;23 }24 25 public String getName() {26 return name;27 }28 29 public void setName(String name) {30 this.name = name;31 }32 33 public String getEmail() {34 return email;35 }36 37 public void setEmail(String email) {38 this.email = email;39 }40 41 public String getAddress() {42 return address;43 }44 45 public void setAddress(String address) {46 this.address = address;47 }48 49 public static long getSerialversionuid() {50 return serialVersionUID;51 }52 53 @Override54 public String toString() {55 return this.id + "#" + this.name + "#" + this.email + "#" + this.address;56 }57 58 }
1 package com.chh.entity; 2 3 import java.util.HashMap; 4 import java.util.List; 5 6 /** 7 * 8 * @author chh 9 * 10 */11 public class Users {12 private List<User> users;13 private User[] userArr;14 private HashMap<String, User> map;15 16 public List<User> getUsers() {17 return users;18 }19 20 public void setUsers(List<User> users) {21 this.users = users;22 }23 24 public User[] getUserArr() {25 return userArr;26 }27 28 public void setUserArr(User[] userArr) {29 this.userArr = userArr;30 }31 32 public HashMap<String, User> getMap() {33 return map;34 }35 36 public void setMap(HashMap<String, User> map) {37 this.map = map;38 }39 40 }
自定义消息拦截器(如果在你的项目中不需要用到拦截器的时候,可以撤掉不用)
1 package com.chh.interceptor; 2 3 import org.apache.cxf.interceptor.Fault; 4 import org.apache.cxf.message.Message; 5 import org.apache.cxf.phase.AbstractPhaseInterceptor; 6 7 /** 8 * 自定义消息拦截器 9 * @author chh10 *11 */12 public class MessageInterceptor extends AbstractPhaseInterceptor<Message> {13 14 //至少要有一个带参的构造方法15 public MessageInterceptor(String phase) {16 super(phase);17 }18 19 public void handleMessage(Message message) throws Fault {20 System.out.println("############handleMessage##########");21 System.out.println(message);22 23 if(message.getDestination() != null){24 System.out.println(message.getId() + "#" + message.getDestination().getMessageObserver());25 }26 27 if(message.getExchange() != null){28 System.out.println(message.getExchange().getInMessage() + "#" + message.getExchange().getInFaultMessage());29 System.out.println(message.getExchange().getOutMessage() + "#" + message.getExchange().getOutFaultMessage());30 }31 32 }33 34 }
用xml配置服务端(applicationContext-service.xml)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:jaxws="http://cxf.apache.org/jaxws" 5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-3.0.xsd10 http://cxf.apache.org/jaxws 11 http://cxf.apache.org/schemas/jaxws.xsd">12 13 <import resource="classpath:META-INF/cxf/cxf.xml"/>14 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>15 <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>16 17 <bean id="userServiceBean" class="com.chh.service.ComplexUserService"/>18 19 <bean id="inMessageInterceptor" class="com.chh.interceptor.MessageInterceptor">20 <constructor-arg value="receive"/>21 </bean>22 23 <bean id="outLoggingInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>24 25 <!-- 注意下面的address,这里的address的名称就是访问的WebService的name -->26 <jaxws:server id="userService" serviceBean="#userServiceBean" address="/Users">27 <jaxws:inInterceptors>28 <ref bean="inMessageInterceptor"/>29 </jaxws:inInterceptors>30 31 <jaxws:outInterceptors>32 <ref bean="outLoggingInterceptor"/>33 </jaxws:outInterceptors>34 </jaxws:server>35 36 </beans>
注意于此同时web.xml中要加在Spring容器
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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"> 3 <display-name>CXFWebService</display-name> 4 5 <!-- 加载Spring容器配置 --> 6 <listener> 7 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 8 </listener> 9 10 <!-- 设置Spring容器加载配置文件路径 -->11 <context-param>12 <param-name>contextConfigLocation</param-name>13 <param-value>classpath*:applicationContext-server.xml</param-value>14 </context-param>15 16 <listener>17 <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>18 </listener>19 20 <servlet>21 <servlet-name>CXFService</servlet-name>22 <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>23 </servlet>24 25 <servlet-mapping>26 <servlet-name>CXFService</servlet-name>27 <url-pattern>/*</url-pattern>28 </servlet-mapping> 29 </web-app>
到这一步为止,我们web服务端开发完成!可以启动项目测试一下自己的web服务有没有发布成功,其中成功与否第一要看项目启动时是否报错,如果报错看具体报什么错误,是包冲突,还是包的版本太低等。启动项目不报错,那么输入地址查看你的这个web服务的wsdl信息:http://localhost:8080/CXFWebService/Users,如果能够看到看到xml格式的信息,则说明你成功发布了web服务。
有了web服务端,但是如果我在程序中想通过别人提供的web服务地址得到自己想要的数据,这一步又该怎么做呢?下面将继续采用CXF+Spring3.0+ 定制开发web服务客户端。其实到这一步已经很简单了,我们可以通过wsdl中的信息来定制客户端(具体有怎样的规则与细节,可以参看http://blog.csdn.net/qjyong/article/details/2148558 这篇博客下面的几个段落)。
根据服务端定制客户端
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:jaxws="http://cxf.apache.org/jaxws" 6 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 9 http://www.springframework.org/schema/context10 http://www.springframework.org/schema/context/spring-context-3.0.xsd11 http://cxf.apache.org/jaxws 12 http://cxf.apache.org/schemas/jaxws.xsd">13 14 <import resource="classpath:META-INF/cxf/cxf.xml"/>15 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>16 <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>17 18 <!-- serviceClass写定制客户接口的全路径 -->19 <jaxws:client id="userWsClient" serviceClass="com.chh.service.IComplexUserService" 20 address="http://localhost:8080/CXFWebService/Users"/>21 22 </beans>
利用客户端得到服务端的数据。值得说的是,以前发布WebService是用Endpoint的push方法。这里用的是JaxWsServerFactoryBean和客户端调用的代码JaxWsProxyFactoryBean有点不同。
1 package com.chh.client; 2 3 import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.chh.entity.User; 8 import com.chh.service.IComplexUserService; 9 10 /**11 * 请求Spring整合CXF的WebService客户端12 * @author chh13 *14 */15 public class SpringUsersWsClient {16 17 public static void clientFirst(){18 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();19 factory.setServiceClass(IComplexUserService.class);20 factory.setAddress("http://localhost:8080/CXFWebService/Users");21 22 IComplexUserService service = (IComplexUserService) factory.create();23 24 System.out.println("#############Client getUserByName##############");25 User user = service.getUserByName("chh");26 System.out.println(user);27 28 user.setAddress("China-Guangzhou");29 service.setUser(user);30 }31 32 public static void clientToXML(){33 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-client.xml");34 35 IComplexUserService service = ctx.getBean("userWsClient", IComplexUserService.class);36 37 System.out.println("#############Client getUserByName##############");38 User user = service.getUserByName("chh");39 System.out.println(user);40 41 user.setAddress("China-Guangzhou");42 service.setUser(user);43 }44 45 public static void main(String[] args) {46 clientToXML();47 }48 }
这样下来,只要项目还启动着web服务还没有停,我们可以运行SpringUserWsClient这个文件的main方法就可以调用到服务端的数据。
项目目录结构图:
整个服务的发布与调用都是采用xml形式开发的,其实如果你不习惯用的话可以文件中用代码实现,这样也是可以的。
到这里,让我想起了公司里面的那套框架的发布服务与调用服务,如果一个web服务想要加密以及MAC校验、设置访问的最大数、超时时间、描述等等,采用现在
这种发布服务的方式那该如何实现,客户端又该如何调用?或者说有没有更加简单的方式来实现这一切功能呢?这样的一些想法还都在摸索着前进,如果有那位热
心肠有高见的话,希望大家知识共享!
- WebService(2) JAX-WS、CXF、Spring3.0+
- WebService CXF学习(进阶篇2):JAX-WS讲解
- WebService CXF学习(进阶篇2):JAX-WS讲解
- 轻量级webservice解决方案Jax-ws(集成Spring3)
- WebService —— JAX-WS 与 CXF
- 简单的Jax-WS WebService实现-cxf
- WS (CXF) JAX-WS
- 基于CXF的JAX-WS、JAX-RS(RESTful)的webService
- 基于CXF的JAX-WS、JAX-RS(RESTful)的webService
- 基于CXF的JAX-WS、JAX-RS(RESTful)的webService
- 基于CXF的JAX-WS、JAX-RS(RESTful)的webService
- CXF之JAX-WS
- CXF JAX-WS 注释
- JAVA采用CXF框架开发基于JAX-WS(SOAP)规范的WebService服务器端
- 【转载】WebService —— JAX-WS 与 CXF
- WebService CXF学习(进阶篇1):JAX-WS讲解
- webservice服务端发布与调用 JAX-WS cxf axis2
- webservice中JAX-WS与CXF,Axis区别
- 说说下一代的报表设计器——Jaspersoft Studio
- oracle 中缩减 UNDOTBS01.DBF 释放磁盘空间
- PHP面试题宝典
- 根据数据动态创建radiobutton,默认选中第一个,并随点击切换碎片
- Android ListView详解
- WebService(2) JAX-WS、CXF、Spring3.0+
- 局域网部分电脑不能ping通
- liunx rabbitmq环境搭建
- wide-dhcpv6的dhcp6c配置
- PHP+JQuery+MySQL实现发布微博程序-PHP篇
- @Query注解的用法(Spring Data JPA)
- linux下追查线上问题常用命令
- 遍历jsp页面里面的值
- Scala处理文件