[英]The Shopping Cart dilemma in JavaEE
我正在使用Java EE堆棧在線商店工作。 為了演示,我使用JSF 2.2,JPA用於持久性,EJB 3.x用於業務邏輯(其中x> = 1)和JAX-RS用於服務,因為還有移動應用程序。
實際問題是購物車的實施。 有一次,購物車可以是SFSB(有狀態會話Bean)。 這意味着EJB容器將servlet / web容器視為客戶端並管理2個容器之間的對話。 如果EJB客戶端是servlet / web容器,那么如何確定將項目添加到購物車的最終用戶(實際客戶端)?
我的第二個選擇是將SFSB存儲到HttpSession
。 這樣,最終用戶可以從HttpSession
檢索購物車(並且會話已經從servlet容器管理)。 這將如何影響EJB對話的事務狀態?
購物車使用JPA保存在數據庫中。
還有什么我需要考慮的嗎?
謝謝。
實際上這是一個非常好的問題。
我70%的開發活動使用完全相同的堆棧(Java EE 7,Glassfish 4,JSF 2.2,EclipseLink JPA,EJB 3.1),我經常開發自定義電子商務網站,因此我對購物設計很熟悉推車。
我遵循的兩種方法(在最終決定兩者之一之前):
@Remote
普通Java接口 SessionScoped
ManagedBean和Stateless EJB實現了一個定義業務邏輯的@Local
接口。 我個人從第一種方法開始,但我最近切換到第二種方法。 我將在后面的答案中解釋原因。
第一種方法非常簡單。 您只需要一個帶有@Remote
注釋的簡單接口和一個實現它的@Stateful
會話Bean。 然后在您的支持bean中,您可以使用@EJB
注釋而不是@Inject
注釋來通過CDI注入接口,以利用EJB注入的所有@Inject
功能,如池。 對於你的購物車,我會創建:
1)名為ShoppingCart.java的接口:
@Remote
public interface ShoppingCart{
public void init(Integer id);
public void addToCart(String product);
}
2)實現ShoppingCart.java接口的名為ShoppingCartImpl.java的有狀態會話EJB
@Stateful
public class ShoppingCartImpl implements ShoppingCart{
private Integer uid;
private ArrayList<String> products;
@PostConstruct
private void create(){
producs = new ArrayList<String>();
}
@Override
public void init(Integer id){
if(id==null){
uid = id;
}
}
@Override
public void addToCart(String product){
if(product!=null){
products.add(product);
}
}
}
客戶端類可以通過@EJB注釋使用CDI訪問Statefull會話Bean。
public class ShoppingCartClient {
@EJB
private static ShoppingCart cart;
// your methods here, using the ShoppingCart interface
}
實際客戶與ShoppingCart實現實例的實例之間的實際“鏈接”得到保證,因為每個客戶端都與有狀態會話bean的新實例相關聯。 從客戶端的角度來看,業務方法似乎在本地運行,盡管它們在會話bean中遠程運行。 對於記錄...... Oracle在他自己的教程中提出了這種方法。
我喜歡的方法
我首選的方法是使用表示代碼的SessionScoped JSF支持bean,並使用無狀態EJB來訪問所需的業務邏輯。 在這種情況下也需要一個接口,但它可以是Local,可以改變代碼:
1)Java Local接口
@Local
public interface ShoppingCart{
public void doSomething(List<Product> list);
}
2)無狀態EJB
@Stateless
public class ShoppingCartImpl implements ShoppingCart{
@Override
public void doSomething(List<Product> list){
// persistence, tax calculation, etc
}
}
3)JSF Session Scoped Bean
@ManagedBean
@SessionScoped
public class CartBean {
private List<Product> products = new ArrayList<Product>();
public void add(Product product) {
products.add(product);
}
public void remove(Product product) {
products.remove(product);
}
public List<Product> getProducts() {
return products;
}
}
第二種方法具有以下好處:
內存占用與第一種情況相同,因為JSF以與存儲狀態會話Bean相同的方式存儲會話范圍的托管bean。
如果您希望能夠在其他地方使用它或在不同的webapp之間共享它們,那么有狀態EJB是適合的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.