基于Spring + CXF框架的Web Service

2024-06-14 13:08
文章标签 java web spring 框架 cxf service

本文主要是介绍基于Spring + CXF框架的Web Service,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、用CXF编写基于Spring的Web service,也是需要分为Server服务器端、Client客户端的。

  1.1)、Server端,操作步骤,如下所示:

    第一步,创建spring的配置文件beans.xml,在其中配置SEI。
    第二步,在web.xml中,配置上CXF的一些核心组件。

  1.2、Client端,操作步骤,如下所示:

    第一步,生成客户端代码。
    第二步,创建客户端的spring配置文件beans-client.xml,并配置。
    第三步,编写测试类请求web service。

2、创建一个动态web工程,将apache-cxf-2.5.9\lib目录下面的包添加到此动态工程的lib目录下面,然后Build Path一下的哦。如果要看源代码,需要下载对应的src包的,不然无法进行查看源代码的。

创建web.xml配置文件,如下所示:

 1 <?xml version="1.0" encoding="UTF-8"?>2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3     xmlns="http://java.sun.com/xml/ns/javaee" 4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 5     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 6     id="WebApp_ID" version="2.5">7   <display-name>webServiceCxf_Spring</display-name>8   <welcome-file-list>9     <welcome-file>index.html</welcome-file>
10     <welcome-file>index.jsp</welcome-file>
11   </welcome-file-list>
12   
13   <!-- 配置beans.xml -->
14   <context-param>
15       <param-name>contextConfigLocation</param-name>
16       <param-value>classpath:beans.xml</param-value>
17    </context-param>
18    <!-- 应用启动的一个监听器 -->
19    <listener>
20       <listener-class>
21          org.springframework.web.context.ContextLoaderListener
22       </listener-class>
23    </listener>
24    
25    <!-- 所有请求都会先经过cxf框架 -->
26    <servlet>
27       <servlet-name>CXFServlet</servlet-name>
28       <servlet-class>
29          org.apache.cxf.transport.servlet.CXFServlet
30       </servlet-class>
31       <load-on-startup>1</load-on-startup>
32    </servlet>
33    <servlet-mapping>
34       <servlet-name>CXFServlet</servlet-name>
35       <url-pattern>/*</url-pattern>
36     </servlet-mapping>
37     
38 </web-app>

创建webservice的接口服务,如下所示:

 1 package com.bie.webservice.ws;2 3 import javax.jws.WebMethod;4 import javax.jws.WebService;5 6 import com.bie.webservice.bean.Order;7 8 /**9  * 
10  * @author
11  *
12  */
13 @WebService
14 public interface OrderWS {
15 
16     /**
17      * 根据订单号获取到订单信息
18      * 
19      * @param id
20      * @return
21      */
22     @WebMethod
23     public Order getOrderById(int id);
24 
25 }

创建webservice的接口服务实现类,如下所示:

 1 package com.bie.webservice.ws.impl;2 3 import javax.jws.WebService;4 5 import com.bie.webservice.bean.Order;6 import com.bie.webservice.ws.OrderWS;7 8 /**9  * 
10  * @author 项目部署的时候就创建好了webservice服务了。项目启动就自动部署了webservice了。
11  *
12  */
13 @WebService
14 public class OrderWSImpl implements OrderWS {
15 
16     /**
17      * 从对象什么时候创建呢,结论,项目部署的时候执行了
18      */
19     public OrderWSImpl() {
20         System.out.println("无参构造器执行,OrderWSImpl......");
21     }
22 
23     @Override
24     public Order getOrderById(int id) {
25         System.out.println("Server getOrderById() :  " + id);
26         return new Order(1, "大飞机", 999999999.00);
27     }
28 
29 }

创建一个是实体类,如下所示:

 1 package com.bie.webservice.bean;2 3 /**4  * 5  * @author6  *7  */8 public class Order {9 
10     private int id;// 订单编号
11     private String name;// 订单名称
12     private Double price;// 订单价格
13 
14     public int getId() {
15         return id;
16     }
17 
18     public void setId(int id) {
19         this.id = id;
20     }
21 
22     public String getName() {
23         return name;
24     }
25 
26     public void setName(String name) {
27         this.name = name;
28     }
29 
30     public Double getPrice() {
31         return price;
32     }
33 
34     public void setPrice(Double price) {
35         this.price = price;
36     }
37 
38     @Override
39     public String toString() {
40         return "Order [id=" + id + ", name=" + name + ", price=" + price + "]";
41     }
42 
43     public Order(int id, String name, Double price) {
44         super();
45         this.id = id;
46         this.name = name;
47         this.price = price;
48     }
49 
50 }

创建beans.xml配置文件,如下所示:

 1 <?xml version="1.0" encoding="UTF-8"?>2 <beans xmlns="http://www.springframework.org/schema/beans"3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"4     xmlns:jaxws="http://cxf.apache.org/jaxws"5     xsi:schemaLocation="http://www.springframework.org/schema/beans 6         http://www.springframework.org/schema/beans/spring-beans.xsd7         http://cxf.apache.org/jaxws 8         http://cxf.apache.org/jaxws">9     
10     <!-- 引cxf-2.5.9.jar此包下面的配置,这些配置不在此项目中,cxf的一些核心配置 -->
11     <import resource="classpath:META-INF/cxf/cxf.xml" />
12     <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
13     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
14 
15     <!-- 
16         jaxws:endpoint标签配置终端。
17         implementor是实现类。
18         address是虚拟地址。
19      -->
20     <jaxws:endpoint id="orderWS"
21         implementor="com.bie.webservice.ws.impl.OrderWSImpl"
22         address="/orderws">
23         <!-- 
24             <jaxws:inInterceptors> 
25                 <bean class="com.bie.interceptor.CheckUserInterceptor"></bean> 
26             </jaxws:inInterceptors> 
27         -->
28     </jaxws:endpoint>
29 
30 </beans>

项目结构,如下所示:

然后可以进行发布了,Run as -> Run on Server,启动项目,项目启动就自动部署了webservice了,可以进行访问,如下所示:

访问地址:http://localhost:8080/webServiceCxf_Spring/orderws?wsdl,其中项目名称后面的地址是beans.xml里面配置的address属性的值。

可以使用eclipse自带的web service浏览器进行查看,如下所示:

3、然后,创建一个客户端访问的动态web工程,将apache-cxf-2.5.9\lib目录下面的包添加到此动态工程的lib目录下面,然后Build Path一下的哦。如果要看源代码,需要下载对应的src包的,不然无法进行查看源代码的。此时,还是需要借助java自带的工具来生成客户端的代码,如下所示:

刷新项目,就可以看到生成的代码了,如下所示:

然后创建一个配置文件client-beans.xml,里面需要进行配置webservice的请求地址和所需要生成的动态代理对象。

 1 <?xml version="1.0" encoding="UTF-8"?>2 <beans xmlns="http://www.springframework.org/schema/beans"3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"4     xmlns:jaxws="http://cxf.apache.org/jaxws"5     xsi:schemaLocation="http://www.springframework.org/schema/beans 6        http://www.springframework.org/schema/beans/spring-beans.xsd7     http://cxf.apache.org/jaxws http://cxf.apache.org/jaxws">8 9     <!-- 
10         客户端配置:
11         serviceClass根据此类动态产生接口的代理对象。
12         address是指的是webservice请求的地址。
13      -->
14     <jaxws:client id="orderClient"
15         serviceClass="com.bie.webservice.ws.OrderWS"
16         address="http://localhost:8080/webServiceCxf_Spring/orderws">
17 
18         <!-- <jaxws:outInterceptors>
19             <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
20             <bean
21                 class="com.bie.webservice.ws.interceptor.AddUserInterceptor">
22                 <constructor-arg name="name" value="张姗姗" />
23                 <constructor-arg name="password" value="123456" />
24             </bean>
25         </jaxws:outInterceptors> -->
26     </jaxws:client>
27 
28 </beans>

最后搞一个客户端的访问类,就可以进行运行了,如下所示:

 1 package com.bie.webservice.ws.client;2 3 import org.springframework.context.support.ClassPathXmlApplicationContext;4 5 import com.bie.webservice.ws.Order;6 import com.bie.webservice.ws.OrderWS;7 8 /**9  * 
10  * @author 客户端访问webservice的代码
11  *
12  */
13 public class ClientCxfSpring {
14 
15     public static void main(String[] args) {
16         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
17                 new String[] { "client-beans.xml" });
18         OrderWS orderWS = (OrderWS) context.getBean("orderClient");
19         Order order = orderWS.getOrderById(1);
20         System.out.println(order);
21     }
22 
23 }

4、如何在此基础上添加自定义拦截器,步骤如下所示:

第一步,Server端,在beans.xml中,在endpoint中配置上入拦截器。

 1 package com.bie.webservice.interceptor;2 3 import javax.xml.namespace.QName;4 5 import org.apache.cxf.binding.soap.SoapMessage;6 import org.apache.cxf.headers.Header;7 import org.apache.cxf.interceptor.Fault;8 import org.apache.cxf.phase.AbstractPhaseInterceptor;9 import org.apache.cxf.phase.Phase;
10 import org.w3c.dom.Element;
11 import org.w3c.dom.Node;
12 
13 /**
14  * 查检用户的拦截器
15  * 
16  * @author
17  *
18  */
19 
20 public class CheckUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
21 
22     private static final String name = "张姗姗";
23     private static final String password = "123456";
24     
25     public CheckUserInterceptor() {
26         super(Phase.PRE_PROTOCOL);
27         System.out.println("CheckUserInterceptor()");
28     }
29 
30     /**
31      * 请求体,服务器端需要解析请求头信息
32      * 
33      * <soap:Envelope> 
34      *     <head>
35      *         <zhangsansan>
36      *             <name>zhangsansan</name>
37      *             <password>123456</password>
38      *         </zhangsansan>
39      *  </head>
40      *     <Body> 
41      *         <sayHello> 
42      *             <arg0>张姗姗</arg0> 
43      *         </sayHello> 
44      *     </Body>
45      * </soap:Envelope>
46      */
47     @Override
48     public void handleMessage(SoapMessage soapMessage) throws Fault {
49         // 获取到请求头的信息
50         QName qName = QName.valueOf("zhangsansan");
51         // 获取到请求头
52         Header header = soapMessage.getHeader(qName);
53         // 判断是否为空
54         if(header != null) {
55             // 获取到对象,强转为w3c的元素标签
56             Element element = (Element) header.getObject();
57             // 获取到name标签的值
58             Node nameNode = element.getElementsByTagName("name").item(0);
59             // 获取到name的值
60             String nameValue = nameNode.getTextContent();
61             // 获取到pasword标签的值
62             Node passwordNode = element.getElementsByTagName("password").item(0);
63             // 获取到pasword的值
64             String paswordValue = passwordNode.getTextContent();
65             // 开始进行判断
66             if(CheckUserInterceptor.name.equals(nameValue) && CheckUserInterceptor.password.equals(paswordValue)) {
67                 System.out.println("Server 通过拦截器......");
68                 return;
69             }
70         }
71         // 如果不能通过
72         System.out.println("Sorry Server 不通过拦截器......");
73         // 抛出异常信息
74         throw new Fault(new RuntimeException("账号密码错误......"));
75     }
76 
77 }

然后在服务器端的beans.xml进行配置,如下所示:

 1 <?xml version="1.0" encoding="UTF-8"?>2 <beans xmlns="http://www.springframework.org/schema/beans"3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"4    xmlns:jaxws="http://cxf.apache.org/jaxws"5    xsi:schemaLocation="http://www.springframework.org/schema/beans 6    http://www.springframework.org/schema/beans/spring-beans.xsd7         http://cxf.apache.org/jaxws http://cxf.apache.org/jaxws">8     9     <!-- 引cxf-2.5.9.jar此包下面的配置,这些配置不在此项目中,cxf的一些核心配置 -->
10     <import resource="classpath:META-INF/cxf/cxf.xml" />
11     <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
12     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
13 
14     <!-- 
15         jaxws:endpoint标签配置终端。
16         implementor是实现类。
17         address是虚拟地址。
18      -->
19     <jaxws:endpoint id="orderWS"
20         implementor="com.bie.webservice.ws.impl.OrderWSImpl"
21         address="/orderws">
22             <!-- 服务器端配置入拦截器 -->
23             <jaxws:inInterceptors> 
24                 <!-- 配置自定义的拦截器,注入到ioc容器中 -->
25                 <bean class="com.bie.webservice.interceptor.CheckUserInterceptor"></bean> 
26             </jaxws:inInterceptors> 
27     </jaxws:endpoint>
28 
29 </beans>

如果开发完毕,重启项目,报下面的错误,我的操作是clean项目,清空tomcat下面的项目,清空tomcat,重启项目解决的。

1 cvc-complex-type.2.4.c: 通配符的匹配很全面, 但无法找到元素 'context:property-placeholder' 的声明

第二步,Client端,通过Client对象设置出拦截器。

  1 package com.bie.webservice.ws.interceptor;2 3 import java.util.List;4 5 import javax.xml.namespace.QName;6 import javax.xml.parsers.DocumentBuilder;7 import javax.xml.parsers.DocumentBuilderFactory;8 import javax.xml.parsers.ParserConfigurationException;9 10 import org.apache.cxf.binding.soap.SoapMessage;11 import org.apache.cxf.headers.Header;12 import org.apache.cxf.interceptor.Fault;13 import org.apache.cxf.phase.AbstractPhaseInterceptor;14 import org.apache.cxf.phase.Phase;15 import org.apache.xml.utils.DOMHelper;16 import org.w3c.dom.Document;17 import org.w3c.dom.Element;18 19 /**20  * 21  * @author 拦截的是某一个消息,所以泛型是SoapMessage22  *23  */24 public class ClientValidateUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> {25 26     private String name;// 账号27     private String password;// 密码28 29     /**30      * 此构造器是关键点,决定了什么时候拦截器会拦截到消息31      * 32      * @param phase33      */34     public ClientValidateUserInterceptor(String name, String password) {35         // 准备协议化的时候进行拦截调用36         super(Phase.PRE_PROTOCOL);37         this.name = name;38         this.password = password;39         System.out.println("Client 客户端,拦截器初始化......");40     }41 42     /**43      * 请求体44      * 45      * <soap:Envelope> 46      *     <head>47      *         <zhangsansan>48      *             <name>zhangsansan</name>49      *             <password>123456</password>50      *         </zhangsansan>51      *  </head>52      *     <Body> 53      *         <sayHello> 54      *             <arg0>张姗姗</arg0> 55      *         </sayHello> 56      *     </Body>57      * </soap:Envelope>58      */59     @Override60     public void handleMessage(SoapMessage soapMessage) throws Fault {61         // 获取到头信息,向头部信息设置值62         List<Header> headers = soapMessage.getHeaders();63         // 此时需要构造这种结构的数据64 //        <zhangsansan>65 //            <name>zhangsansan</name>66 //            <password>123456</password>67 //        </zhangsansan>68         69         // 第一步:初始化一个XML解析工厂70         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();71         // 第二步:创建一个DocumentBuilder实例72         DocumentBuilder builder = null;73         try {74             builder = factory.newDocumentBuilder();75         } catch (ParserConfigurationException e) {76             // TODO Auto-generated catch block77             e.printStackTrace();78         }79         // 第三步:构建一个Document实例80         Document doc = builder.newDocument();81         // standalone用来表示该文件是否呼叫其它外部的文件。若值是 ”yes” 表示没有呼叫外部文件82         doc.setXmlStandalone(true);83         // 第四步:创建一个根节点,名称为root,并设置一些基本属性,创建标签84         Element rootElement = doc.createElement("zhangsansan");85         // 设置节点属性86         // rootElement.setAttribute("attr", "root");87         // 设置标签之间的内容88         // rootElement.setTextContent("root attr");89         90         // 开始设置<zhangsansan>下面的标签<name>zhangsansan</name>91         Element nameElement = doc.createElement("name");92         nameElement.setTextContent(this.name);93         // 第五步:把节点添加到Document中,再创建一些子节点加入,将子标签添加到父标签中94         rootElement.appendChild(nameElement);95         96         // 开始设置<zhangsansan>下面的标签<name>zhangsansan</name>97         Element passwordElement = doc.createElement("password");98         passwordElement.setTextContent(this.password);99         // 第五步:把节点添加到Document中,再创建一些子节点加入,将子标签添加到父标签中
100         rootElement.appendChild(passwordElement);
101         
102         // 第六步:把构造的XML结构,写入到具体的文件中
103         // 参数一QName起一个唯一的名字,这个名称必须和rootElement标签的值必须一样
104         // 参数二就是rootElement根节点
105         Header header = new Header(new QName("zhangsansan"), rootElement);
106         // 将此请求体和构建的请求头发送给服务器端
107         headers.add(header);
108         
109         System.out.println("Client handleMessage Interceptor......");
110         
111         // DOMHelper.createDocument()方法过期了
112         // Document createDocument = DOMHelper.createDocument();
113     }
114 
115 }

然后在客户端的beans.xml进行配置,如下所示:

 1 <?xml version="1.0" encoding="UTF-8"?>2 <beans xmlns="http://www.springframework.org/schema/beans"3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"4     xmlns:jaxws="http://cxf.apache.org/jaxws"5     xsi:schemaLocation="http://www.springframework.org/schema/beans 6        http://www.springframework.org/schema/beans/spring-beans.xsd7     http://cxf.apache.org/jaxws http://cxf.apache.org/jaxws">8 9     <!-- 
10         客户端配置:
11         serviceClass根据此类动态产生接口的代理对象。
12         address是指的是webservice请求的地址。
13      -->
14     <jaxws:client id="orderClient"
15         serviceClass="com.bie.webservice.ws.OrderWS"
16         address="http://localhost:8080/webServiceCxf_Spring/orderws">
17 
18         <!-- 客户端配置出拦截器类 -->
19         <jaxws:outInterceptors>
20             <!-- <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> -->
21             <bean
22                 class="com.bie.webservice.ws.interceptor.ClientValidateUserInterceptor">
23                 <!-- 通过构造参数传递给客户端拦截器类 -->
24                 <constructor-arg name="name" value="张姗姗" />
25                 <constructor-arg name="password" value="123456" />
26             </bean>
27         </jaxws:outInterceptors>
28     </jaxws:client>
29 
30 </beans>

使用tomcat启动服务端,然后客户端访问服务端,效果如下所示:

这篇关于基于Spring + CXF框架的Web Service的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1060490

相关文章

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Java中的@SneakyThrows注解用法详解

《Java中的@SneakyThrows注解用法详解》:本文主要介绍Java中的@SneakyThrows注解用法的相关资料,Lombok的@SneakyThrows注解简化了Java方法中的异常... 目录前言一、@SneakyThrows 简介1.1 什么是 Lombok?二、@SneakyThrows