我有一个复合组件来动态调用 bean 动作:
<composite:interface>
<composite:attribute name="actionMethod" method-signature="java.lang.String action()"/>
</composite:interface>
<composite:implementation>
<p:menubar autoDisplay="false" styleClass="subMenu">
<p:menuitem>
<h:commandButton action="#{cc.attrs.actionMethod}" value="#{bundle.CreateSaveLink}" styleClass="smallButton button buttonSave"/>
</p:menuitem>
</p:menubar>
</composite:implementation>
而且我还定义了一个 ActionListener 类来实现安全性:
public class SecurityActionListener extends ActionListenerImpl implements ActionListener {
private static final Logger log = Logger.getLogger(SecurityActionListener.class);
private String isCasEnabled;
public SecurityActionListener() {
isCasEnabled = PropertyUtility.isCasEnabled();
}
@SuppressWarnings("unused")
@Override
public void processAction(final ActionEvent event) {
if(!isCasEnabled.equals("true")) {
super.processAction(event);
return;
}
final FacesContext context = FacesContext.getCurrentInstance();
final Application application = context.getApplication();
final ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) application.getNavigationHandler();
// Action stuff
final UIComponent source = event.getComponent();
final ActionSource actionSource = (ActionSource) source;
MethodBinding binding;
binding = actionSource.getAction();
final String expr = binding.getExpressionString();
if (!expr.startsWith("#")) {
super.processAction(event);
return;
}
final int idx = expr.indexOf('.');
if (idx <0) {
log.error("Errore nella formattazione della chiamata al metodo: " + expr + ". No '.' found");
return;
}
final String target = expr.substring(0, idx).substring(2);
final String t = expr.substring(idx + 1);
String method = t.substring(0, (t.length() - 1));
final int idxParams = method.indexOf('(');
if (idxParams >=0) {
method = method.substring(0,idxParams);
}
final MethodExpression expression = new MethodExpressionMethodBindingAdapter(binding);
final ELContext elContext = context.getELContext();
final ExpressionFactory factory = context.getApplication().getExpressionFactory();
final ValueExpression ve = factory.createValueExpression(elContext, "#{" + target + '}', Object.class);
final Object result = ve.getValue(elContext);
// Check if the target method is a secured method
// and check security accordingly
final Method[] methods = result.getClass().getMethods();
for (final Method meth : methods) {
if (meth.getName().equals(method)) {
if (meth.isAnnotationPresent(CustomSecurity.class)) {
final CustomSecurity securityAnnotation = meth.getAnnotation(CustomSecurity.class);
log.debug("Function to check security on: " + securityAnnotation.value());
SecurityUtility.checkSecurity(securityAnnotation.value());
} else {
super.processAction(event);
}
break;
}
}
log.warn("No method: " + method + " found in: " + methods + ", for object: " + result);
}
}
如果 commandButton 上的操作以标准方式定义:
<h:commandButton action="#{bean.action}" value="test" />
一切正常,我能够通过其 ActionEvent 在侦听器中检测 bean 和动作,但是使用复合组件和此代码我没有关于实际动作参数的信息
如果我使用大括号表示法,我也会遇到同样的问题:#{beanName['action']}。在这种情况下,在调试模式下,我可以看到对象 TagMethodExpression 与 MethodExpressionImpl 和 VariableMapperImpl 绑定,其中有映射 beanName -> "real_bean_name"
如果 ActionEvent 是由复合组件或大括号表示法生成的,有没有办法通过 ActionEvent 获取 bean 和 action?
谢谢!