通常在Spring發(fā)布Hession,RMI等,是非常方便的,
但是要發(fā)布SOAP類型的WebService則要依賴一個(gè)獨(dú)立的Servlet容器(如Tomcat+Axis),
這種Webservice一般還有別的配置文件,比如web.xml,wsdd文件等等
。有時(shí)侯,你可能想一臺(tái)機(jī)器上只部署一個(gè)Http Soap Service
,這種場(chǎng)合你可能不希望安裝一個(gè)類似Tomcat的容器,
你更希望發(fā)布的時(shí)候就是一個(gè)服務(wù)程序,該程序啟動(dòng)則提供WebService.這篇文章描述一種解決方案。
開發(fā)環(huán)境:
Spring 1.2.6
XFire 1.0
Jetty 4.2.1
方案描述:我們可以通過XFire的編程接口來創(chuàng)建WebService并嵌入一個(gè)HttpServer,
從而來做到在一個(gè)獨(dú)立應(yīng)用程序中發(fā)布Http Service
1
// Create an XFire Service
2
ObjectServiceFactory serviceFactory = new ObjectServiceFactory();
3
Service service = serviceFactory.create(Echo.class);
4
service.setInvoker(new BeanInvoker(new EchoImpl()));
5
// Register the service in the ServiceRegistry
6
XFire xfire = XFireFactory.newInstance().getXFire();
7
xfire.getServiceRegistry().register(service);
8
// Start the HTTP server
9
XFireHttpServer server = new XFireHttpServer();
10
server.setPort(8191);
11
server.start();
這樣的話,如果發(fā)布多個(gè)WebSerice則要依次顯式的創(chuàng)建 XFire Service,然后再一一注冊(cè),
這樣顯然是不夠優(yōu)雅的。
我們想要讓開發(fā)者在Spring配置文件中指定要發(fā)布為WebService的POJOs,
然后載入Spring環(huán)境就自動(dòng)發(fā)布為webservice,而不需要跟 XFire API打交道。
首先,我們想要一個(gè)BeanFacory,能把一個(gè)pojo裝配成XFire Service
1 /**
2 *
3 */
4 package com.yovn.ws.xfire.example;
5
6 import org.codehaus.xfire.service.Service;
7 import org.codehaus.xfire.service.binding.BeanInvoker;
8 import org.codehaus.xfire.service.binding.ObjectServiceFactory;
9 import org.springframework.beans.factory.FactoryBean;
10
11 /**
12 * @author new
13 *
14 */
15 public class XFireServiceFactoryBean implements FactoryBean
16 {
17
18
19
20
21 private Class serviceClass;
22
23
24 private Object target;
25
26
27 private Service service;
28
29
30 private final ObjectServiceFactory sf=new ObjectServiceFactory();
31
32 /**
33 *
34 */
35 public XFireServiceFactoryBean()
36 {
37
38 }
39
40 /* (non-Javadoc)
41 * @see org.springframework.beans.factory.FactoryBean#getObject()
42 */
43 public Object getObject() throws Exception
44 {
45 if(service==null)
46 {
47 service=sf.create(serviceClass);
48 service.setInvoker(new BeanInvoker(target));
49 }
50 return service;
51 }
52
53 /* (non-Javadoc)
54 * @see org.springframework.beans.factory.FactoryBean#getObjectType()
55 */
56 public Class getObjectType()
57 {
58
59 return Service.class;
60 }
61
62 /* (non-Javadoc)
63 * @see org.springframework.beans.factory.FactoryBean#isSingleton()
64 */
65 public boolean isSingleton()
66 {
67 return true;
68 }
69
70 public void setServiceClass(Class serviceClass)
71 {
72 this.serviceClass = serviceClass;
73 }
74
75 public void setTarget(Object target)
76 {
77 this.target = target;
78 }
79
80 }
81
這樣我們可以通過Spring來裝配一個(gè)pojo,
下一步我們要在Spring容器載入時(shí)候注冊(cè)XFire Service,
并啟動(dòng)一個(gè)嵌入的Http Server,我們可以借助Spring的ApplicationListener來實(shí)現(xiàn)
1 /**
2 *
3 */
4 package com.yovn.ws.xfire.example;
5
6
7 import org.apache.commons.logging.Log;
8 import org.apache.commons.logging.LogFactory;
9 import org.codehaus.xfire.XFire;
10 import org.codehaus.xfire.XFireFactory;
11 import org.codehaus.xfire.server.http.XFireHttpServer;
12 import org.codehaus.xfire.service.Service;
13 import org.codehaus.xfire.service.ServiceRegistry;
14 import org.springframework.context.ApplicationContext;
15 import org.springframework.context.ApplicationEvent;
16 import org.springframework.context.ApplicationListener;
17 import org.springframework.context.event.ContextClosedEvent;
18 import org.springframework.context.event.ContextRefreshedEvent;
19
20 /**
21 * @author new
22 *
23 */
24 public class XFireServiceStarter implements ApplicationListener
25 {
26
27 private int port = 80;
28
29 private XFireHttpServer server;
30 private final Log logger=LogFactory.getLog(getClass().getName());
31
32 public void setPort(int port)
33 {
34 this.port = port;
35 }
36
37 public void onApplicationEvent(ApplicationEvent event)
38 {
39 try
40 {
41 if (event instanceof ContextRefreshedEvent)
42 {
43
44 if (server != null)
45 {
46
47 server.stop();
48 logger.info("xfire server stopped
");
49
50 }
51 registerService((ApplicationContext)event.getSource());
52 server = new XFireHttpServer();
53 server.setPort(port);
54 server.start();
55 logger.info("xfire server started
");
56
57 } else if (event instanceof ContextClosedEvent)
58 {
59 if(server!=null)
60 {
61 server.stop();
62 logger.info("xfire server stopped
");
63 }
64
65 }
66
67 } catch (Exception e)
68 {
69 logger.error("process event "+event+" error",e);
70 }
71
72 }
73
74 private void registerService(ApplicationContext context)
75 {
76 XFire xfire=XFireFactory.newInstance().getXFire();
77 ServiceRegistry registry=xfire.getServiceRegistry();
78 String names[]=context.getBeanNamesForType(Service.class);
79
80 for(int i=0;i<names.length;i++)
81 {
82 Service service=(Service)context.getBean(names[i]);
83 registry.register(service);
84 logger.info("register service:"+service.getName());
85 }
86
87 }
88
89 }
90
Ok,我們完成基礎(chǔ)的代碼,下面試著發(fā)布一個(gè)簡(jiǎn)單的WebServie
1 package com.yovn.ws.xfire.example;
2
3 public interface Add
4 {
5 int add(int a,int b);
6
7 }
該接口的實(shí)現(xiàn)如下
1 package com.yovn.ws.xfire.example;
2
3 public class AddImpl implements Add
4 {
5
6 public int add(int a, int b)
7 {
8
9 return a+b;
10 }
11
12 }
這是一個(gè)簡(jiǎn)單功能的POJO,下面我們?cè)赟pring中裝配起來
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd">
3 <beans>
4 <bean id="addService" class="com.yovn.ws.xfire.example.XFireServiceFactoryBean">
5 <property name="serviceClass" value="com.yovn.ws.xfire.example.Add"/>
6 <property name="target" ref="adder"/>
7 </bean>
8
9 <bean id="adder" class="com.yovn.ws.xfire.example.AddImpl"/>
10 <bean id="xfireStarter" class="com.yovn.ws.xfire.example.XFireServiceStarter">
11 <property name="port" value="80"/>
12 </bean>
13 </beans>
好了,我們完成了,只要載入這個(gè)xml初始化一個(gè)Spring ApplicationContext,一個(gè)名叫Add的webservice就發(fā)布了。你可以通過訪問
http://localhost/Add?wsdl來獲得webservice的詳細(xì)描述!