Анзор Кармов
等級 31
Санкт-Петербург

介紹EJB

在 Random-TW 群組發布
在本文中,我們將了解 EJB——Enterprise JavaBeans。該技術是 Java EE 規範的一部分。我們將討論以下問題:
  • 什麼是 EJB;
  • EJB 的歷史是什麼?
  • 有哪些類型的 EJB?
我們還將使用 EJB 和 servlet 編寫一個小型 HelloWorld 應用程式。 EJB 簡介 - 1本文對於已經熟悉 Java SE 並開始學習 Java EE 的讀者很有用。為了充分理解本文的實作部分,建議您先閱讀「設定本地環境」一文。

EJB 簡史

早在 1996 年,當本文作者 5 歲的時候,Java 就已經在開發者中流行起來。原因是友善的API、自動垃圾收集等。Java被廣泛應用於負責後端的系統。然而,儘管語言有很多樂趣,但當時的程式設計師需要 JDK 中尚未實現的某些功能。這些需求是:
  • 確保資料持久性;
  • 交易完整性
  • 競爭性存取資料(多執行緒控制);
  • 很可能還有別的東西。
所有這些導致本土、自寫、封閉圖書館的數量自然增長。換句話說,每個人都盡力滿足了自己的需求。直到 IBM 提出了「每個人都應該以同樣的方式滿足他們的需求」的口號,並於 1997 年發布了 Enterprise Java Bean (EJB) 規格。正是這樣,才能夠統一開發流程,並將典型問題(上面描述為需求)的解決方案帶到框架中。Sun 已經花了兩年的時間來適應 IBM 的創意,並於 1999 年發布了 EJB 1.0 規範。這就是該技術的誕生方式,我們將在更多應用方面進一步討論該技術。

什麼是EJB

從某種意義上說,EJB 是一個集體術語,根據上下文,它可以表示一般的 Enterprise JavaBeans 技術本身,也可以表示屬於 EJB 技術一部分的某些特定 Enterprise JavaBean 軟體元件 (bean)。維基百科上給出了 EJB 作為一種技術的定義:Enterprise JavaBeans(也經常用作縮寫 EJB)是一種用於編寫和支援包含業務邏輯的伺服器元件的技術規格。它是 Java EE 的一部分。當業務邏輯至少需要以下服務之一(通常是所有服務)時,通常會使用此技術:
  • 支援資料持久性:即使停止程序後資料也應該是安全的。最常使用資料庫來實作;
  • 支援分散式事務;
  • 支援並行資料修改和多執行緒;
  • 活動支援;
  • 命名和目錄支援(JNDI);
  • 資料存取的安全性和限制;
  • 支援在應用程式伺服器上自動安裝;
  • 遠端存取。
上面列出的服務是EJB技術無疑的優勢。另一個這樣的優點是上面列出的所有內容都可以立即使用。那些。程式設計師不需要考慮支援分散式事務。程式設計師只需要考慮他目前正在嘗試實現的業務邏輯。作為特定軟體元件的 EJB 是一個 Java 類,帶有來自 EJB 規範的一個或多個註釋,其中包含應用程式的一些業務邏輯。EJB 規範中的註釋賦予了標記類某些權力、權力和超級權力。請閱讀下文以了解更多相關資訊。

EJB類型

我們來總結一下。EJB 是一個帶有特殊註解之一的常規 Java 類別。這樣的類別稱為 Bean。根據類別標記的註釋,它將代表一種或另一種類型的 EJB(bean)。豆子主要分為三種:
  • Message Driven Beans(訊息驅動bean);
  • Entity Beans-在JPA(Java Persistence API)規格中定義,用於儲存資料;
  • 會話 Bean。
後者(會話 bean)分為幾個子類型:
  • 無狀態(無狀態);
  • 有狀態(支援目前會話狀態);
  • 單例(整個應用程式的一個物件;從 EJB 3.1 開始)。
EJB 簡介 - 2下面我們將更詳細地了解每種類型的 bean。

會話Bean

會話 Bean,或稱為會話 Bean,是一種特定類型的 Bean。它們封裝了客戶端可以透過呼叫 bean 的方法以程式設計方式呼叫的業務邏輯。方法呼叫可以執行以下操作:
  • 本地,透過與會話 bean 相同的 JVM 中的另一個類別;
  • 使用 Java RMI(遠端方法呼叫)技術,透過網路從另一個 JVM 進行遠端操作。
「會話」一詞表示該 Bean 僅在伺服器執行特定任務時可用,並且在伺服器發生故障或關閉時將被不可挽回地破壞。會話 bean 實例的生命週期由 EJB 容器控制(您可以在本系列的第一講中閱讀更多有關 EJB 容器的資訊)。 無狀態會話 Bean不會儲存有關其狀態的資訊。這種類型的組件可供各種客戶端使用。無狀態 Bean 用於實現可在一次操作中完成的業務流程。例如,檢查客戶的信用記錄。因為單一 bean 實例可以由多個客戶端使用,所以開發人員必須提供對 bean 資料的線程安全存取。創建這種類型的 Bean(以及所有其他會話 Bean)非常簡單。這是一個帶有註解的常規 Java 類別@Stateless。下面我們舉個例子:
import javax.ejb.Stateless;

@Stateless
public class StatelessEjbExample {
    public String sayHi() {
        return "Hi, I'm Stateless EJB!";
    }
}
支援當前會話狀態(有狀態)的會話 bean保留有關同一客戶端呼叫之間的狀態信息,並根據客戶端的明確請求終止其存在。這是因為有狀態 Bean 對於每個客戶端來說都是唯一的。這種類型的 Bean 可以負責的任務的一個範例是讓線上商店中的購物車為每個使用者保持最新。這些bean 的生命週期由EJB 容器管理。當客戶端退出時,這些 Bean 也會被銷毀。這樣的豆子也很容易創建。這是一個用註解標記的 Java 類別Stateful。下面的例子:
import javax.ejb.Stateful;

@Stateful
public class StatefulEjbExample {
    public String sayHi() {
        return "Hi, I,m Stateful EJB";
    }
}
單例會話 bean在應用程式的生命週期內啟動一次,並在應用程式的整個生命週期中存在。此類 Bean 專為必須在所有用戶端之間共用一種狀態的情況而設計。與無狀態 Bean 一樣,在獨立 Bean 中,開發人員需要確保 Bean 內的環境以線程安全的方式組織。讓我們舉一個 Singleton bean 的例子,它和上面討論的對應的 bean 一樣容易建立。很容易猜到這是一個帶有註解的Java類別@Singleton。但是,在這種情況下您需要小心。有兩個註釋,語法相同,但用途不同並且位於不同的包中:
  • javax.ejb.Singleton
  • javax.inject.Singleton
要建立 EJB,您必須使用javax.ejb. 下面的例子:
import javax.ejb.Singleton;

@Singleton
public class SingletonEjbExample {
    public String sayHi() {
        return "Hi, I'm Singleton EJB!";
    }
}

訊息驅動 Bean

訊息驅動 Bean(或 MDB)或訊息驅動 Bean 實現一些業務邏輯,如會話 Bean。但與它的親戚不同的是,MDB 有一個重要的區別。客戶端從不直接呼叫 MDB 方法。此類 Bean 通常充當 JMS(Java 訊息服務)訊息的偵聽器,並用於組織系統各部分之間的非同步訊息交換。此類訊息的一個範例是從自動化零售系統向供應管理系統傳送庫存的請求。下面是 MDB bean 的範例。與會話 bean 不同,它的創建更有趣一些:
import javax.annotation.Resource;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(mappedName = "jms/TestQueue")
public class MessageDrivenEjbExample implements MessageListener {

    @Resource
    private MessageDrivenContext messageDrivenContext;

    public void onMessage(Message message) {
        try {
            if (message instanceof TextMessage) {
                TextMessage msg = (TextMessage) message;
                msg.getText();
            }
        } catch (JMSException e) {
            messageDrivenContext.setRollbackOnly();
        }
    }

}
該註解MessageDriven使我們的 MDB 類別成為一個 bean。在註釋內部,使用 JNDI(在此處閱讀有關 JNDI的資訊)確定了 JMS 發行版的名稱,我們的類別將成為該發行版的偵聽器。此外,我們的類別也實作了該介面MessageListener及其方法onMessage。當一些訊息從佇列/分發到達且其名稱在註解中定義時,將呼​​叫此方法MessageDriven

實體bean

EJB 技術的一部分是 JPA 規格。JPA(即 Java Persistence API)是一種規範,它提供 Java 物件(實體 bean)的物件關係映射 (ORM),並提供用於儲存、檢索和管理此類物件的 API。JPA 允許您將資料庫中的資料表示為 Java 對象,以及將 Java 對象保存為資料庫中的記錄。並不是每個類別都可以充當這樣的對象,但實體 bean 除外。Entity Bean 是一個 Java 類,表示資料庫中的表。顯示(映射)是透過使用特殊註釋來實現的。在它們的幫助下,可以將 Java 類別與資料庫中的表格進行比較,以及將 Java 類別的欄位與資料庫表格的欄位進行比較。下面是一個實體 bean 的範例,程式碼中帶有註解:
@Entity // Делает данный класс Entity бином
@Table(name = "employee") // "Связывает" данный класс с таблицей employee в БД
public class Employee implements Serializable {

    @Id // Говорит о том, что поле ниже является первичным ключом
    @GeneratedValue(strategy = GenerationType.AUTO) // Определяет тип генерации значений первичного ключа
    private int id;

    @Column(name="name") // "Связывает" поле ниже с полем name в таблице employee в БД
    private String name;

    @Column (name="age") // "Связывает" поле ниже с полем age в таблице employee в БД
    private int age;

    // getters and setters...
}
值得注意的是,這種類型的 bean 僅在研究 JPA 規範的背景下才有意義。

編寫應用程式:EJB HelloWorld

在本節中,我們將編寫一個小型 Java EE HelloWorld 應用程序,並將其部署在 GlassFish 伺服器上。在閱讀本文之前,強烈建議您閱讀有關設定本地環境的文章
  1. 在 IntelliJ IDEA 中建立一個新的 Maven 專案。

    文件 -> 新建 -> 項目...

    EJB 簡介 - 3
  2. 點擊下一步

  3. 填寫Maven項目參數:

    EJB 簡介 - 4
  4. 按一下“完成”

  5. 該專案已建立並具有以下結構:

    EJB 簡介 - 5
pom.xml 檔案如下所示: EJB 簡介 - 6首先,我們需要新增對 Java EE API 的依賴,並指定以 Web 應用程式存檔(war)的形式打包我們的專案。為此,您需要將 pom.xml 程式碼變更為以下形式:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.javarush.lectures</groupId>
    <artifactId>ejb_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
        </dependency>
    </dependencies>

</project>
接下來,您可以繼續處理 Java 程式碼。我們的應用程式將是最簡單的。我們將有 1 個 servlet 和 1 個 EJB。這將是一個無狀態會話 bean。在 EJB 內部,我們將只定義 1 個傳回字串「Hello World」的方法。首先,讓我們創建一個套件com.javarush.lectures。然後,在包內com.javarush.lectures,我們將建立我們的 bean - DemoEJB。bean程式碼如下:
import javax.ejb.Stateless;

@Stateless
public class DemoEJB {
    public String helloWorld() {
        return "Hello world!";
    }
}
正如前面所說,一切都很簡單。我們的下一步是建立一個 servlet,它將傳遞來自 EJB 的值作為對 HTTP 請求的回應。值得注意的是,servlet 不是本文的主題,但您仍然需要使用它們來示範 EJB。為此,我們DemoServlet在與 EJB 相同的套件中建立一個新的 servlet。其程式碼如下:
@WebServlet("/helloWorld")
public class DemoServlet extends HttpServlet {

    @EJB
    private DemoEJB ejb;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write(ejb.helloWorld());
    }
}
以下是對程式碼的一些簡短評論。Abstract @WebServlet("/helloWorld")- 將我們的類別定義為 servlet,它將處理對端點的 HTTP 請求/helloWorld。我們班有一個場地—— DemoEJB ejb. 這是我們之前定義的 bean。類別欄位上的註解 —@EJB執行依賴項注入 (DI)。那些。需要時,ejb 變數會自動以新實例進行初始化。我們的類別是 HttpServlet 的後代,並重寫超類別方法之一 - doGet。此方法處理 HTTP GET 請求並採用兩個參數 -HttpServletRequestHttpServletResponseHttpServletRequest用於取得有關傳入 HTTP 請求的資訊。HttpServletResponse需要產生對請求的回應。在方法內部,我們使用PrintWriter.response 物件從回應物件 ( ) 取得物件。接下來,我們可以使用 向結果物件寫入一些值。事實上,我們透過將從我們定義的 EJB 獲得的值寫入 -a 物件來使用它(該值是字串「Hello World!」)。發送 HTTP 請求的用戶端將收到此值作為對其請求的回應。下一步是在 GlassFish Java EE 伺服器上啟動應用程式。為此,我們將建立一個新配置,如有關設定本地環境的文章所述。下面是目前專案完成配置的螢幕截圖。確保在開始之前安裝了 GlassFish 伺服器: 建立啟動配置後,使用Run -> Run 'ejb_demo'選單或使用Shift+F10熱鍵啟動應用程式。啟動後,您可以看到它的日誌: 以及打開的瀏覽器: 所有這些都表明應用程式按預期工作。 HttpServletResponsegetWriter()writePrintWriterEJB 簡介 - 7EJB 簡介 - 8EJB 簡介 - 9

結論

在本文中,我們了解了 EJB——Enterprise JavaBeans。我們考慮了以下問題:
  • 什麼是EJB?
  • EJB歷史
  • 不同類型的 EJB
回想一下,EJB 有以下類型:
  • Message Driven Beans(訊息驅動bean);
  • Entity Beans - 在JPA(Java Persistence API)實體規格中定義並用於儲存資料;
  • 會話 Bean:
    • 無狀態(無狀態)
    • 有狀態(支援目前會話狀態)
    • 單例(整個應用程式的一個物件;從 EJB 3.1 開始)
我們也使用 EJB 編寫了一個小型 HelloWorld 應用程式。作為PD,您可以自己重複本文的實作部分。然後再為您的應用程式新增兩個 servlet,它們將使用有狀態 bean 和單例 bean 來接收值。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION