使用Apache CXF开发SOAP Web服务

在上一篇文章中,我逐步介绍了使用apache CXF开发简单的RESTFull服务的步骤。 在本文中,我将讨论使用CXF开发SOAP Web服务。 在继续前进之前,让我们了解构成SOAP Web服务的一些概念/元素。

SOAP或简单对象访问协议

SOAP是一种协议,用于使用诸如http,smtp等应用程序协议作为载体在网络上交换基于XML的消息。 SOAP消息包含一个SOAP信封。 信封可以分为标题和正文。 标头包含与上下文相关的定义(例如安全性),而主体包含实际的应用程序数据。 典型的SOAP消息看起来像

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header></soap:Header><soap:Body><m:GetStockPrice xmlns:m="http://www.example.org/stock"><m:StockName>IBM</m:StockName></m:GetStockPrice></soap:Body>
</soap:Envelope>

WSDL或Web服务描述语言

WSDL是基于标准的XML语言,用于描述Web服务。 WSDL完全描述了Web服务公开的公共接口,期望的参数,返回的输出结构以及Web服务的位置。 WSDL将Web服务定义为能够交换消息的通信端点的集合。 这些通信端点称为端口。 端口由两部分组成。

  1. 包含Web服务公开的公共接口。 接口包含所有方法,调用它们所需的参数以及它们返回的响应结构。
  2. 第二部分将公共接口绑定到诸如http之类的网络协议。 绑定包括诸如公共接口的位置和服务的消息格式之类的信息。

SOAP通讯样式

存在两种类型的沟通方式

  1. 文献
  2. RPC

SOAP Web服务使用的通信样式在其WSDL中定义。

在文档样式中,作为肥皂主体一部分的应用程序数据作为XML文档发送。 可以通过也是WSDL一部分的xml模式来完全验证该文档。 由于XML可以按照服务开发人员的意愿包含结构,因此,编组和解编xml有效负载的责任在于提供者和使用者代码的末尾。

顾名思义,以RPC风格表示,使用者调用服务方法就像调用本地方法一样。 为此,RPC消息包含使用者可以调用的公共接口方法的列表。 这些方法按名称列为xml元素。 这些方法所需的方法参数构成方法元素的子元素。 封送/取消封送的责任在于Web服务框架。 该框架包含其自己的封送/解封库。 RPC样式导致应用程序代码和Web服务框架之间的代码紧密耦合,因此规范是创建文档样式服务。 掌握了关键概念之后,让我们看一下如何使用Apache CXF编写肥皂网络服务的示例。

获取本教程的源代码

我已经在SVN中提交了本教程的源文件。

  • 您可以从以下网站下载该Web应用程序: http : //subversion.assembla.com/svn/weblog4j/Weblog4jDemo/trunk
  • 您可以从以下 网址 下载客户端: http : //subversion.assembla.com/svn/weblog4j/DemoClient/trunk

注意:这两个都是ItelliJ maven项目,因此您可以将它们直接导入到intelliJ IDE或将文件手动复制到其他IDE

创建一个struts2框架应用程序以包含您的服务。

您可以使用任何MVC框架,但出于我自己的原因,我更喜欢struts2。 您可以在此处看到有关如何使用Eclipse在eclipse中创建空的struts2应用程序的示例。

添加CXF依赖项

在您的项目POM中添加以下依赖项以下载CXF jar

<properties><cxf.version>2.5.0</cxf.version>
</properties>
<dependencies><!-- apache cxf --><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>${cxf.version}</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxrs</artifactId><version>${cxf.version}</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>${cxf.version}</version></dependency>
</dependencies>

例如,让我们创建一个简单的书架网络服务。 为简单起见,让我们假设以下用例。

  1. 在自己的书中插入一本书
  2. 从书架上按标题检索一本书。

开发服务

可以通过两种方式完成:“代码优先”和“合同优先”。 我们将使用代码优先方法。

创建服务端点接口(SEI)

让我们创建一个名为BookShelfService的SEI接口

package com.aranin.weblog4j.services;import com.aranin.weblog4j.vo.BookVO;import javax.jws.WebMethod;
import javax.jws.WebService;@WebService
public interface BookShelfService {@WebMethodpublic  String insertBook(BookVO bookVO);@WebMethodpublic  BookVO getBook(String title);
}

如果看上面的SEI,可以看出它是一个普通的Java接口,但有两个注释

  • @WebService –这是一个注释JAXWS库。 它将普通的POJO转换为Web服务。 在我们的例子中,注释位于接口定义的正上方,它通知BookShelfService不是普通接口,而是Web服务接口或SEI。 该注释还有其他一些属性可以完全定义Web服务,但是我们现在不会使用它。
  • @WebMethod –此注释是可选的,主要用于为wsdl中的公共方法提供名称属性。

实施服务。

现在我们有了SEI,因此让我们在BookShelfServiceImpl的接口中实现方法

package com.aranin.weblog4j.services;import com.aranin.weblog4j.hashdb.HashDB;
import com.aranin.weblog4j.vo.BookVO;import javax.jws.WebService;@WebService(endpointInterface = "com.aranin.weblog4j.services.BookShelfService",serviceName="bookShelfService")
public class BookShelfServiceImpl implements BookShelfService {public String insertBook(BookVO bookVO) {HashDB.insertBook(bookVO);return "Book with name : " + bookVO.getBookName() + " is now available on the shelf";  //To change body of implemented methods use File | Settings | File Templates.}public BookVO getBook(String title) {return HashDB.getBook(title);  //To change body of implemented methods use File | Settings | File Templates.}
}

此类是实现SEI的简单POJO。 这里唯一值得注意的是@WebService批注。 如果您仔细看一下,我们提供了它实现的SEI的完全合格的类名和Web服务的名称。

数据绑定类(BookVO)

package com.aranin.weblog4j.vo;import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;@XmlRootElement(name = "Book")
public class BookVO implements Serializable {private long bookId;private String bookName;private String author;public long getBookId() {return bookId;}public void setBookId(long bucketId) {this.bookId = bookId;}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}
}

这里唯一要注意的是@XmlRootElement批注。 该注释是JAXB库的一部分。 CXF使用JAXB作为默认数据绑定组件。 由于BookVO在Web服务调用期间需要作为XML进行传输,因此需要在CXF安装中由JAXB引擎进行编组/解组。 使用@XmlRootElement批注,我们可以帮助JAXB将BookVO类映射到xml,并将其name属性作为xml的根元素。

基于Spring的服务器Bean

使CXF成为Web服务框架的第一选择的原因在于,它通过基于Spring的配置文件发布其服务端点。 让我们创建一个配置文件并在其中注册我们的服务。 我们将文件命名为beans.xml并将其保存在应用程序的WEB-INF文件夹中

<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://cxf.apache.org/jaxrshttp://cxf.apache.org/schemas/jaxrs.xsdhttp://cxf.apache.org/jaxwshttp://cxf.apache.org/schemas/jaxws.xsd"><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" />	<jaxws:endpointid="bookShelfService"implementor="com.aranin.weblog4j.services.BookShelfServiceImpl"address="/bookshelfservice" /></beans>

现在要加载beans.xml,我们只需在web.xml中添加以下内容

<context-param>
<param-name>contextConfigLocation</param-name><param-value>/WEB-INF/beans.xml,/WEB-INF/applicationContext.xml</param-value>
</context-param>

最后,我们需要通过web.xml连接spring和CXF。

<servlet><servlet-name>CXFServlet</servlet-name><display-name>CXF Servlet</display-name><servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class><load-on-startup>2</load-on-startup>
</servlet><servlet-mapping><servlet-name>CXFServlet</servlet-name><url-pattern>/*</url-pattern>
</servlet-mapping>

注意:我没有包括Spring ContextLoaderListner的加载。 如果您使用struts2入门原型通过maven创建了struts2应用程序,那么spring将由maven项目本身下载并注册。

现在您的Web服务已准备就绪。 在任何servlet容器中编译和部署应用程序。 如果一切都很好,那么您可以在以下位置看到您的wsld: http:// localhost:8080 / weblog4jdemo / bookshelfservice?wsdl

创建您的客户

有许多工具可用于使用wsdl生成客户端代码。 为了节省您的更多麻烦,我们将利用CXF自己的前端api。 因此,让我们看看步骤。

  1. 使用您选择的IDE创建一个简单的Maven项目。 我目前正在使用IntelliJ,它很棒。 可以说该项目的名称为DemoClient。
  2. 如创建框架应用程序部分所示,添加CXF依赖项。
  3. 既然我们知道SEI,公共方法和绑定对象是什么。 我们将在客户端创建它们,以免给我们带来麻烦。 如果有很多此类,我们可以使用wsdl2java等工具来生成我们的代码。
  4. 在与父SEI完全相同的包结构中创建存根SEI。
  5. 以与父BookVO相同的包结构创建BookVO。
  6. 以上类应与在父应用程序中创建的类完全相同。
  7. 我们不需要在客户端创建SEI实现。
  8. 现在,我们将使用JaxWsProxyFactoryBean创建一个客户端。 此类是与SEI代理一起使用以调用Web服务方法的工厂。 这是课程。
package com.aranin.weblog4j.client;import com.aranin.weblog4j.services.BookShelfService;
import com.aranin.weblog4j.vo.BookVO;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;public class DemoClient {public static void main(String[] args){String serviceUrl = "http://localhost:8080/weblog4jdemo/bookshelfservice";JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();factory.setServiceClass(BookShelfService.class);factory.setAddress(serviceUrl);BookShelfService bookService = (BookShelfService) factory.create();//insert bookBookVO bookVO = new BookVO();bookVO.setAuthor("Issac Asimov");bookVO.setBookName("Foundation and Earth");String result = bookService.insertBook(bookVO);System.out.println("result : " + result);bookVO = new BookVO();bookVO.setAuthor("Issac Asimov");bookVO.setBookName("Foundation and Empire");result = bookService.insertBook(bookVO);System.out.println("result : " + result);bookVO = new BookVO();bookVO.setAuthor("Arthur C Clarke");bookVO.setBookName("Rama Revealed");result = bookService.insertBook(bookVO);System.out.println("result : " + result);//retrieve bookbookVO = bookService.getBook("Foundation and Earth");System.out.println("book name : " + bookVO.getBookName());System.out.println("book author : " + bookVO.getAuthor());}
}

这是上述调用的输出

INFO: Creating Service {http://services.weblog4j.aranin.com/}BookShelfServiceService from class com.aranin.weblog4j.services.BookShelfService
result : Book with name : Foundation and Earth is now available on the shelf
result : Book with name : Foundation and Empire is now available on the shelf
result : Book with name : Rama Revealed is now available on the shelf
book name : Foundation and Earth
book author : Issac AsimovProcess finished with exit code 0

您可以在Apache CXF中探索大量其他内容,例如创建动态客户端,拦截器,利用其他传输协议,基于https的Web服务等。但是,我打算将本文作为入门教程。

ew,这又是一个漫长的帖子。 我需要提高写作技巧以缩短篇幅。 但我仍然希望您喜欢它并发现它有用。 我打算在我的下一篇文章中撰写有关Web服务的javascript客户端的文章。 在那之前,再见,编码愉快。

参考: Weblog4j博客上的JCG合作伙伴 Niraj Singh 使用Apache CXF开发SOAP Web服务 。

翻译自: https://www.javacodegeeks.com/2013/06/developing-soap-web-service-using-apache-cxf.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pkill mysql_每天一个linux命令:kill命令

终止一个进程或终止一个正在运行的程式&#xff0c;一般是通过kill 、killall、pkill、xkill 等进行。比如一个程式已死掉&#xff0c;但又不能退出&#xff0c;这时就应该考虑应用这些工具。另外应用的场合就是在服务器管理中&#xff0c;在不涉及数据库服务器程式的父进程的停…

HTML5中如何检查浏览器是否支持本地存储

如果你的浏览器支持该特性的话&#xff0c;那么全局对象&#xff1a;window上会有一个localStorage的属性&#xff0c;反之&#xff0c;你的浏览器不支持的话&#xff0c;那么该属性值为undefinedJavaScript function supports_local_storage(){ return !!window.localStorage…

解决swiper-slide在ion-slide-box不滑动的问题(暂且这么描述)

1&#xff0c;开发环境ionic1angularjs1 嗯对的版本都是最低版本 页面结构想要完成的功能是这样的&#xff08;比较丑 &#xff0c;不接受批评&#xff0c;捂脸&#xff09; 大致如图 代码结构&#xff1a; <ion-slide-box><ion-slide> //列表 <div class"…

java趣味题-打印99乘法表

java趣味题-打印99乘法表 public class First102 { public static void main(String[] args) { for(int i1;i<9;i){ for(int j1;j<i;j){ System.out.print(i"*"j""i*j" "); } System.out.println(""); } } }posted…

MOXy的@XmlVariableNode – JSON模式示例

我们正在向EclipseLink MOXy添加从域模型生成JSON模式的 功能 。 为此&#xff0c;我们创建了一个新的变量节点映射。 在本文中&#xff0c;我将通过将Java模型映射到JSON模式来演示新的映射。 您可以使用每晚构建的EclipseLink 2.6.0进行尝试&#xff1a; http://www.eclips…

在HTML5中如何利用Canvas处理并存储图片

HTML5中增加的Canvas元素&#xff0c;配合JS灵活的语法&#xff0c;处理起图片变得异常简单&#xff0c;不需要在客户端用C/C 写一大堆代码&#xff0c;对于熟悉JS的程序员来说&#xff0c;只需要考虑处理图片的逻辑了。 canvas中如果想要处理图片就需要借助ImageData这个对象&…

python正则表达式research_八Python正则表达式

正则表达式是搜索、替换和解析复杂字符串的一种强大而标准的方法&#xff0c;Python中的正则相关的东西全在re模块下。1 常用的匹配^匹配字符串的开始$匹配字符串的结尾\b匹配一个单词的边界\d匹配任意数字\D匹配任意非数字字符x?匹配一个可选的x(匹配1次或0次x字符)x*匹配0次…

Win10 系统直接在目录下打开cmd

每次用cmd命令&#xff0c;就要定位到当前文件夹&#xff0c;很麻烦&#xff0c;于是想了下&#xff0c;可不可以直接定位到要操作的文件夹&#xff0c;百度了一下&#xff0c;果然&#xff0c;度娘没有让我失望&#xff0c; 美滋滋的试了下。真的可以。在此记录下&#xff0c;…

使用Apache Lucene 4.3轻松进行搜索

Lucene是用Java编写的全文搜索引擎&#xff0c;可以为任何应用程序提供强大的搜索功能。 Lucene的核心是基于文件的全文本索引。 Lucene提供API创建该索引&#xff0c;然后向该索引添加和删除内容。 此外&#xff0c;它允许使用功能强大的搜索算法从该索引中搜索和检索信息。 可…

Html5中新增的表单元素详解

HTML5 的新的表单元素&#xff1a; HTML5 拥有若干涉及表单的元素和属性。•datalist•keygen•outputdatalist 元素datalist 元素规定输入域的选项列表。列表是通过 datalist 内的 option 元素创建的。如需把 datalist 绑定到输入域&#xff0c;请用输入域的 list 属性引用 da…

今日学到乱写

EXPLAIN 直接上图 一个个说&#xff1a; select_type 查询中每个select子句的类型&#xff08;简单OR复杂&#xff09; a. SIMPLE&#xff1a;查询中不包含子查询或者UNION b. 查询中若包含任何复杂的子部分&#xff0c;最外层查询则被标记为&#xff1a;PRIMARY c. 在SELECT或…

JavaScript日期格式化处理

1 /**2 * 获取年月&#xff0c;如&#xff1a;2018-083 */4 export function getMonth () {5 return formatDate(new Date(), yyyy-MM)6 }7 8 /**9 * 10 * param {*} date 11 * param {*} fmt : yyyy-MM、yyyy-MM-dd、yyyy-MM-dd hh:mm、yyyy-MM-dd hh:mm:ss 12 */ 13 …

在JBoss AS 7上部署BroadleafCommerce 2.0

前2个步骤与Broadleaf的具体联系并不紧密&#xff0c;但提到该步骤使执行&#xff08;复制/粘贴&#xff09;这些步骤变得容易。 步骤&#xff03;1&#xff1a;在JBoss AS中配置数据源。 <datasource jta"true" jndi-name"java:jboss/datasources/Broadlea…

hash的算法 java_【数据结构与算法】一致性Hash算法及Java实践

追求极致才能突破极限一、案例背景1.1 系统简介首先看一下系统架构&#xff0c;方便解释&#xff1a;页面给用户展示的功能就是&#xff0c;可以查看任何一台机器的某些属性(以下简称系统信息)。消息流程是&#xff0c;页面发起请求查看指定机器的系统信息到后台&#xff0c;后…

MySQL之汇总数据(AVG,COUNT,MAX,MIN,SUM)

备注&#xff1a;sum和count的不同&#xff1a;count()函数里面的参数是列名的的时候,那么会计算有值项的次数。 //行数Sum()函数里面的参数是列名的时候&#xff0c;是计算列名的值的相加&#xff0c;而不是有值项的总数。 //行内数据的和table testFieldTypeNullKeyDefault…

使用HTML5实现地理位置定位

HTML5 Geolocation&#xff08;地理定位&#xff09;用于定位用户的位置。定位用户的位置HTML5 Geolocation API 用于获得用户的地理位置。鉴于该特性可能侵犯用户的隐私&#xff0c;除非用户同意&#xff0c;否则用户位置信息是不可用的。浏览器支持Internet Explorer 9、Fire…

暑假第五周计划

在上一周根据视频在电脑上安装了一个伪Hadoop&#xff0c;只有一个虚拟机&#xff0c;并且配置好了环境变量&#xff0c;可以在命令行运行程序自带的一些例子&#xff0c;比如计算圆周率&#xff0c;统计文本文件的字符数 遇到的问题主要就是对linux的操作命令不熟悉&#xff0…

Java EE CDI依赖关系消歧示例

在本教程中&#xff0c;我们将向您展示如何避免CDI bean中的依赖关系消除歧义。 在CDI中&#xff0c;我们可以为应用程序中不同客户端的接口的多个实现实现依赖项注入。 依赖关系消除歧义的问题是客户端如何在不同的实现中调用特定的实现&#xff0c;而不会发生任何错误。 为了…

linux java 安装配置_类Linux环境安装jdk1.8及环境变量配置详解

配置很简单&#xff0c;但是每次都要查一下&#xff0c;索性就记录下1. 安装前准备1.1 创建安装目录&#xff0c;习惯上通常安装在/usr/local/jdk8目录下mkdir /usr/local/jdk81.2 查看是否安装过jdk&#xff0c;安装前要把之前的删除干净# 通过jdk环境变量查看echo $JAVA_HOME…

Mac版Anaconda安装R语言iGraph包

Anaconda官网给出的R语言Igraph包安装方法&#xff1a;https://anaconda.org/r/r-igraph 查阅Anaconda官方文档&#xff0c;可以通过以下控制台命令安装R语言Igraph包。 conda install -c r r-igraph 在控制台执行后&#xff0c;系统可能会提示未找到conda指令&#xff0c; 所以…