通常在Spring发布Hession,RMI等,是非常方便的,但是要发布SOAP类型的WebService则要依赖一个独立的Servlet容器(如Tomcat+Axis),这种Webservice一般还有别的配置文件,比如web.xml,wsdd文件等等。有时侯,你可能想一台机器上只部署一个Http Soap Service,这种场合你可能不希望安装一个类似Tomcat的容器,你更希望发布的时候就是一个服务程序,该程序启动则提供WebService.这篇文章描述一种解决方案。 开发环境: Spring 1.2.6 XFire 1.0 Jetty 4.2.1 方案描述:我们可以通过XFire的编程接口来创建WebService并嵌入一个HttpServer,从而来做到在一个独立应用程序中发布Http Service
// Create an XFire Service ObjectServiceFactory serviceFactory = new ObjectServiceFactory(); Service service = serviceFactory.create(Echo.class); service.setInvoker(new BeanInvoker(new EchoImpl())); // Register the service in the ServiceRegistry XFire xfire = XFireFactory.newInstance().getXFire(); xfire.getServiceRegistry().register(service); // Start the HTTP server XFireHttpServer server = new XFireHttpServer(); server.setPort(8191); server.start();这样的话,如果发布多个WebSerice则要依次显式的创建 XFire Service,然后再一一注册,这样显然是不够优雅的。 我们想要让开发者在Spring配置文件中指定要发布为WebService的POJOs,然后载入Spring环境就自动发布为webservice,而不需要跟 XFire API打交道。 首先,我们想要一个BeanFacory,能把一个pojo装配成XFire Service
/** * */ package com.yovn.ws.xfire.example; import org.codehaus.xfire.service.Service; import org.codehaus.xfire.service.binding.BeanInvoker; import org.codehaus.xfire.service.binding.ObjectServiceFactory; import org.springframework.beans.factory.FactoryBean; /** * @author yovn * */ public class XFireServiceFactoryBean implements FactoryBean { private Class serviceClass; private Object target; private Service service; private final ObjectServiceFactory sf=new ObjectServiceFactory(); /** * */ public XFireServiceFactoryBean() { } /* (non-Javadoc) * @see org.springframework.beans.factory.FactoryBean#getObject() */ public Object getObject() throws Exception { if(service==null) { service=sf.create(serviceClass); service.setInvoker(new BeanInvoker(target)); } return service; } /* (non-Javadoc) * @see org.springframework.beans.factory.FactoryBean#getObjectType() */ public Class getObjectType() { return Service.class; } /* (non-Javadoc) * @see org.springframework.beans.factory.FactoryBean#isSingleton() */ public boolean isSingleton() { return true; } public void setServiceClass(Class serviceClass) { this.serviceClass = serviceClass; } public void setTarget(Object target) { this.target = target; } }这样我们可以通过Spring来装配一个pojo,下一步我们要在Spring容器载入时候注册XFire Service,并启动一个嵌入的Http Server,我们可以借助Spring的ApplicationListener来实现
/** * */ package com.yovn.ws.xfire.example; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.xfire.XFire; import org.codehaus.xfire.XFireFactory; import org.codehaus.xfire.server.http.XFireHttpServer; import org.codehaus.xfire.service.Service; import org.codehaus.xfire.service.ServiceRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; /** * @author yovn * */ public class XFireServiceStarter implements ApplicationListener { private int port = 80; private XFireHttpServer server; private final Log logger=LogFactory.getLog(getClass().getName()); public void setPort(int port) { this.port = port; } public void onApplicationEvent(ApplicationEvent event) { try { if (event instanceof ContextRefreshedEvent) { if (server != null) { server.stop(); logger.info("xfire server stopped..."); } registerService((ApplicationContext)event.getSource()); server = new XFireHttpServer(); server.setPort(port); server.start(); logger.info("xfire server started..."); } else if (event instanceof ContextClosedEvent) { if(server!=null) { server.stop(); logger.info("xfire server stopped..."); } } } catch (Exception e) { logger.error("process event "+event+" error",e); } } private void registerService(ApplicationContext context) { XFire xfire=XFireFactory.newInstance().getXFire(); ServiceRegistry registry=xfire.getServiceRegistry(); String names[]=context.getBeanNamesForType(Service.class); for(int i=0;i; registry.register(service); logger.info("register service:"+service.getName()); } } }Ok,我们完成基础的代码,下面试着发布一个简单的WebServie
package com.yovn.ws.xfire.example; public interface Add { int add(int a,int b); }该接口的实现如下
package com.yovn.ws.xfire.example; public class AddImpl implements Add { public int add(int a, int b) { return a+b; } }这是一个简单功能的POJO,下面我们在Spring中装配起来
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="addService" class="com.yovn.ws.xfire.example.XFireServiceFactoryBean"> <property name="serviceClass" value="com.yovn.ws.xfire.example.Add"/> <property name="target" ref="adder"/> </bean> <bean id="adder" class="com.yovn.ws.xfire.example.AddImpl"/> <bean id="xfireStarter" class="com.yovn.ws.xfire.example.XFireServiceStarter"> <property name="port" value="80"/> </bean> </beans>好了,我们完成了,只要载入这个xml初始化一个Spring ApplicationContext,一个名叫Add的webservice就发布了。你可以通过访问http://localhost/Add?wsdl来获得webservice的详细描述!