Spring结合JSF使用时的组件命名支持

本文探讨了Seam和Spring在组件命名空间解析上的差异,并通过实现一个自定义ELResolver来解决Spring环境下组件命名空间解析的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前和打倒小日本做项目的时候,用seam,曾经定过一条规则,Service/Manager/DAO这个层面上由于组件数量不是特别多,所以组件命名不需要空间前缀,但是对于action层面的组件,由于可能很多,所以按功能模块划分命名空间,例如:

@Compoenent("treasure.selector"),@Component("store.main")等等,在Seam的支持下,在页面上写表达式语言的时候,没有任何问题,例如#{store.main.entity.name}

后来在某环境下,不用seam,用Spring了,发现如下的代码会有问题:

@Component("auth.main")//Spring的Annotation
public class MainAction{........}

在页面上用#{auth.main.xx}这样的表达式的时候,会出现找不到对象的错误。跟代码发现Spring提供的SpringBeanFacesELResolver里面解析的时候,先解析"auth",找不到,于是后面就解析不下去了。

问题的关键点在于这个EL解析器。Seam的ELResolver能够正确解析带命名空间的组件,而Spring的这个不行。

于是,扩展之。

首先第一步是要让系统知道有哪些命名空间,这里用了Spring的一个接口,叫做BeanFactoryPostProcesser,看名字应该能看的出来,和我们常用的BeanPostProcess道理一样,只不过实现了BeanFactoryPostProcesser接口的组件会在整个beanFactory初始化之前和之后调用。

看代码:


@Component
public class BeanNamespacePostProcesser implements BeanFactoryPostProcessor {

@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for(String beanName : beanNames){
if(beanName.indexOf('.') == -1)
continue;
else{
String[] terms = beanName.split("\\.");
Namespace space = Namespace.rootNamespace;
for(int i = 0;i<terms.length - 1; i++){
space = space.getOrCreateChild(terms[i]);
}
}
}
}

}



这样,在系统启动的时候分析所有的bean的名字,把命名空间记录下来。

然后,创建一个ELResolver,让他能够解析命名空间:

public class JSFELResolver extends SpringBeanFacesELResolver {

@Override
public Object getValue(ELContext elContext, Object base, Object property) throws ELException {
if (base == null) {
return resolveBase(elContext, property);
} else if (base instanceof Namespace) {
return resolveInNamespace(elContext, (Namespace) base, property);
}else {
return null;
}
}

private Object resolveInNamespace(ELContext elContext, Namespace base,
Object property) {
Object result = base.get((String) property);
elContext.setPropertyResolved(true);
return result;
}

private Object resolveBase(ELContext elContext, Object property) {
if(this.getWebApplicationContext(elContext).containsBean(property.toString())){
elContext.setPropertyResolved(true);
return this.getWebApplicationContext(elContext).getBean(property.toString());
}else{
Object result = Namespace.rootNamespace.get(property.toString());
if(result != null)
elContext.setPropertyResolved(true);

return result;
}
}
}



在JSF的配置文件中启用这个ELResolver:

<el-resolver>el.JSFELResolver</el-resolver>

这样,就可以在页面上用表达式引用带命名空间的组件了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值