webservice http://kyfxbl.iteye.com/category/213780
评:
上次总结了spring集成cxf的方法,不过有些地方说得不清楚:http://kyfxbl.iteye.com/category/213780

上次把web service客户端接口,用注解注入到别的bean里,结果报错了。当时一直没有找到原因,现在回想,有可能是当时代码环境的问题,spring和cxf的配置都有些混乱

最近在搭建一个培训的框架,开发环境很纯净,上次那个问题没有再发生了。因此也简化了一下,重新总结一下。不过由于上次那个问题,最终也没找到原因,所以不敢保证这次也一定是正确的,只能说,在以下环境是OK的:

tomcat7.0.29
spring-framework-3.1.0
cxf-2.6.1
neethi-3.0.2
wsdl4j-1.6.2
xmlschema-core-2.0.2

本文介绍的是从代码到wsdl文件的写法,如果是从wsdl到代码,可以看另一篇博客:http://kyfxbl.iteye.com/blog/1481330

首先是web.xml
Xml代码 收藏代码

<?xml version="1.0" encoding="UTF-8"?> 


 <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"> 


 <display-name>DevelopFramework</display-name> 


 <context-param> 

 <param-name>contextConfigLocation</param-name> 

 <param-value>WEB-INF/beans.xml</param-value> 

 </context-param> 


 <listener> 

 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 

 </listener> 


 <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> 


 </web-app>




这里因为没有集成spring-mvc,所以web.xml就很简单

然后是spring的配置文件
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:context="http://www.springframework.org/schema/context" 

 xmlns:jaxws="http://cxf.apache.org/jaxws" 

 xsi:schemaLocation="http://www.springframework.org/schema/beans 

 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
 http://www.springframework.org/schema/context 

 http://www.springframework.org/schema/context/spring-context-3.1.xsd 

 http://cxf.apache.org/jaxws 

 http://cxf.apache.org/schemas/jaxws.xsd"> 


 <import resource="classpath:META-INF/cxf/cxf.xml" /> 


 <context:component-scan base-package="com.huawei.inoc.framework" /> 


 <jaxws:endpoint id="helloWorld" implementor="#helloWorldWebserviceImpl" address="/HelloWorld" /> 


 <jaxws:client id="client" 

 serviceClass="com.huawei.inoc.dummy.webservice.IDemoSupport" 

 address="http://localhost:8080/Dummy/webservice/getDate" /> 


 </beans>




这里是简化后的配置,仅包含必要的配置信息

这里分别配置了一个web service的客户端,和一个web service的服务端

这里要注意的是,jaxws:endpoint里的implementor,不能直接写xxx.xxx.ClassName,因为这里的实现类,自身也是一个bean,如果直接写的话,里面的依赖关系就没有了,要用#beanName的语法

jaxws:client里的serviceClass,写的是接口的完整类名,address是目标endpoint的地址

接下来是要发布的webservice接口代码
Java代码 收藏代码

@WebService 

 public interface HelloWorldWebservice { 


 String sayHello(String name); 


 }




就是一个普通的接口声明,只是要加上@WebService注解

最后是webservice实现类代码
Java代码 收藏代码

@Controller 

 public class HelloWorldWebserviceImpl implements HelloWorldWebservice { 


 @Autowired 

 private ITestService service; 


 @Autowired 

 private IDemoSupport support; 


 @Override 

 public String sayHello(String name) { 

 service.doSomething(); 

 System.out.println(support.getDate()); 

 return "hello " + name; 

 } 


 }




实现类更加简单,只需要继承刚才声明的接口就可以了,不需要额外的注解

这里用到了@Controller和@Autowired注解,只是为了演示把实现类自身声明为spring bean,并把下层的业务bean,和webservice client的bean注入进来

启动tomcat后,webservice就发布成功了,并且ITestService和IDemoSupport都是注入成功的

[点击查看原始大小图片]

用soapui调用一下,控制台打出如下信息:
doSomething()
Wed Aug 15 17:12:50 CST 2012

说明此时业务bean和client bean都是注入成功的。上次死活就不行,估计确实是代码环境的原因,现在也没法还原现场了,成为悬案

另外写了一个Servlet,看看当前的ApplicationContext里究竟注册了哪些bean
Java代码 收藏代码

protected void doGet(HttpServletRequest request, 

 HttpServletResponse response) throws ServletException, IOException { 


 ApplicationContext context = WebApplicationContextUtils 

 .getWebApplicationContext(request.getServletContext()); 


 String[] beanNames = context.getBeanDefinitionNames(); 


 for (String beanName : beanNames) { 

 System.out.println(beanName); 

 } 


 }



执行之后,控制台打出bean信息:

cxf 

org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor 

org.apache.cxf.bus.spring.Jsr250BeanPostProcessor 

org.apache.cxf.bus.spring.BusExtensionPostProcessor 

testService 

helloWorldWebserviceImpl 

org.springframework.context.annotation.internalConfigurationAnnotationProcessor 

org.springframework.context.annotation.internalAutowiredAnnotationProcessor 

org.springframework.context.annotation.internalRequiredAnnotationProcessor 

org.springframework.context.annotation.internalCommonAnnotationProcessor 

org.springframework.context.annotation.internalPersistenceAnnotationProcessor 

propertyConfigurer 

dataSource 

sessionFactory 

helloWorld 

client.proxyFactory 

client 

org.springframework.conte

xt.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0

前4个都是cxf.xml里注册的

testService是业务bean

helloWorldWebserviceImpl是webservice实现类的bean,注意这个只是一个普通的spring bean,还没有被发布为web service,下面的helloWorld才是

helloWorld,就是<jaxws:endpoint>那行生成的bean,实际的web service

client,是<jaxws:client>那行生成的bean。这个类是cxf生成的代理类,但是实现了web service服务端接口。代码不可见,但是可以像普通的spring bean一样注入到别的bean里
Java代码 收藏代码

Object clientProxyFactory = context.getBean("client"); 

 System.out 

 .println("client: " + clientProxyFactory.getClass().getName()); 

 System.out.println(clientProxyFactory instanceof IDemoSupport);




执行以后,输出是:
client: $Proxy42
true
如果跟进去调试,可以看得更清楚一点:


client.proxyFactory应该是cxf生成的一个内部bean,bean definition是abstract的,如果尝试用getBean()方法获取,会抛出异常
Java代码 收藏代码

Object clientProxyFactory = context.getBean("client.proxyFactory"); 



org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name 'client.proxyFactory': Bean definition is abstract

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring