Jsf 是否可以通过编程方式调用方法签名中定义的方法?

Jsf 是否可以通过编程方式调用方法签名中定义的方法?,jsf,jsf-2,primefaces,composite-component,Jsf,Jsf 2,Primefaces,Composite Component,假设我有一个复合组件 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:composite="http://java.sun.com/jsf/composite

假设我有一个复合组件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:composite="http://java.sun.com/jsf/composite"
  `enter code here`    xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">

<h:head></h:head>
<h:body>
    <composite:interface componentType="editableLabel">
        <composite:attribute name="value" required="true" type="java.lang.String"/>
        <composite:attribute name="oldValue" type="java.lang.String"/>
        <composite:attribute name="editMode" required="false" default="#{false}" type="java.lang.Boolean"/>
        <composite:attribute name="updateListener" required="false" method-signature="void actionListener()"/>
        <composite:attribute name="cancelListener" required="false" method-signature="void actionListener()"/>
    </composite:interface>
    <composite:implementation>
        <h:panelGroup id="editableLabelComponent">
            <h:panelGroup rendered="#{cc.attrs.editMode}">
                <p:inputText value="#{cc.attrs.value}"/>

                <p:commandButton value="Update" actionListener="#{cc.update}" update="editableLabelComponent"/>

                <p:commandButton value="Cancel" actionListener="#{cc.cancel}" update="editableLabelComponent"/>
            </h:panelGroup>

            <p:commandLink>
                <p:outputLabel id="display" value="#{cc.attrs.value}" rendered="#{!cc.attrs.editMode}"/>
                <p:ajax event="click" listener="#{cc.toggleEditMode}" update="editableLabelComponent"/>
            </p:commandLink>
        </h:panelGroup>
    </composite:implementation>
</h:body>

</html>

使用Faces组件

import org.apache.commons.lang3.StringUtils;

import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import java.io.Serializable;

/**
 * Created by labraham on 1/14/16.
 */
@FacesComponent(value = "editableLabel")
public class EditableLabel extends UIComponentBase implements Serializable, NamingContainer {
  private static final long serialVersionUID = 108467781935083432L;

  public static final String VALUE_ATTRIBUTE = "#{cc.attrs.value}";
  public static final String OLD_VALUE_ATTRIBUTE = "#{cc.attrs.oldValue}";
  public static final String EDIT_MODE_ATTRIBUTE = "#{cc.attrs.editMode}";

  private FacesContext context;
  private ELContext elContext;

  @Override
  public String getFamily() {
    return UINamingContainer.COMPONENT_FAMILY;
  }

  /**
   *
   */
  public void update() {

    ValueExpression oldValue = getAttr(OLD_VALUE_ATTRIBUTE, String.class);

    String value = (String) getAttr(VALUE_ATTRIBUTE, String.class).getValue(getElContext());

    oldValue.setValue(getElContext(), value);

    toggleEditMode();
  }

  /**
   *
   */
  public void cancel() {
    ValueExpression value = getAttr(VALUE_ATTRIBUTE, String.class);

    String oldValue = (String) getAttr(OLD_VALUE_ATTRIBUTE, String.class).getValue(getElContext());

    value.setValue(getElContext(), oldValue);

    toggleEditMode();
  }

  /**
   *
   */
  public void toggleEditMode() {
    if (StringUtils.isEmpty((String) getAttr(OLD_VALUE_ATTRIBUTE, String.class).getValue(getElContext()))) {
     getAttr(OLD_VALUE_ATTRIBUTE, String.class).setValue(getElContext(),
         getAttr(VALUE_ATTRIBUTE, String.class).getValue(getElContext())
     );
    }

    ValueExpression editmode = getAttr(EDIT_MODE_ATTRIBUTE, Boolean.class);
    editmode.setValue(getElContext(), !((Boolean) editmode.getValue(getElContext())));

  }

  /**Get value expression for a given attr.*/
  private ValueExpression getAttr(final String attribute, final Class<?> attributeType) {
    return getContext().getApplication().getExpressionFactory()
           .createValueExpression(getElContext(), attribute, attributeType);
  }

  /**Get ElContext.*/
  public ELContext getElContext() {
    if (this.elContext == null) {
      elContext = getContext().getELContext();
    }
    return elContext;
  }

  public void setElContext(final ELContext elContext) {
    this.elContext = elContext;
  }

  /**Get faces context*/
  public FacesContext getContext() {
    if (this.context == null) {
      context = FacesContext.getCurrentInstance();
    }
    return context;
  }

  public void setContext(final FacesContext context) {
    this.context = context;
  }
}
import org.apache.commons.lang3.StringUtils;
导入javax.el.ELContext;
导入javax.el.ValueExpression;
导入javax.faces.component.FacesComponent;
导入javax.faces.component.NamingContainer;
导入javax.faces.component.UIComponentBase;
导入javax.faces.component.UINamingContainer;
导入javax.faces.context.FacesContext;
导入java.io.Serializable;
/**
*拉布拉罕于2016年1月14日创作。
*/
@FacesComponent(value=“editableLabel”)
公共类EditableLabel扩展UIComponentBase实现可序列化的NamingContainer{
私有静态最终长serialVersionUID=108467781935083432L;
公共静态最终字符串值_ATTRIBUTE=“#{cc.attrs.VALUE}”;
公共静态最终字符串OLD_VALUE_ATTRIBUTE=“#{cc.attrs.oldValue}”;
公共静态最终字符串EDIT_MODE_ATTRIBUTE=“#{cc.attrs.editMode}”;
私有FacesContext上下文;
私人语境;
@凌驾
公共字符串getFamily(){
返回UINamingContainer.COMPONENT_族;
}
/**
*
*/
公共无效更新(){
ValueExpression oldValue=getAttr(旧值属性,String.class);
String value=(String)getAttr(value_属性,String.class).getValue(getElContext());
setValue(getElContext(),value);
切换编辑模式();
}
/**
*
*/
公开作废取消(){
ValueExpression value=getAttr(value\u属性,String.class);
String oldValue=(String)getAttr(OLD_VALUE_属性,String.class).getValue(getElContext());
setValue(getElContext(),oldValue);
切换编辑模式();
}
/**
*
*/
public void toggleEditMode(){
if(StringUtils.isEmpty((String)getAttr(OLD_VALUE_属性,String.class).getValue(getElContext())){
getAttr(旧值属性,String.class).setValue(getElContext(),
getAttr(VALUE\u属性,String.class).getValue(getElContext())
);
}
ValueExpression editmode=getAttr(编辑模式属性,Boolean.class);
setValue(getElContext(),!((布尔)editmode.getValue(getElContext()));
}
/**获取给定属性的值表达式*/
私有值表达式getAttr(最终字符串属性,最终类属性类型){
返回getContext().getApplication().getExpressionFactory()
.createValueExpression(getElContext(),属性,attributeType);
}
/**获取上下文*/
公共ELContext getElContext(){
if(this.elContext==null){
elContext=getContext().getELContext();
}
返回上下文;
}
公共无效集合上下文(最终集合上下文){
this.elContext=elContext;
}
/**获取面上下文*/
public FacesContext getContext(){
if(this.context==null){
context=FacesContext.getCurrentInstance();
}
返回上下文;
}
公共void setContext(最终面上下文){
this.context=上下文;
}
}
现在,此小部件的所有实例都将具有cancel()和update()函数定义的cancel和update的基线功能。但是,除了这个基本功能之外,用户可能还需要一些附加功能(例如在更新时调用webservice),这些功能将通过某种支持bean方法添加到updateListener和/或cancelListener属性中


我的问题是,是否可以从FacesComponent内部以编程方式调用用户附加到侦听器属性的方法,或者我这样做是错误的?

是的,它可以作为
MethodExpression
类型化属性提供。所有复合属性都可以通过继承的映射以通常的方式使用。另见

例如,要获取
#{cc.attrs.updateListener}
并在没有参数的情况下调用:

MethodExpression updateListener = (MethodExpression) getAttributes().get("updateListener");
updateListener.invoke(getFacesContext().getELContext(), null);

与具体问题无关,处理
ValueExpression
属性的方法很笨拙。要获取
{cc.attrs.oldvalue}
,只需执行以下操作:

String oldvalue = (String) getAttributes().get("oldvalue");
getAttributes().put("value", oldvalue);
要设置
#{cc.attrs.value}
,只需执行以下操作:

String oldvalue = (String) getAttributes().get("oldvalue");
getAttributes().put("value", oldvalue);
FacesContext
ELContext
作为实例变量,从技术上讲,幸运的是,在这个特定的构造中不会造成伤害,但这是可疑的,您最好将它们放在方法局部范围内。
FacesContext
仅可由用户使用

另见:

是的,它作为
MethodExpression
typed属性提供。所有复合属性都可以通过继承的映射以通常的方式使用。另见

例如,要获取
#{cc.attrs.updateListener}
并在没有参数的情况下调用:

MethodExpression updateListener = (MethodExpression) getAttributes().get("updateListener");
updateListener.invoke(getFacesContext().getELContext(), null);

与具体问题无关,处理
ValueExpression
属性的方法很笨拙。要获取
{cc.attrs.oldvalue}
,只需执行以下操作:

String oldvalue = (String) getAttributes().get("oldvalue");
getAttributes().put("value", oldvalue);
要设置
#{cc.attrs.value}
,只需执行以下操作:

String oldvalue = (String) getAttributes().get("oldvalue");
getAttributes().put("value", oldvalue);
FacesContext
ELContext
作为实例变量,从技术上讲,幸运的是,在这个特定的构造中不会造成伤害,但这是可疑的,您最好将它们放在方法局部范围内。
FacesContext
仅可由用户使用

另见:

感谢巴卢斯的帮助。昨天我开始匆忙地自学这些东西。谢谢巴卢斯的帮助。昨天我开始匆忙地自学这些东西。