天天看點

TomEE 入門指導

介紹

Apache TomEE(音tommy), 多麼熟悉的名字呀!不錯,它是Tomcat的變身,融合JavaEE之特性而成: TomEE = Tomcat + java EE 。那麼,它有何與衆不同之處呢?

衆多應用伺服器使用 Tomcat 提供的 servlet 功能。 這是個不錯的選擇,Tomcat是一款優秀的 servlet 容器。與其它應用伺服器相比, TomEE 不是把 Tomcat 嵌入到應用伺服器中, 而是把 EJB, CDI 及 其它 Java EE特性融入到 Tomcat 中,給你一個以 Tomcat 為主、完全相容的 Web Profile伺服器。建立TomEE 很簡單,隻需将 Tomcat zip 檔案解壓縮,加入自己的 jar 包,并在 conf/server.xml 檔案裡添加一個單執行個體監聽器(single listener),然後重新壓縮打包就可以了。

TomEE 開發有三條很重要的指導性原則:

  • 保持小巧
  • 基于标準
  • 秉承Tomcat衣缽

尤其是第三條,我們是要在 Tomcat 中加入特性,而不是要去除 Tomcat 的特性。

釋出應用和普通 Tomcat 無異,将war包放到 webapps目錄下即可。

也可以用 TomEE 的配置檔案指向你的應用源代碼,

定義在 server.xml 或 context.xml 檔案中的 應用依舊可以工作。

之前難以做到的一些事性,諸如像 WebService 或 EJB 那樣的所有Jave EE 安全概念,

現在都可以安全無縫地工作在 Tomcat 領域(Tomcat Realms)了。

這樣的設計理念并不隻是增強伺服器本身而已,它也帶來了其它好處。

既然,它是 Tomcat 的延伸版本,那麼,能和 Tomcat 一起工作的所有工具,

如 EEclipse WTP 那樣的內建開發工具(IDE tool),也能和 TomEE 和諧工作。

TomEE 的确是真正的 Tomcat 伺服器,并且具備所有 Jave EE Web Profile 的特性,一點不漏。

版本

Apache TomEE 可配置三種不同的版本:Webprofile, JAX-RS, and Plus。Webprofile 提供了最小的釋出版(僅27M),和Java EE Web Profile完全相容; JAX-RS 在 Web Profie 基礎上, 添加了 Apache CXF 的精簡版來實作 JAX-RS 支援,依然基于 Web Profile 标準;Plus 包提供了包含 JMS, JAX-WS 和 JCA 等特性,但它不是基于 Java EE 标準的。

下表列出了三種版本所有不同的特性:

Feature WebProfile JAX-RS Plus
Servlet 3.0 Yes Yes Yes
CDI Yes Yes Yes
EJB Yes Yes Yes
JPA Yes Yes Yes
JSF Yes Yes Yes
JSP Yes Yes Yes
JSTL Yes Yes Yes
JTA Yes Yes Yes
JavaMail Yes Yes Yes
Bean Validation Yes Yes Yes
JAX-RS No Yes Yes
JAX-WS No No Yes
JMS No No Yes
Connector No No Yes

入門

先到Apache TomEE 下載下傳頁面 獲得其中一個釋出版,在寫這篇文章時的最新版是 1.5.0 。 下載下傳解壓後,檢視一下它的檔案目錄結構,你會發現它和 Tocmcat 多麼相似。 bin/ 目錄存放catalina shell/batch 腳本,  conf/ 下存放 配置檔案, webapps/ 下 用于存放  war應用釋出包.。 啟動 Tomcat EE 隻要到 bin 目錄 下執行 ./catalin.sh  (window 下 執行 catalina.bat)。 啟動一般隻需幾秒,然後在浏覽器位址欄中輸入http://localhost:8080,不出問題, 就能看到自帶的 Tomcat 應用。有一個按鈕可以連結到 TomEE控制台, 可檢視你的設定是否正常工作, 還能檢視 JNDI 配置。

Eclipse 開發環境配置

啟動 Eclipse ,我們來看一個簡單的示例。其它的內建開發工具 如 Netbeans 和 IDEA 配置方法雷同。 Eclipse(含 WTP ) 可配置各種不同的應用伺服器,可以釋出代碼, 在你修改代碼後能自動重新釋出。 配置 TomEE 和 配置 Tomcat 無異。

第一步,在 server 視窗選擇 'New server' 連結 :

TomEE 入門指導

第二步,選擇 Apache Tomcat 7, 填上 server 名稱:

TomEE 入門指導

下一步設定本機 TomEE 的安裝目錄:

TomEE 入門指導

要是你的 Eclipse 配置使用 workspace metadata, 而不是 TomEE 的安裝目錄,把 TomEE conf/ 目錄下的配置檔案拷貝到 workspace 是個不錯的選擇。這樣,伺服器直接從 workspace 的 conf/ 目錄下讀取配置。 WTP插件能自動将 Tomcat 配置拷貝到 workspace, 除了 tomee.xml 及 system.properties.

可選的調整 要拷貝必要的檔案,右擊 Server 項目的 localhost-config 檔案夾, 然後 從 conf/ 目錄下導入:

TomEE 入門指導

在 web.xml 中, TomEE 預設不設定JSP開發模式的自動編譯參數,這意味着,即使你儲存更改,JSP也不會編譯更新。打開Servers->Tomcat v7.0 Server  -localhost-config 目錄下的 web.xml 檔案,更改 JSP servlet,将 development 值設為 true就可以了。

Listing 1: web.xml - configuring development mode for JSPs

<servlet>
                <servlet-name>jsp</servlet-name>
                <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
                <init-param>
                        <param-name>fork</param-name>
                        <param-value>false</param-value>
                </init-param>
                <init-param>
                        <param-name>xpoweredBy</param-name>
                        <param-value>false</param-value>
                </init-param>
                <init-param>
                        <param-name>development</param-name>
                        <param-value>true</param-value>
                </init-param>
                <load-on-startup>3</load-on-startup>
        </servlet>
           

一個簡單的應用 

設定好開發模式後,讓我們來示範一個簡單的應用。Apache TomEE 自帶了大量示例,可示範Java EE各種不同特性。目前有100多個。是學習Java EE 新特性極佳的入門資料。在TomEE Subversion 倉庫可以下載下傳到這些例子。此處引用 moviefun 例子。示例代碼見http://tomee.apache.org/examples-trunk/moviefun/README.html。這是個簡單的 web 應用,結合了 Web Profile 的一些特性。 應用定義了一個簡單的 POJO 代表 Movie, 用 JPA 從資料庫存取。代碼如下:

Listing 2: Movie Entity 

@Entity
        public class Movie implements Serializable {

                @Id
                @GeneratedValue(strategy = GenerationType.AUTO)
                private long id;

                private String director;
                private String title;
                private int year;
                private String genre;
                private int rating;

                public Movie() {
                }

                // SNIP getter and setters below...
        }
           

 類中使用了anotation 标注了持久化上下文,以便注入簡單的 EJB 或 CDI bean 執行個體,并通過 JPA 在資料庫中存取Movie 對象。 

Apache TomEE 支援 EJB 1.0 到 3.1版本。 EJB 3.0 的建立較之前版本容易了很多,3.1 版本作了進一步簡化。其中一個新特性叫"無接口"示圖 ("no-interface" view), 意味着 EJB session bean不必再提供接口。

下列展示了一個簡單的無狀态 session EJB, 用 JPA2 管理資料存取。并标注了 anotation @Stateless (EJB 中所必需的),然後通過 TomEE 使用 @PersistenceContext annotation 注入執行個體。 

Listing 3: Stateless session bean using JPA2 

@Stateless
        public class MoviesBean {

                @PersistenceContext(unitName = "movie-unit")
                        private EntityManager entityManager;

                public Movie find(Long id) {
                        return entityManager.find(Movie.class, id);
                }

                public void addMovie(Movie movie) {
                        entityManager.persist(movie);
                }

                public void deleteMovie(Movie movie) {
                        entityManager.remove(movie);
                }

                public void deleteMovieId(long id) {
                        Movie movie = entityManager.find(Movie.class, id);
                        deleteMovie(movie);
                }

                public List<Movie> getMovies() {
                        CriteriaQuery<Movie> cq = entityManager.getCriteriaBuilder().createQuery(Movie.class);
                        cq.select(cq.from(Movie.class));
                        return entityManager.createQuery(cq).getResultList();
                }
        }
           

類還提供了簡單的方法,如查找,删除對象等。getMovies() 從資料庫中取出所有的 Movie 執行個體,這裡沒有例行的事務控制。EJB的方法會預設管理事務。TomEE 也已經為你省下功夫。

這個簡單的 bean 提供了與資料庫互動的 API。現在,我們可以用它了! 讓我們來看一下 moviefun's user 接口。web 前端與這個 EJB 互動有很多方法,比如可以用 JSF ManagedBean 調用,或者其它 MVC 架構調用。為簡單起見,本例使用一個 servlet 和這個 EJB 通訊,然後将結果轉給 JSP 頁面。

正如你所料, TomEE 以 Tomcat 7 為核心, 支援 Servlet 3.0 spec。 這允許我們建立一個類,來繼承 javax.servlet.http.HttpServlet ,并标注 anotation @WebServlet。Servlets 和 managed bean  都可以給标注了 @EJB annotation 的字段注入值。 CDI beans 則通過@Inject annotation 。TomEE 同樣支援@Inject 構造注入,該特性已加入到 JaveEE 7 中了。

Listing 4: Servlet with session bean injected 

@WebServlet("/moviefun/*")
        public class ActionServlet extends HttpServlet {
                private static final long serialVersionUID = -5832176047021911038L;

                @EJB
                private MoviesBean moviesBean;

                @Override
                protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
                                List<Movie> range = moviesBean.getMovies();
                                request.setAttribute("movies", movies);
                        }

                        request.getRequestDispatcher("WEB-INF/moviefun.jsp").forward(request, response);
                }
        }
           

 我們可以用一個簡單的 JSP 來展示資料

Listing 5: JSP to render movies 

<div>
                <table>
                        <thead>
                                <tr>
                                        <th>Title</th>
                                        <th>Director</th>
                                        <th>Genre</th>
                                        <th>Rating</th>
                                        <th>Year</th>
                                </tr>
                        </thead>
                        <tbody>
                                <c:forEach items="${movies}" var="movie">
                                        <tr>
                                                <td><c:out value="${movie.title}" /></td>
                                                <td><c:out value="${movie.director}" /></td>
                                                <td><c:out value="${movie.genre}" /></td>
                                                <td><c:out value="${movie.rating}" /></td>
                                                <td><c:out value="${movie.year}" /></td>
                                        </tr>
                                </c:forEach>
                        </tbody>
                </table>
        </div>
           

 OK,有了上面三個類和一個 JSP ,就可以開始了,另外,得再配置一個檔案,META-INF/persistence.xml, 提供持久單元的基本資訊友善注入EJB。

Listing 6: Persistence.xml 

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
          <persistence-unit name="movie-unit">
            <jta-data-source>movieDatabase</jta-data-source>
            <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
            <class>org.superbiz.moviefun.Movie</class>

            <properties>
              <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
            </properties>
          </persistence-unit>
        </persistence>
           

檔案定義了  @Entity 類 org.superbiz.moviefun.Movie ,指定了OpenJPA 自動建立資料庫腳本schema, 要是資料庫不存在對應的表。

部署應用

将此子產品添加到伺服器,啟動伺服器後,可以看到應用成功啟動。URL中應用的位址取決于 .war 包名 或 Eclipse下項目名,假設為 example, 則釋出到 http://localhost:8080/example/

TomEE 入門指導

瞧, 不用EARs!

你可以看到所有的東西都在一個子產品裡,被打包成單一的 WAR 檔案,不用EJB 建構 EAR 檔案,這一特性源于 TomEE 。 TomEE 在幾年前就有了,如今為 JavaEE 所吸收。這是 TomEE 給 Java EE 所作的最重要貢獻之一。

所有記憶體都是你的!

值得指出的一點是,TomEE 以預設的記憶體參數運作 - 跑在我的 Mac 64bit server JDK 1.6 上,預設最大是128MB。

TomEE 實際上是基于Amazon EC2 微執行個體标準,其任意一個隻要613MB 的RAM空間--在現在的水準這不算多。但用 TomEE 作為你的應用伺服器,那613Mb 中大部分都可以供你的應用使用。這為你的應用留下了足夠的記憶體空間。我們曾經在一個隻有256MB RAM 的 Raspberry Pi 機器運作 TomEE 和 moviefun 執行個體,TomEE 運作 moviefun 例子隻用了約其中30Mb。那個隻要 35 美元的成本,誰說 Java EE 笨重或花費昂貴來着?

TomEE 入門指導

資料庫配置

你可能已經注意到我們使用和部署了一個使用資料庫的應用,然而在 TomEE 中未作任何實際配置。若是在 Eclipse 中重新開機 TomEE 服務, 你可以看到所有的應用資料都已持久化了。那麼資料到底存到了哪裡?資料源又是如何配置的?

TomEE 使用了一個單一的XML配置檔案,conf/目錄下的 tomee.xml 。你可以看到與預設的 EJB pools 、資料源、資源擴充卡等設定有所不同。文法與你所見的其它應用的 XML配置檔案也有差别。它的配置風格是基于Apache httpd 服務,保持盡可能的簡單易讀。比如時間設定,不是指定用毫秒,可以表達成任一時間機關的組合,如"1 hour and 10 minutes and 30 seconds"。

預設的資料源可以如下代碼段添加到 tomee.xml 中。

Listing 7: Configuring a datasource in tomee.xml 

<Resource id="movieDatabase" type="DataSource">
          JdbcDriver com.mysql.jdbc.Driver
          JdbcUrl jdbc:mysql://localhost:3306/moviefun
          UserName username
          Password password
          JtaManaged true
        </Resource>
           

在檔案中指定你資料庫的JdbcDriver,JdbcUrl, UserName 和 Password,同時需要将 JDBC 驅動 jar 添加到 TomEE/lib 目錄。

其中 Resource ID 要比對 persistence.xml 檔案中定義的<jta-data-source> 或<non-jta-data-source> 。 若在 tomee.xml 中沒有找到相比對的資源,則使用預設的資料庫,正像上面的例子,預設的資料庫是一個基于HSQLDB執行個體的檔案,位于 data/ 目錄。該檔案也可以被配置成 JMS 隊列和主題,和其它任一可供應用使用的資源形式。

配置也可以通過系統屬性設定,上例 example 的資料源像下面那樣以 JAVA_OPTS 參數指定:

-DmovieDatabase.JdbcDriver=com.mysql.jdbc.Driver

 -DmovieDatabase.JdbcUrl=jdbc:mysql://localhost:3306/moviefun

-DmovieDatabase.UserName=username -DmovieDatabase.Password=password

或者,可以添加到 conf/system.properties 檔案中。更多資訊可以參考 TomEE website 。

安全性

TomEE 完全內建了 Java EE 的安全性,無縫、一緻地運作于 web 層,EJBs 和 webservices 端。添加一個應用和任何一個 定制的Tomcat Realms 的實作都相當簡單, 如 JDBC,LDAP 或 MongoDB 支援的 Realms, 不作任何修改,都可以運作在 TomEE 中。另外,也支援用 JAAS conf/目錄下login.config定制的安全子產品。可以通過以下步驟給 moviefun 示例 添加 基本的 HTTP 安全驗證。 在 tomcat-users.xml 中定義一個 user 和 role:

<user username="movies" password="movies" roles="moviefun"/>

在 web.xml 中添加一些安全配置,如下:

Listing 8: web.xml security configuration 

<login-config>
                <auth-method>BASIC</auth-method>
                <realm-name>UserDatabase</realm-name>
        </login-config>

        <security-role>
                <role-name>moviefun</role-name>
        </security-role>

        <security-constraint>
                <web-resource-collection>
                        <web-resource-name>Everything</web-resource-name>
                        <url-pattern>/*</url-pattern>
                </web-resource-collection>
                <auth-constraint>
                        <role-name>moviefun</role-name>
                </auth-constraint>
                <user-data-constraint>
                        <transport-guarantee>NONE</transport-guarantee>
                </user-data-constraint>
        </security-constraint>
           

最後為 MoviesBean 類 添加 @RolesDeclared 和 @RolesAllowed anotation。或者添加在一個你想授權通路的單一方法上。如下

Listing 9: adding roles to session bean 

@Stateless
        @DeclareRoles(value = { "moviefun" })
        public class MoviesBean {

                @RolesAllowed(value = { "moviefun" })
                public List<Movie> findAll(int firstResult, int maxResults) {
                        ...
                }
        }
           

 以上配置,通路應用裡的任何頁面,都需提供驗證,使用者名和密碼通過tomcat 的 UserDatabase realm 的 tomcat-users.xml 檢驗。最後, TomEE 将登入規則和相關權限傳遞給 EJB。隻有授權的使用者方可調用 EJB 的方法。遠端用戶端調用 EJB 的方法同樣需要使用者名和密碼校驗。

作者資訊

Jon 是一個開源和Java EE的愛好者,任職于英國 Weatherbys Ltd公司。作為開源的使用者和貢獻者,在過去的四年裡, Jon 送出了 Apache TomEE and OpenEJB 項目, 并緻力于多種不同的特性,包括早期內建 Tomcat 7 到TomEE 中,  EJB 3.1 compliance, TomEE Arquillian adapters 和 OpenEJB Eclipse 插件的部分工作.  當為 Apache TomEE 孜孜不倦,夜以繼日地工作的同時, Jon 同樣享受着生活,喜歡烹饪, 愛看Formula One 賽車, 偶爾還打打高爾夫球。

該文章發表于 JAX Magazine:TomEE - 可以這裡下載下傳。

翻譯不當之處,可檢視原文。 或參考 開源中國的另一翻譯版本。

感謝你的關注,願你至少能夠以陪伴電腦一樣長的時間來陪伴你的親人和朋友。願你和你的親朋健康快樂!