设为首页 收藏本站
查看: 902|回复: 0

[经验分享] WebService之JAX-WS、CXF、Spring3.0+

[复制链接]

尚未签到

发表于 2017-3-1 06:03:18 | 显示全部楼层 |阅读模式
  前言:
  面对工作的需要,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如下:
DSC0000.gif

  1、首先创建一个web项目,将得到的包拷贝到lib目录下
  既然是想发布自己的服务,首先创建一个接口


DSC0001.gif IComplexUserService


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 chh
12  *
13  */
14 @WebService
15 @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 }
  接口只是用来定义,具体操作要在它下面的实现类中得以体现


ComplexUserService


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 chh
14  *
15  */
16 @WebService
17 @SOAPBinding(style=Style.RPC)
18 @SuppressWarnings("deprecation")
19 public class ComplexUserService implements IComplexUserService {
20
21     @Override
22     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     @Override
34     public void setUser(User user) {
35         System.out.println("############Server setUser###########");
36         System.out.println("setUser:" + user);
37     }
38
39 }
  实体


User


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     @Override
54     public String toString() {
55         return this.id + "#" + this.name + "#" + this.email + "#" + this.address;
56     }
57
58 }

Users


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 }
  自定义消息拦截器(如果在你的项目中不需要用到拦截器的时候,可以撤掉不用)


MessageInterceptor


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 chh
10  *
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)


applicationContext-server.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.xsd
10     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容器


web.xml


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   这篇博客下面的几个段落)。
  根据服务端定制客户端


applicationContext-client.xml


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/context
10     http://www.springframework.org/schema/context/spring-context-3.0.xsd
11     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有点不同。


SpringUsersWsClient


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 chh
13  *
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校验、设置访问的最大数、超时时间、描述等等,采用现在
  这种发布服务的方式那该如何实现,客户端又该如何调用?或者说有没有更加简单的方式来实现这一切功能呢?这样的一些想法还都在摸索着前进,如果有那位热
  心肠有高见的话,希望大家知识共享!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-348467-1-1.html 上篇帖子: OSGi系列 下篇帖子: Geoserver基本使用、WMS服务发布与OpenLayers测试
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表