(感覺BlogJava很有人氣,就把原來寫在msn space上的也轉過來)
通常在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
?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();
這樣的話,如果發布多個WebSerice則要依次顯式的創建 XFire Service,然后再一一注冊,
這樣顯然是不夠優雅的。
我們想要讓開發者在Spring配置文件中指定要發布為WebService的POJOs,
然后載入Spring環境就自動發布為webservice,而不需要跟 XFire API打交道。
首先,我們想要一個BeanFacory,能把一個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來裝配一個pojo,
下一步我們要在Spring容器載入時候注冊XFire Service,
并啟動一個嵌入的Http Server,我們可以借助Spring的ApplicationListener來實現
?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,我們完成基礎的代碼,下面試著發布一個簡單的WebServie
1?package?com.yovn.ws.xfire.example;
2?
3?public?interface?Add
4?{
5?????int?add(int?a,int?b);
6?
7?}
該接口的實現如下
?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?}
這是一個簡單功能的POJO,下面我們在Spring中裝配起來
?1?<?xml?version="1.0"?encoding="UTF-8"?>
?2?<!DOCTYPE?beans?PUBLIC?"-//SPRING//DTD?BEAN//EN"?"http://www.springframework.org/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>
好了,我們完成了,只要載入這個xml初始化一個Spring ApplicationContext,一個名叫Add的webservice就發布了。你可以通過訪問
http://localhost/Add?wsdl來獲得webservice的詳細描述!