`
kv0002
  • 浏览: 8505 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

用Annotation方式发布Flex-Bds服务

阅读更多
引用
Spring最近(08-12-16)发布了支持BDS的类库:spring-flex-1.0.0.M1.jar,但还是没有提供Annotation发布方式,于是趁周末无聊的时间,让它简化到底吧(至少在官方的Anno没有发布出来之前)。

这是Spring提供的BDS服务导出配置:
<!-- Bootstraps and exposes the BlazeDS MessageBroker -->  
<bean id="mySpringManagedMessageBroker"  
class="org.springframework.flex.messaging.MessageBrokerFactoryBean" />

<!-- Implementation of ProductService using Spring's SimpleJdbcTemplate -->  
<bean id="productService" class="flex.samples.product.JdbcProductService" >  
    <constructor-arg ref="dataSource"/>  
</bean>  
  
<!-- Expose the productService bean for BlazeDS remoting -->  
<bean id="product"  
    class="org.springframework.flex.messaging.remoting.FlexRemotingServiceExporter">  
    <property name="messageBroker" ref="mySpringManagedMessageBroker"/>  
    <property name="service" ref="productService"/>  
</bean> 

注册请求服务
<!-- Maps request paths at /messagebroker to the BlazeDS MessageBroker -->  
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
    <property name="mappings">  
        <value>  
            /messagebroker/*=mySpringManagedMessageBroker   
        </value>  
    </property>  
</bean>  
  
<!-- Dispatches requests mapped to a MessageBroker -->  
<bean class="org.springframework.flex.messaging.servlet.MessageBrokerHandlerAdapter"/>

服务导出的重点就在FlexRemotingServiceExporter,更具它的原理,重构一个ProxyExporter
public class FlexRemotingServiceProxyExporter implements InitializingBean, ResourceLoaderAware {
	private static final Logger logger = Logger.getLogger(FlexRemotingServiceProxyExporter.class);

	/**
	 * Flex 消息发布器
	 */
	private MessageBroker messageBroker;

	/**
	 * BdsService集合
	 */
	private Map<String, Object> bdsServiceMap = new HashMap<String, Object>();

	private List<RemotingDestination> rdList = new ArrayList<RemotingDestination>();

	public void setMessageBroker(MessageBroker messageBroker) {
		this.messageBroker = messageBroker;
	}

	public void afterPropertiesSet() throws Exception {
		Assert.notNull(messageBroker, "The 'messageBroker' property is required.");

		RemotingService remotingService = (RemotingService) messageBroker
				.getServiceByType(RemotingService.class.getName());
		Assert.notNull(remotingService, "Could not find a proper RemotingService in the Flex MessageBroker.");

		for (String serviceId : bdsServiceMap.keySet()) {
			RemotingDestination destination = (RemotingDestination) remotingService
					.createDestination(serviceId);
			rdList.add(destination);

			FlexFactory factory = new FlexFactoryInstance(bdsServiceMap.get(serviceId));

			destination.setFactory(factory);
			destination.start();

			Assert.isInstanceOf(JavaAdapter.class, destination.getAdapter(),
					"Spring beans exported as a RemotingDestination require a JavaAdapter.");
		}
	}

	public void setResourceLoader(ResourceLoader resourceLoader) {
		if (resourceLoader instanceof XmlWebApplicationContext) {
			XmlWebApplicationContext context = (XmlWebApplicationContext) resourceLoader;
			String[] names = context.getParent().getBeanDefinitionNames();

			for (String name : names) {

				Object bean = context.getParent().getBean(name);
				BdsService bdsService = bean.getClass().getAnnotation(BdsService.class);
				if (bdsService == null) {
					continue;
				}

				bdsServiceMap.put(bdsService.serviceName(), bean);

				logger.info("Export bdsService: " + bdsService.serviceName());
			}
		}
	}

}


FlexFactoryInstance:
public class FlexFactoryInstance implements FlexFactory {
	private Object bean;

	public FlexFactoryInstance(Object bean) {
		this.bean = bean;
	}

	public FactoryInstance createFactoryInstance(String id, ConfigMap properties) {
		return new ServiceFactoryInstance(this, id, properties);
	}

	public Object lookup(FactoryInstance instanceInfo) {
		throw new UnsupportedOperationException("FlexFactory.lookup");
	}

	public void initialize(String id, ConfigMap configMap) {
		// No-op			
	}

	public final class ServiceFactoryInstance extends FactoryInstance {
		public ServiceFactoryInstance(FlexFactory factory, String id, ConfigMap properties) {
			super(factory, id, properties);
		}

		@Override
		public Object lookup() {
			return bean;
		}
	}
}


BdsService
@Target(TYPE)
@Retention(RUNTIME)
public @interface BdsService {
	/**
	 * 服务名称
	 * @return
	 */
	String serviceName() default "";
}

大功告成,下面是使用SAMPLE
创建bdsServiceContext.xml,在WEB.XML中定义(注意,该xml只能在WEB.XML中引入,如果跟其他的webController配置放置在一起,在SPRING加载时,因为有限读取Adapter的原则,其他的controller配置——包括Hessian的服务导出都会失效):

web.xml
<servlet>
		<servlet-name>flexDispatcherServlert</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				classpath:nbf/config/spring/flexContext.xml
			</param-value>
		</init-param>
		<load-on-startup>2</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>flexDispatcherServlert</servlet-name>
		<url-pattern>/messagebroker/*</url-pattern>
	</servlet-mapping>

bdsServiceContext.xml
<!--去掉之前的FlexRemotingServiceExporter,替换成下面的Exporter-->
<!--FlexRemotingServiceProxyExporter会自动扫描标注了BdsService的BEAN,并将其注册为BDS服务-->
<bean id="flexServiceExporter"
		class="steel.web.flex.FlexRemotingServiceProxyExporter">
		<property name="messageBroker"
			ref="mySpringManagedMessageBroker" />
	</bean>


(附件中提供Eclipse/Flex项目源代码)
分享到:
评论
2 楼 找不到服务器 2009-03-11  
能不能剖析一下原理???
1 楼 roger_588 2009-03-10  
好!目前正在研究这个东西。

相关推荐

Global site tag (gtag.js) - Google Analytics