EJB 通常用于实现任何类型的服务。它们与 JPA 集成得非常好,因此经常用于 DB 访问,但这不是它们的唯一用途。
EJB 通常不适合建模数据。 IE。它们应该是应用程序中的动词,而不是名词。因此以下是错误的:
@Stateless
@Entity
public class CreditCard { // silly, don't do this!
@Id
Long id; + getters/setters
Data expiration date; + getters/setters
}
以下更好,它是一项服务,当您的应用程序启动时,它会从某处获取一些报价数据:
@Singleton
@Startup
public class QuoteFetcher {
private List<Quote> quotes; // + getter
@PostConstruct
public fetchQuote()
quotes = SomeUrlBuilder.someUrl().getQuotes();
}
}
以下是强制性 DAO 示例:
@Stateless
public class JPAInvoiceDAO implements InvoiceDAO {
@PersistenceContext
private EntityManager entityManager;
public Invoice getById(Long invoiceId) {
return entityManager.find(invoiceId, Invoice.class);
}
// More DAO methods
}
下面展示了如何使用声明性安全性,以及 bean 如何查找已在外部映射到其私有上下文 (ENC) 的内容:
@Stateless
public class TokenFetcher
@Resource
private SessionContext sessionContext;
@RolesAllowed("SYSTEM")
public Token getToken() {
return (Token) sessionContext.lookup("token");
}
}
问题的第二部分似乎是如何在您的代码中使用这些 bean。基本上有四种方法:
- 托管 bean 中的注入
- 通过 JNDI 引导
- 启动时自动调用
- 通过计时器自动
注入是最简单的方法,但只有托管 bean 才是注入候选者(基本上意味着 Java EE 框架会创建 bean,并且您不使用 new() 来实例化它)。
例如注入:
@ManagedBean
public class InvoiceBacking {
private Long invoiceId; // + getter/setter
private Invoice invoice; // + getter
@EJB
private InvoiceDAO invoiceDAO;
@PostConstruct
public void init() {
invoice = invoiceDAO.getById(invoiceId);
}
}
(另见Communication in JSF 2.0#Processing GET request parameters)
通过 JNDI 引导:
public class SomeQuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
// verbose exception handling and closing JNDI context omitted for brevity
}
}
前面展示的 @Singleton bean 是 Java EE 框架如何在启动时调用您的代码本身的一个示例。对于自动计时器,您可以在 bean 的方法上使用 @Schedule 注释。