【问题标题】:JSF converter scope when using CDI (Seam 3) view-scoped使用 CDI (Seam 3) 视图范围时的 JSF 转换器范围
【发布时间】:2013-04-04 01:52:55
【问题描述】:

我目前正在审查代码,发现 CDI 转换器如下:

@Named
@RequestScoped
public class BankConverter implements Converter, Serializable
{
    @EJB
    private BankService bankService;

    @Override
    public Object getAsObject( FacesContext ctx, UIComponent comp, String identifier )
    {
        if ( identifier == null || identifier.trim().isEmpty() )
        {
            return null;
        }

        Bank bank = null;

        try
        {       
            bank = this.bankService.findByPrimaryKey( Long.valueOf( identifier ) );
        }
        catch( Exception e )
        {
            // omitted
        }

        return bank;
    }

    @Override
    public String getAsString( FacesContext ctx, UIComponent comp, Object obj )
    {
        if ( obj == null || ( ( Bank ) obj ).getId() == null )
        {
            return null;
        }

        return ( ( Bank ) obj ).getId().toString();
    }

}

转换器基本上总是这样使用(注意converter="#{bankConverter}"):

<p:autoComplete id="bank"
                value="#{employeeDepotManager.selectedBank}"
                var="bnk"
                converter="#{bankConverter}"
                completeMethod="#{autoCompleter.completeBankSearch}"
                itemLabel="#{bnk.name}"
                itemValue="#{bnk}"
                forceSelection="false"
                minQueryLength="3"
                global="true"
                validator="#{employeeDepotManager.validateBank}"
                scrollHeight="200">
    <p:ajax event="itemSelect" update="bank-code bank-name" />
    <p:column>#{bnk.code}</p:column>
    <p:column>#{bnk.name}</p:column>
</p:autoComplete>                    

我目前正在与一位同事讨论哪种范围最适合转换器...

从 JSF 页面引用的管理器 bean 中有 95% 是 @ViewScoped,所以我认为转换器最好也是 @ViewScoped(而不是 @RequestScoped,据我所知,它将重新创建每个 AJAX 请求的转换器实例)。

然后我的同事补充说,转换器可能应该是@Dependent,因为这会自动将转换器放入周围 bean 所在的范围内。我的感觉是,这行不通。但是,我真的不能不同意,因为我的知识差不多到此为止了。

那么,当 JSF 引用的几乎所有 bean 都是 @ViewScoped 时,可能是转换器的最佳范围?

PS:请注意,我们使用 Seam 3 来混合 @Named@ViewScoped

【问题讨论】:

    标签: java jsf ejb cdi seam3


    【解决方案1】:

    由于大多数转换器实际上是无状态的,它们很容易成为@ApplicationScoped,在我看来,这是它们最自然的范围。尽管如此,有些转换器实际上并非如此。例如,DateTimeConverter 后面的 &lt;f:convertDateTime&gt; 标签确实持有一些状态。此外,@FacesConverter 的默认实现使用 Application#createConverter(String converterId) 在需要时创建一个新的转换器实例,因此每个请求可以创建多次。

    此外,就我而言,自定义转换器在范围方面与引用的支持 bean 没有任何交集,因此它们是否为 ViewScoped 并不重要。在选择转换器范围时,真正重要的是转换器实例中保存的状态范围,正如 BalusC 正确发现的那样。

    就您问题中的转换器而言,实际上是无状态的,它可以是@ApplicationScoped

    【讨论】:

    • 请注意,并非所有转换器都是无状态的。例如。 DateTimeConverter 后面的 &lt;f:convertDateTime&gt; 不是。然而,问题中的特定问题是,所以它确实可以安全地是@ApplicationScoped。因此,答案最终归结为:取决于转换器实例中保持的状态范围。
    • @BalusC:我不得不搜索一下以找到我从(你)那里复制的示例。它位于 balusc.blogspot.de/2011/09/… 。你为什么在这里使用@ViewScoped? @All:对于我的具体示例(以及上述示例),只要您通过@EJB@Inject 引用无状态bean,省略范围注释可能最实用?一旦使用其他范围的bean,范围应该可能相同?我实际上正在寻找一个最佳实践...
    • BalusC 确实使用了@ViewScoped 注释用于托管bean@RequestScoped 注释用于转换器。转换器中使用的请求范围意味着它将在每个请求的基础上创建,而如果将它放在应用程序范围内,它将被创建一次并在必要时用于转换每个对象。但是,如果您的转换器是无状态的,则可以实施最后一种方法。省略范围实际上是一个坏主意,除非您知道自己在做什么,否则您将得到default scope
    • @BalusC 感谢您的聪明纠正。 DateTimeConverter 确实不是无国籍的,所以我的回答实际上在逻辑上是不正确的。您不介意我将您的调查包含在答案中吗?
    • Skuntsel,请随时修正您的答案。 Kawu,至于我的博客,这只是为了安全起见,你永远不会知道复制粘贴启动器。例如。 UserService 在他们的情况下可能是有状态的。我至少更新了the blog example,并在@RequestScoped 后面添加了评论。
    猜你喜欢
    • 1970-01-01
    • 2017-06-13
    • 2014-07-08
    • 2013-07-14
    • 1970-01-01
    • 2012-10-11
    • 2014-07-17
    • 1970-01-01
    • 2012-08-03
    相关资源
    最近更新 更多