基于Maven在Spring中集成CXF Web Service框架

引言: 在跨系统和跨平台的系统通信中,WebService是一个事实上的标准,其以平台无关性,获得了广泛的应用。本文将讲述如何基于Spring来集成CXF,并开发出第一个Hello World的应用。

1.  Web Service是什么?

Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。

Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web
Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。

2.  Web Service模型

WebService体系结构基于三种角色(即服务提供者、服务注册中心和服务请求者)之间的交互。交互涉及发布、查找和绑定操作,这些角色和操作一起作用于WebServices组件,即WebServices软件模块及其描述。在典型情况下,服务提供者托管可通过网络访问的的软件模块,定义WebServices的服务描述并把它发布到服务注册中心;服务请求者使用查找操作来从服务注册中心检索服务描述,然后使用服务描述与服务提供者进行绑定并调用WebServices实现和同它交互。

面向服务的体系结构(SOA),如图所示:

从图中可以看出,SOA结构中共有三种角色:

(1)、服务提供者:发布自己的服务,并且对服务请求进行响应。

(2)、服务注册中心:注册已经发布的WebServices,对其进行分类,并提供搜索服务。

(3)、服务请求者:利用服务注册中心查找所需的服务,然后使用该服务。

SOA体系结构中的组件必须具有上述一种或多种角色,这些角色之间使用三种操作:

(1)、发布操作:使服务提供者可以向服务注册中心注册自己的功能及访问接口。

(2)、查找操作:使服务请求者可以通过服务注册中心查找特定种类的服务。

(3)、绑定操作:使服务请求者能够真正使用服务提供者提供的服务。

3.  WebService开源框架的选择

目前主流的Web Service框架主要有3种: Axis 2, CXF, 和 Spring WS。其中Spring WS出身Spring框架,名门出身,但是使用了几次,太关注于标准支持,比较难以使用。

Axis 2和CXF都是来自于Apache, 各个方面相差不多,但是考虑到目前市场上使用CXF比较多一点,就才用了CXF。

4.  基于CXF创建WebService

项目背景是Spring 3.2, CXF: 2.7.14,JDK 1.6, Maven 3.2.3.

4.1  在POM.xml中添加正确的依赖包。

              <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-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>

注意: 第二个http的包必须进行添加,否则会报错。

4.2 创建服务接口

@WebService
public interface IHelloWorld {
	@WebMethod
	public String sayHello(@WebParam(name = "username") String username);
	public void setUser(String username);
}

注意:“@WebService”标记表示该接口是一个WebService服务;“@WebMethod”表示表示以下方法为WebService服务中的方法;“@WebParam(name="username")”表示方法中的参数,username属性限制了参数的名称,若没有指定该属性,参数将被重命名。

4.3  创建服务实现类

public class HelloWorldImpl implements IHelloWorld {
	@Override
	public String sayHello(String username) {

		return "Hello " + username;
	}

	@Override
	public void setUser(String username) {

	}
}

4.4  在Web.xml中声明CXF监听器

<servlet>
 <servlet-name>CXFServlet</servlet-name>
	<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	 <servlet-name>CXFServlet</servlet-name>
	 <url-pattern>/webservice/*</url-pattern>
</servlet-mapping>

注意:<servlet-mapping>下的<url-pattern>指明了服务访问地址的形式,“/*”代表URL地址中,包名称后直接跟服务endpoint地址,若指明<url-pattern>为/webservice/*,则URL为“包名/webservice/endpoing?wsdl”。

4.5  创建WebService声明的Spring配置文件spring-cxf-service.xml

<?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:http-conf = "http://cxf.apache.org/transports/http/configuration"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
		http://cxf.apache.org/jaxws
		http://cxf.apache.org/schemas/jaxws.xsd
		http://cxf.apache.org/transports/http/configuration
        http://cxf.apache.org/schemas/configuration/http-conf.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" />
  
  <bean id="helloServiceBean" class="com.creditease.bsettle.webservice.HelloWorldImpl" />
  <!-- 第一个测试级WebService服务发布 -->
  <jaxws:endpoint id="helloService" implementor="helloServiceBean" address="/helloService"  />
  <!-- 转账相关service(换一种服务发布方式) -->
  <jaxws:server id="CeTransferAccountWS" address="/CeTransferAccountWS"
	xmlns:s="http://impl.ce.handler.transferaccount.payplatform.app.creditease.com/"<span style="font-family: Arial, Helvetica, sans-serif;">    </span>
<span style="font-family: Arial, Helvetica, sans-serif;">             serviceClass="com.creditease.ns.adapter.transfer.CeTransferAccountWS">	</span>
<span style="font-family: Arial, Helvetica, sans-serif;">     <jaxws:serviceBean></span>
	    <bean class="com.creditease.ns.adapter.transfer.impl.CeTransferAccountWSImpl" />
	</jaxws:serviceBean>
    </jaxws:server>
   </beans>

注意:<jaxws:endpoint>定义了一个WebService,implementor是WebService处理类,值为在(6)中定义的bean的id,其具体的实现类在class中指明,address是它的访问路径,就是上面提到的将要在URL中显示的endpoint的名称。

4.6 spring配置文件在web.xml中的位置

由于在web.xml中配置了listener, 所以需要将该配置文件读入的位置提前,不能放在DispatcherServlet的配置文件路径中。问题参照7.2.

<!-- The definition of the Root Spring Container shared by all Servlets
		and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
		  classpath:META-INF/spring-hibernate.xml
		  classpath:META-INF/spring-cxf-service.xml
		</param-value>
	</context-param>

4.6 测试Web Service

访问路径: http://host:port/context_path/services,获取该路径所有的服务列表

读取wsdl文件内容,访问路径: http://host:port/context_path/services/serviceName?wsdl

4.7 基于SoapUI进行接口测试

5.  创建CXF客户端

正常开发两个独立系统之间互操作的服务,需要双方协商好WSDL,然后根据WSDL规范去实现互操作性。在本示例中,我们已经开发完成了服务端程序,下面需要开发客户端程序,为了达到客户端调用服务端的目的,我们需要通过双方协商好的WSDL(这里直接通过访问服务端服务地址得到)来生成Java存根类文件。

CXF发行版提供了一个名为“wsdl2java.bat”的工具,该工具可以通过WSDL为特定的服务创建stub。该工具有如下参数:


-p : 指定其wsdl的命名空间,即要生成代码的包名。

-d : 指定要产生代码所在目录。

-client : 生成客户端测试web service的代码。

-server : 生成服务器启动web service的代码。

-impl : 生成web service的实现代码。

-ant : 生成build.xml文件。

-compile : 生成代码后编译。

-quient : 静默模式,不输出警告与错误信息。

-all : 生成所有开始端点代码:types, service proxy, service interface, server mainline, client mainline, implementation object, and an Ant build.xml file。

一般用到的命令:“wsdl2java –p 生成代码的包名–d 生成代码的路径 wsdl地址”。执行命令生成本示例的stub代码文件:

也可以利用Java自带的方式生成WS客户端文件:

D:\Program Files\Java\jdk1.6.0_26\bin>wsimport -sD:/workspaceNew/shortcutDemo/s

rc/com/creditease/ns/adapter/channel/implhttp://10.100.30.37:8089/ns-adapter-ch

annel/services/CeFinalPaymentWS?wsdl

D:\apache-cxf-2.7.6\bin>wsdl2java.bat -pcom.creditease.ns.adapter.channel.impl

-dD:/workspaceNew\shortcutDemo/src/com/creditease/ns/adapter/channel/impl http:

//10.100.30.37:8089/ns-adapter-channel/services/CeFinalPaymentWS?wsdl

6.  编写客户端测试类,模拟调用服务

第一种实现方式:通过JaxWsProxyFactoryBean代理类来设定服务处理类和服务地址,无须额外的客户端配置。


package com.test.client;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

/**

* 客户端测试服务调用

*

* @author Administrator

*

*/

public
class
MainTestClient {

public
static void
main(String[] args)throws Exception {

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

factory.setServiceClass(IServerService.class);

factory.setAddress("http://localhost:8080/workflow/webservice/sayHello?wsdl");

IServerService client = (IServerService) factory.create();

String response = client.sayHello("Hai,jiangqiao");

System.out.println("Response:" + response);

}

}

注意:此种方式比较方便,无须配置比较灵活,大部分情况下都会采用这种方式调用服务程序。

运行客户端程序,调用成功并能正常反馈,说明客户端与服务端的一次交互成功!

第二种实现方式:通过配置客户端来调用服务,方式比较麻烦需要额外对客户端进行配置,这里只需要了解下即可。


<jaxws:clientid="sayHello2"

 serviceClass="com.test.client.IServerService" address="http://localhost:8080/workflow/webservice/sayHello?wsdl"/>

说明:该方式访问ws服务是利用了Spring的依赖注入法,其中id是Spring IOC容器唯一标识符,在代码中也是通过id获取服务对象的(context.getBean("sayHello2"));serviceClass是WebService服务接口;address是WDSL地址。

按照此种方式额外配置客户端信息之后,客户端代码则写成这样:


public
testWebService() throws
Exception

IServerService client =(IServerService)CrmContexts.getBean("sayHello2");

String response = client.sayHello("Hai,jiangqiao");

System.out.println("Response:" + response);

}

实际上这种方式与第一种方式在过程上是一致的,都是设定服务处理类和WDSL地址的过程,只不过方式不一样。可以根据项目的不同设计而进行选择!

注意,此种方式配置客户端,必须通过HTTP的方式进行访问才能正常调用服务,否则会报Spring找不到相应对象的错误;这种访问方式的好处就是,不需要生成桩文件。

7. .  问题以及解决

7.1 No bean named ‘cxf‘ is defined

错误信息如下:

HTTP Status 500 - Servlet.init() for servlet CXFService threw exception

type Exception report

message Servlet.init() for servlet CXFService threw exception

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Servlet.init() for servlet CXFService threw exception
	org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
	org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
	org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
	org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2441)
	org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2430)
	java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	java.lang.Thread.run(Thread.java:662)
root cause

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cxf' is defined
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:575)
	org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1111)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:276)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
	org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121)
	org.apache.cxf.transport.servlet.CXFServlet.loadBus(CXFServlet.java:80)
	org.apache.cxf.transport.servlet.CXFNonSpringServlet.init(CXFNonSpringServlet.java:76)
	org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
	org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
	org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
	org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2441)
	org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2430)
	java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	java.lang.Thread.run(Thread.java:662)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.53 logs.

原因以及解决办法:

主要的原因是cxf对象实例初始化顺序晚于CXFServlet, 故需要将其spring-cxf-service.xml的初始化顺序从原来的dispatcherServlet, 提前至<context-param>中的初始化参数

7.2   class path resource [META-INF/cxf/cxf-servlet.xml] cannot be opened because it does not exist

完整的错误日志信息如下:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from relative location [spring-cxf-service.xml]
Offending resource: class path resource [META-INF/applicationContext.xml]; nested exception is org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:META-INF/cxf/cxf-servlet.xml]
Offending resource: class path resource [META-INF/spring-cxf-service.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [META-INF/cxf/cxf-servlet.xml]; nested exception is java.io.FileNotFoundException: class path resource [META-INF/cxf/cxf-servlet.xml] cannot be opened because it does not exist
	at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
	at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
	at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:76)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:282)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(DefaultBeanDefinitionDocumentReader.java:207)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:192)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:139)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:108)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:410)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:META-INF/cxf/cxf-servlet.xml]
Offending resource: class path resource [META-INF/spring-cxf-service.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [META-INF/cxf/cxf-servlet.xml]; nested exception is java.io.FileNotFoundException: class path resource [META-INF/cxf/cxf-servlet.xml] cannot be opened because it does not exist
	at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
	at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
	at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:76)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:256)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(DefaultBeanDefinitionDocumentReader.java:207)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:192)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:139)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:108)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:266)
	... 29 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [META-INF/cxf/cxf-servlet.xml]; nested exception is java.io.FileNotFoundException: class path resource [META-INF/cxf/cxf-servlet.xml] cannot be opened because it does not exist
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:250)
	... 38 more
Caused by: java.io.FileNotFoundException: class path resource [META-INF/cxf/cxf-servlet.xml] cannot be opened because it does not exist
	at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:171)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328)
	... 42 more
Jan 21, 2015 11:51:21 AM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
Jan 21, 2015 11:51:21 AM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/bsettle] startup failed due to previous errors
Jan 21, 2015 11:51:21 AM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Jan 21, 2015 11:51:21 AM org.apache.catalina.core.StandardContext listenerStop
SEVERE: Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
	at org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory(AbstractRefreshableApplicationContext.java:171)
	at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1090)
	at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1064)
	at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1010)
	at org.springframework.web.context.ContextLoader.closeWebApplicationContext(ContextLoader.java:586)
	at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:143)
	at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:5014)
	at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5659)
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
Jan 21, 2015 11:51:21 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-7080"]
Jan 21, 2015 11:51:21 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Jan 21, 2015 11:51:21 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 4258 ms

原因以及应对办法:

问题的起源是缺少了jar,关于通信协议和servlet声明的包。引入jar即可,比如在pom.xml中加入如下配置,而非单纯cxf包。

	<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>

8. 总结

CXF在实现上存在诸多的底层实现,jaxws, rs等等诸多的内容,这里只选取jaxws来做为示例,至于其他的诸多实现,笔者也不是非常熟悉,姑且放下不论。好了,经过了漫长的配置和调试之后,相信大家对于如何使用cxf进入开发状态有了一个初步的认识。

目前来说,越来越多的企业和系统已经迁移至基于http请求的json或者xml格式的请求,而非标准的soap/webservice请求,究其原因还是soap/webservice过于复杂、标准虽好,但是用着不多。关键是看是否简单易用,可以快速解决开发中存在的问题,在这个方面json/xml则是非常的简单。

参考资料

1.  WebService定义 http://baike.baidu.com/link?url=mep-1agA29j5jauITgTP9Hn_iI1X6bM6m0N_D83eflzvNlXmXrVrNMJMV7k3nMunD88qDBkXKOhzUa9kMvslkK

2. 官方站点: cxf.apache.org

时间: 2024-08-01 22:43:31

基于Maven在Spring中集成CXF Web Service框架的相关文章

基于maven进行spring 和mybatis的整合(Myeclpise)

学习日记:基于maven进行spring和mybatis的整合,进行分页查询 什么是maven:maven是一个项目管理工具,使用maven可以自动管理java项目的整个生命周期,包括编译.构建.测试.发布和报告等.在大型项目开发中,使用maven来管理是必不可少的. 开发工具myeclipse:myclipse 10.0自带了maven的插件.也可以网上下载maven插件 1.新建一个maven project,点击next,选择maven-archetype-webapp,点击next,填写

Apache CXF实现Web Service(4)——Tomcat容器和Spring实现JAX-RS(RESTful) web service

准备 我们仍然使用 Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service 中的代码作为基础,并引入spring来进行RESTful web service的配置和管理. 项目目录结构如下图 首先我们要在web.xml中加入通过Spring的ContextLoaderListener加载的Spring运行时环境以及CXF的Spring配置文件 web.xml <?xml version="

spring 中集成quartz定时器及quartz中cronExpression配置说明

 spring 中集成quartz: spring文件的配置: <?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:p="http:/

spring中集成使用jedis(2)

本文主要就spring注入的连接池使用问题,做简要说明. 使用过JedisPool的同学会发现,通过JedisPool获取资源,在使用完毕后,需要显式的将资源放回连接池中, 如下: JedisPool jedisPool; Jedis jedis = jedisPool.getResource(); //操作 jedisPool.returnResource(jedis); 如果未显示的回收资源,则在连接池中资源使用完毕后,系统会出现阻塞. 因为如果使用连接池,就相当于将客户端连接托管给池,而池

CXF Web Service的Hello World之一 搭建环境

摘要 本文介绍如何配置 Eclipse + Java EE + Apache CXF + Tomcat + JDK 的开发环境,用于开发CXF Web Service. JDK 版本:1.7.0_71,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html,我下载的安装包文件名:jdk-7u71-windows-x64.exe. 配置环境变量,参见下面的脚本:setx_java_env.bat,注意修改ROO

spring中集成shiro进行安全管理

shiro是一款轻量级的安全框架,提供认证.授权.加密和会话管理四个基础功能,除此之外也提供了很好的系统集成方案. 下面将它集成到之前的demo中,在之前spring中使用aop配置事务这篇所附代码的基础上进行集成 一.添加jar包引用 修改pom.xml文件,加入: <!-- security --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core&

在Spring中集成shiro

1.在pxm添加集成导入 <!-- shiro的支持包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.4.0</version> <type>pom</type> </dependency> <!-- shiro与Spr

spring中集成使用jedis(1)

本文主要说明在项目中通过spring集成jedis的使用方法. 首先,在jedis的连接配置中,出于性能考虑选择连接池形式.jedis中的连接池类为 redis.clients.jedis.JedisPool 其中包含多个构造器,可根据需要自行选取,这里选择较为基础形式: public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, final int port) { this(poolConfig,

Spring中集成Shiro授权实例

授权流程回顾 首先说一句,使用授权的前提当然是先要实现身份验证,也就是要保证用户登录之后才可能考虑授权的问题.关于身份验证之前已经写过了,还不清楚的童鞋可以点这里 上一篇文章介绍了Shiro中授权的一些基础知识和原理.学了就要用,本篇文章就介绍如何在项目中应用Shiro的授权.这里为了方便大家阅读,先贴出上一篇文章中分析出的授权流程: 当我们调用Subject.hasRole(...)后 首先会委托给securityManager来处理,而securityManager内部有一个Authoriz