(感覺(jué)BlogJava很有人氣,就把原來(lái)寫(xiě)在msn space上的也轉(zhuǎn)過(guò)來(lái))
通常在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.這篇文章描述一種解決方案。
開(kāi)發(fā)環(huán)境:
Spring 1.2.6
XFire 1.0
Jetty 4.2.1
方案描述:我們可以通過(guò)XFire的編程接口來(lái)創(chuàng)建WebService并嵌入一個(gè)HttpServer,
從而來(lái)做到在一個(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)雅的。
我們想要讓開(kāi)發(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?
這樣我們可以通過(guò)Spring來(lái)裝配一個(gè)pojo,
下一步我們要在Spring容器載入時(shí)候注冊(cè)XFire Service,
并啟動(dòng)一個(gè)嵌入的Http Server,我們可以借助Spring的ApplicationListener來(lái)實(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中裝配起來(lái)
?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>
好了,我們完成了,只要載入這個(gè)xml初始化一個(gè)Spring ApplicationContext,一個(gè)名叫Add的webservice就發(fā)布了。你可以通過(guò)訪問(wèn)
http://localhost/Add?wsdl來(lái)獲得webservice的詳細(xì)描述!