【问题标题】:Dynamic choice of bean in ELEL中bean的动态选择
【发布时间】:2026-01-04 21:40:02
【问题描述】:

有没有办法在运行时而不是设计时指定 EL 中使用的托管 bean?例如。 actionListener="#{myBean.method}" 使得 myBean 部分可以具有不同的值,具体取决于调用代码的 JSF 页面(前提是使用的任何对象而不是 myBean 都派生自实现“方法”的公共父级)。

【问题讨论】:

    标签: java jsf el


    【解决方案1】:

    如果您事先知道 bean 范围并且事先已经创建了 bean,那么可以,可以使用以下语法:

    actionListener="#{requestScope[beanName].method}"
    

    其中#{requestScope} 代表请求范围映射(相同的映射可用于视图、会话和应用程序范围),#{beanName} 代表保存托管 bean 名称的变量。

    如果您事先不知道 bean 范围和/或没有事先创建 bean,那么您需要创建一个执行 Application#evaluateExpressionGet() 的实用 EL 函数,以便可以使用它如下:

    actionListener="#{util:getBean(beanName).method}"
    

    【讨论】:

    • 我的范围是“ViewScoped”,所以我想你答案的第二部分可能更适合。问题是我在运行时不知道 bean 的名称。假设我知道“beanName”,您编写了 {util:getBean(beanName).method}。但是,我需要在以下条件下获取与给定页面关联的 bean(无论它的名称是什么):1)只有一个 ViewScoped bean 与页面关联,2)这个 bean 继承自“父”bean。
    • 作为回答,相同的地图可用于视图、会话和应用程序范围。使用#{viewScope[beanName].method}。您也许可以使用视图 ID 作为 bean 名称。您可以使用#{view.viewId} 获取视图ID。您可能只需要从中拆分路径 / 和父文件夹。您可以为此使用 JSTL 函数。
    • 谢谢,我会深入研究文献,现在尝试并回信。
    • 我把它放在我的代码中:。 WF_M_2 是 bean 的实际名称(只是想尝试这种方法)。按下按钮时,我得到“目标无法访问,'project.modules.dev2.managedBeans.miniwf.WF_M_2@6215db' 返回 null”。
    • 对不起,我忘了提一个重要的前提条件:bean 必须事先已经创建(这通常通过事先在视图中明确指定#{beanName} 来完成)。我更新了答案。您最好的选择似乎确实使用了一些 EL 实用功能(或者在使用 EL 2.2 时,甚至是应用程序范围托管 bean 的一些辅助方法)。您可以在此答案中找到如何创建自定义 EL 函数:*.com/questions/7079978/…
    【解决方案2】:

    如果您的问题涉及为具有公共元素的多个子类生成一组页面,您也可以使用页面组合来实现此目的。

    例如,如果 Resident 和 Nonresident 是 Person 子类的托管 bean:

    例如。在'non-resident.xhtml'中

    <ui:define name="body">
        <ui:param name="Controller" value="#{NonResident}"/>
        <ui:include src="anyone.xhtml"/>
    </ui:define>
    

    在“resident.xhtml”中

    <ui:define name="body">
        <ui:param name="Controller" value="#{Resident}"/>
        <ui:include src="anyone.xhtml"/>
    </ui:define>
    

    然后'anyone.xhtml'可以使用'Controller'作为bean名称来定义公共元素。

    这种方法还可以让您消除重复的页面定义。

    【讨论】: