cxf springmvc
在上一篇文章中,我逐步介绍了使用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服务定义为能够交换消息的通信端点的集合。 这些通信端点称为端口。 端口由两部分组成。
- 包含Web服务公开的公共接口。 接口包含所有方法,调用它们所需的参数以及它们返回的响应结构。
- 第二部分将公共接口绑定到诸如http之类的网络协议。 绑定包括诸如公共接口的位置和服务的消息格式之类的信息。
SOAP通讯样式
存在两种类型的沟通方式
- 文件
- 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>
例如,让我们创建一个简单的书架网络服务。 为简单起见,让我们假设以下用例。
- 在自己的书中插入一本书
- 从书架上按标题检索一本书。
开发服务
可以通过两种方式完成:“代码优先”和“合同优先”。 我们将使用代码优先方法。
创建服务端点接口(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 {
@WebMethod
public String insertBook(BookVO bookVO);
@WebMethod
public 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,该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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws
http://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:endpoint
id="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。 因此,让我们看一下步骤。
- 使用您选择的IDE创建一个简单的Maven项目。 我目前正在使用IntelliJ,它很棒。 可以说该项目的名称为DemoClient。
- 如创建框架应用程序部分所示,添加CXF依赖项。
- 既然我们知道了SEI和公共方法以及绑定对象是什么。 我们将在客户端创建它们,以免给我们带来麻烦。 如果有很多这样的类,我们可以使用wsdl2java等工具来生成我们的代码。
- 在与父SEI完全相同的包结构中创建存根SEI。
- 以与父BookVO相同的包结构创建BookVO。
- 以上类应与在父应用程序中创建的类完全相同。
- 我们不需要在客户端创建SEI实现。
- 现在,我们将使用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 book
BookVO 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 book
bookVO = 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 Asimov
Process finished with exit code 0
您可以在Apache CXF中探索大量其他内容,例如创建动态客户端,拦截器,利用其他传输协议,基于https的Web服务等。但是,我打算将本文作为入门教程。
ew,这又是一个漫长的帖子。 我需要提高写作技巧以缩短篇幅。 但我仍然希望您喜欢它并发现它有用。 我打算在我的下一篇文章中介绍有关Web服务的javascript客户端。 在那之前,再见,编码愉快。
翻译自: https://www.javacodegeeks.com/2013/06/developing-soap-web-service-using-apache-cxf.html
cxf springmvc