使用 JSF 自动设置托管 bean 变量的值

Automatically set value of a managed bean variable with JSF

我想在后台将一个值传递给托管 bean。所以我有这个托管 bean:

@ManagedBean(name = "mbWorkOrderController")
@SessionScoped
public class WorkOrderController {

    // more attributes...

    private WorkOrder workOrderCurrent;

    // more code here...

    public WorkOrder getWorkOrderCurrent() {
        return workOrderCurrent;
    }

    public void setWorkOrderCurrent(WorkOrder workOrderCurrent) {
        this.workOrderCurrent = workOrderCurrent;
    }
}

它持有自定义类型 WorkOrder 的参数 workOrderCurrent。 class WorkOrder 具有类型 String 的属性 applicant

目前我在 inputtext 中使用 placeholder 来向用户显示他需要在 inputText 中键入的内容。

<p:inputText id="applicant"
    value="#{mbWorkOrderController.workOrderCurrent.applicant}"
    required="true" maxlength="6"
    placeholder="#{mbUserController.userLoggedIn.username}" />

我想做的是自动将 mbUserController.userLoggedIn.username 的值传递给 mbWorkOrderController.workOrderCurrent.applicant 并从我的表单中完全删除 applicantinputText

我尝试使用 c:set:

<c:set value="#{mbUserController.userLoggedIn.username}" target="#{mbWorkOrderController}" property="workOrderCurrent.applicant" />

但不幸的是我收到 javax.servlet.ServletException 消息:

class'WorkOrderController'没有属性'workOrderCurrent.applicant'.

有人有什么建议吗?

The class 'WorkOrderController' does not have the property 'workOrderCurrent.applicant'.

您的 <c:set> 语法不正确。

<c:set value="#{mbUserController.userLoggedIn.username}"
       target="#{mbWorkOrderController}" 
       property="workOrderCurrent.applicant" />

你似乎在想那部分..

value="#{mbWorkOrderController.workOrderCurrent.applicant}"

..在幕后工作如下:

WorkOrderCurrent workOrderCurrent = mbWorkOrderController.getWorkOrderCurrent();
workOrderCurrent.setApplicant(applicant);
mbWorkOrderController.setWorkOrderCurrent(workOrderCurrent);

这不是真的。它的工作原理如下:

mbWorkOrderController.getWorkOrderCurrent().setApplicant(applicant);

因此,正确的 <c:set> 语法如下:

<c:set value="#{mbUserController.userLoggedIn.username}"
       target="#{mbWorkOrderController.workOrderCurrent}" 
       property="applicant" />

也就是说,所有这些都不是 the concrete problem you actually tried to solve 的正确解决方案。您应该在模型本身中执行模型预填充。这可以通过使用 @ManagedProperty 引用另一个 bean 属性 并使用 @PostConstruct 基于它执行初始化来实现。

@ManagedBean(name = "mbWorkOrderController")
@SessionScoped
public class WorkOrderController {

    @ManagedProperty("#{mbUserController.userLoggedIn}")
    private User userLoggedIn;

    @PostConstruct
    public void init() {
        workOrderCurrent.setApplicant(userLoggedIn.getUsername());
    }

    // ...
}

也许你可以多解释一下上下文,但这是另一种解决方案。如果您从另一个页面导航,您可以在 URL 中传递工作 WorkOrder 的一些标识符,例如 http://host:port/context/page.xhtml?workOrderId=1.

然后,您可以像这样在托管 bean 中设置标识符:

<h:html>
    <f:viewParam name="workOrderId" value="#{mbWorkOrderController.id}"/>
</h:html>

您必须向您的 bean 添加一个新的 属性:

public class WorkOrderController {
    private long id;
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }

    // ...
}

然后,在 JSF 设置 属性 之后,您可以在生命周期事件中找到工单:

<h:html>
    <f:viewParam name="workOrderId" value="#{mbWorkOrderController.id}"/>
    <f:event type="preRenderView" listener="#{mbWorkOrderController.findWorkOrder()}"/>
</h:html>

public class WorkOrderController {
    private long id;
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }

    public void findWorkOrder() {
        this.workOrderCurrent = null /* some way of finding the work order */
    }

    // ...
}

此策略的优点是让您可以收藏 URLs。