【问题标题】:In jsf, how should a bean communicate with a regular java class (aka the business logic)在 jsf 中,bean 应该如何与常规 java 类(又名业务逻辑)进行通信
【发布时间】:2012-08-11 03:04:58
【问题描述】:

这是一个基于 glassfish 的 jsf 项目,由 Netbeans 开发。我尝试将我的 bean 连接到我的常规 java 类。

这是我的理解:
- 托管 bean 或其 CDI 等效项负责处理与 UI 相关的用户数据(例如,用户输入)
- 业务逻辑在常规 java 类中实现
- 2 个托管 bean 或其 CDI 等效项可以与 @injection 通信

我缺少的是:bean 如何与常规 java 类 通信? (我的业务逻辑在哪里?)
换句话说,我希望我可以通过使用 bean 作为其构造函数的参数来运行我的 java 类!

我试过了:
- 在我的 java 类中包含 @Inject 注释,但这不起作用(bean 未注入,保持为空)
喜欢

public class myJavaProgram (){
@Inject
UserInputBean userInputBean;
//my business logic using the properties of userInputBean here...  //does not work, userInputBean is null!
}
  • 在我的 java 类的构造函数中将 bean 的属性作为参数传递。有效,但丑陋:为什么我不能简单地将整个 bean 作为参数直接传递给构造函数?但是当我这样做时,我的 java 类中的 bean 再次出现空指针异常。

    我错过了什么吗?谢谢!

【问题讨论】:

  • 一个非常开放的问题,更多细节会有所帮助。但无论如何,在我们的应用程序中,我们扭转了局面。我们有命令按钮委托给的动作处理程序类,这些类要么直接实例化业务对象,要么将业务对象注入其中。换句话说,让您的业务对象成为您的操作处理程序的客户端,而不是尝试使用 bean 作为您的业务对象的客户端。
  • 我的 pb 非常简单:我的 bean 从用户输入中收集 2 个字符串:名字和姓氏。我想将这两个字符串导出到一个类中,该类执行一个将这两个字符串作为参数的 API 调用。您的解决方案很有趣,但我很惊讶没有更直接的方法来处理它?无论如何谢谢@SteveAtkinson
  • 我不明白,你需要像public class Bean { String s1; String s2; public void someAction() { BL bl = new BL(); bl.doSomething(s1, s2); //...} } 这样的东西,然后在你的页面中使用<h:commandButton value="click me" action="#{bean.someAction}" />
  • @LuiggiMendoza 我不认为 OP 真的知道他的问题是什么,他似乎从根本上对依赖注入和控制框架反转的概念感到困惑。
  • 这只是基本的 Java。您是 Java 新手吗?根据您的问题历史,我强烈建议您选择一本不错的 Java 和 Java EE 书籍。

标签: jsf netbeans glassfish javabeans facelets


【解决方案1】:

现代企业应用程序通常在整个应用程序中使用依赖注入模式,而不仅仅是表示层。因此,您将有一个数据访问层贡献 bean,例如 EntityManager。这些被注入到业务服务中,形成业务服务层。反过来,业务服务被注入到您的 JSF 支持 bean 中。什么依赖注入容器最好是一个有争议的问题,你也可以混合它们。

在 Java EE 6 标准中(至少我是这么理解的),EJB 充当数据访问和业务服务层的依赖注入容器,而 CDI 充当表示层的依赖注入容器(这就是为什么您可以注入CDI bean 中的 EJB)。其他人则希望替换 EJB 并通过所有层使用 CDI。还有一些人仍然聪明地摆脱了 J2EE 造成的伤害,并使用 Spring 作为依赖注入容器。

提供一些代码,你可以这样做:

@Named
@SessionScoped
public class UserBean {

    @Inject UserService userService;

    User user;

    public void save() {
        userService.create(user);
    }

}

@Stateless
public class UserService {
    public void create(User user) { ... }
}

【讨论】:

  • >EJB 充当数据访问和业务服务层的依赖注入容器——我不会这么说。 CDI 是整体注入设施。 EJB bean(@Resource,@EJB)中恰好提供了注入,但这被认为已被 CDI 取代。 EJB 确实提供了对数据访问和业务层特别方便的服务(但预计这些服务最终也会成为基于 CDI 的服务)
  • 据我所知,JEE 6 规范和 JEE 7 规范都没有推荐或反对在数据访问和业务服务层使用 CDI。虽然我同意 @EJB 可能会在 JEE 规范的未来版本中被弃用,但这还没有发生,因此是一个意见问题。
  • 确实,规范并没有具体说明 CDI 是否适合。虽然这不是我的意思;)我只是指注射能力,例如@Inject@Resource。在 EJB bean 中,您可以将@Inject 用于许多事情(不是全部!),从而让 CDI 处理注入,同时仍然使用 EJB 组件模型和 EJB 服务(如池、安全等)。
  • >虽然我同意 @EJB 可能会在 JEE 规范的未来版本中被弃用,但这还没有发生 - 它确实还没有发生,但实际上正在讨论中.参见例如EJB 规范负责人 (Marina) 在她的博客上发表的评论:blogs.oracle.com/marina/entry/ejb_3_2_news(最后评论)
  • >因此是一个见仁见智的问题 - 嗯,目前我认为 EJB 是更好的数据访问/业务逻辑的 bean。到目前为止,并非所有 EJB 服务都已迁移到 CDI 扩展/拦截器。因此,对于数据访问和业务逻辑,我个人建议继续使用 EJB。但如前所述,可以使用 CDI 丰富 EJB,在可能的情况下使用 @Inject 将 EJB bean 注入其他 bean 并在适当的情况下将 CDI 范围应用于 EJB bean。
【解决方案2】:

我假设当您说 CGI 时,您实际上是指 CDI...

这是一个 IoC(控制反转)框架,用于促进 JSF 应用程序中的 DI(依赖注入)。这种框架的另一个例子是 Spring,它正在慢慢开始采用更好的 JSF 支持。

如果您打算将业务逻辑从托管 bean 分离到 CDI 注入的 bean 中,那么 JSF 托管 bean 的角色是您的表示逻辑的视图控制器和存储库。

@Inject 注释只会注入已通过 CDI 配置的对象,这取决于您的项目设置,可能实际上包含也可能不包含 JSF 托管 Bean。这一切都取决于您如何配置项目以及正在使用什么 EL Resolver 实现。如果它是您的 JSF 实现(例如 Mojarra)的默认 EL 解析器,则正在使用 EL 解析器的 JSF 实现,您的 IoC 将无法识别这些依赖关系。

当然,您仍然可以将托管 bean 依赖注入到其他托管 bean,但您需要通过 EL Resolver 执行此操作。

@ManagedProperty("#{userInputBean}")
UserInputBean userInputBean;

您引用的其他 Java 类依赖项应代表您的业务逻辑层,并应由 CDI 配置和处理。

【讨论】:

    猜你喜欢
    • 2011-07-03
    • 1970-01-01
    • 2010-12-24
    • 2015-11-10
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多