Java EE—最輕量級的企業框架?

確保高效發展進程的建議java

好久之前,J2EE,特別是應用程序服務器被認爲過於臃腫和「重量級」。對於開發人員來講,使用此技術開發應用程序會很是繁瑣且使人沮喪。可是,因爲 J2EE 框架的名稱已更改成Java EE,所以該假設再也不適用。 Java EE 與其餘企業框架相比區別在哪以及框架輕量級的標準是什麼?git

在選擇技術時,須要考慮的最重要方面之一是開發人員在開發過程當中的生產力。工程師應該花費盡量多的時間來實現用例和創收功能,由於這將使公司朝着目標前進。github

所選擇的技術和方法應該最大限度地縮短開發人員的時間。具體哪些時間呢:等待構建,測試和部署; 配置應用; 實施與業務用例無關的管道; 並配置構建環境和外部依賴項。 可是大多數可用技術都沒有這樣作。web

1.爲何標準?

與其餘框架相比,Java EE 的最大優點之一是使用的API的標準化。標準聽起來可能很無聊並且不夠創新 - 從本質上講,這是真的,由於Java規範請求(JSR)已經成爲行業內過去已通過充分證實的結果。 但使用這些標準有幾個優勢。apache

2.整合規範

Java EE中的特定API - 例如上下文和依賴注入(CDI),JAX-RS,JSON 處理(JSR 353)和 Bean驗證 - 能夠很好地協同工做,而且能夠無縫地相互組合。 最重要的是,CDI 被用做應用程序組件之間的「粘合劑」。 該規範包含諸如*「若是容器支持規範 A 和 B,那麼 A 必須與 B 無縫集成並良好地工做。」*json

例如,JAX-RS 支持 JSONP 類型,例如JsonObject用做請求或響應實體,它支持調用Bean 校驗功能 - 若是驗證失敗,則包括正確的HTTP狀態代碼(參見清單1)。api

@Path("duke") 
public class DukeResource {           
    @GET          
    public JsonObject getDuke() {                   
        return Json.createObjectBuilder().add("name", "Duke").build();         
    }     
    @POST         
    public void create(@Valid @NotPlayedYet Game game) {    
                // game object has been validated at this point         
    }
}

清單1. JAX-RS的JSONP和Bean Validation集成瀏覽器

使用 JSONP 類型意味着內容類型將是 application / json,而且若是驗證失敗,將發送HTTP狀態代碼 400 Bad Request。 這無需編寫任何配置代碼就能使一切都完成。服務器

另外一個例子是 CDI 使開發人員可以經過 @Inject 將任何 bean 和用戶定義的對象注入 Java EE託管組件。 請參閱清單2,瞭解一個 bean 驗證 Validator,它直接使用另外一個 CDI 託管bean。架構

public class GameNotPlayedValidator implements ConstraintValidator<notplayedyet, game> {          
    @Inject          
    GameHistory history;          
    public void initialize(NotPlayedYet constraint) {                 
        // no initialization needed         
    }      

    public boolean isValid(Game game, ConstraintValidatorContext context) {                   
        return !history.exists(game);        
    }
}

清單2. bean 驗證的 CDI 集成

集成是規範的一個主要方面,能夠提供直接的開發人員體驗。開發人員能夠依賴應用程序服務器進行集成和配置工做,從而能夠專一於應用程序的業務邏輯。

3.按配置約定驅動開發

因爲 Java EE 的配置約定驅動方法,大多數實際應用程序不須要大量配置。 繁瑣的 XML 描述符的日子結束了。 對於簡單的 Java EE 應用程序,您不須要單個 XML 文件。

因爲聲明性註釋,一個簡單的帶註釋的普通舊 Java 對象(POJO)處理 HTTP 請求(@Path),或分別做爲 Enterprise JavaBeans(EJB)bean(@ Stateless) - 包括事務,監視或攔截器。過去,這些方法已在各類框架中獲得很好的證實,並已在 Java EE 中進行了標準化。

若是須要,XML 描述符仍可用於部署時配置,可是配置約定有助於最大限度地提升開發人員的工做效率。

4.外部依賴

少數實際企業項目在部署工件中沒有任何額外依賴項的狀況下工做。 但這些依賴關係的理由主要是由技術驅動 - 例如包括日誌記錄或實體映射框架或 Apache Commons 或 Google Guava 等經常使用庫 - 而不是用例。

Java EE 7 - 尤爲是與 Java 8 一塊兒使用時 - 具備足夠的功能來覆蓋大多數用例而沒有任何其餘依賴性。開箱即用的內容大部分均可以用最少許的代碼來實現,例如,經過 CDI 提供商的可注入配置,經過攔截器的斷路器(查看 Adam Bien 的開源庫),或經過複雜的收集操做 Java 8 lambda 表達式和流。

固然,你能夠爭辯說不要在這裏從新發明輪子。 但實際上,爲了節省一些自編寫的代碼行,將兆字節的外部依賴項包含在部署工件中並無多大意義。

經驗代表,最大的問題不是直接引入的依賴,而是傳遞的依賴。傳遞的依賴常常與應用程序服務器上已有的庫版本衝突,並致使具備挑戰性的衝突。在一天的工做時間內,開發人員要花費更多時間來管理這些衝突,而不是聚焦在將小功能實現到項目中所需的時間。這主要適用於具備技術驅動而非用例驅動的依賴關係的狀況。

有關簡單的 Java EE 7 項目Maven項目對象模型(POM)的文件啓發,請參閱清單 3,該文檔受Adam Bien的啓發 Java EE 7 Essentials Archetype.

<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.sebastian-daschner</groupid>     
 <artifactid>game-of-duke</artifactid>     
 <version>1.0-SNAPSHOT</version>     
 <packaging>war</packaging>      

 <dependencies>         
     <dependency>             
          <groupid>javax</groupid>             
          <artifactid>javaee-api</artifactid>             
          <version>7.0</version>             
          <scope>provided</scope>         
     </dependency>     
 </dependencies>      

 <build>         
     <finalname>game-of-duke</finalname>     
 </build>      

 <properties>         
     <maven.compiler.source>1.8</maven.compiler.source>         
     <maven.compiler.target>1.8</maven.compiler.target>         
     <failonmissingwebxml>false</failonmissingwebxml>         
     <project.build.sourceencoding>UTF-8</project.build.sourceencoding>     
     </properties> 
</project>

清單3. Java EE 7 Maven POM 文件

固然,有時應用程序確實須要集成對於實現軟件目標相當重要的庫。可是,這些依賴關係須要經過業務需求來證實。通常來講,它頗有意義,能夠節省時間和精力來最小化外部生產庫。

對於測試依賴關係,這是一個不一樣的故事,由於庫,例如JUnit,Mockito或者在某些狀況下,Arquillian - 是相當重要的。 但一樣,關注測試依賴項列表也是有意義的。

5.精簡部署 Artifacts

因爲應用程序服務器知道Java EE API,所以該API沒必要包含在部署 artifact 中。 只包含業務邏輯 - 只需最少的膠水代碼和交叉關注點。

所以,這些千字節大小的工件可使構建時間很是短,由於構建過程不須要複製不少東西。這能夠在每一個構建上產生幾秒鐘的差別。 若是總結開發人員和持續集成(CI)服務器所花費的全部額外時間,那就會產生很大的不一樣。項目建設的頻率越高 - 對於持續交付(CD)情景尤爲如此 - 影響越大。

除了較短的構建時間外,小型部署 artifacts 還可確保較短的發佈和部署時間。 因爲實現已經包含在運行時中,因此在全部狀況下,移動部件花費的時間都是最小的。

6.Docker的理想框架

這正是Java EE成爲Docker等容器技術的完美框架的緣由。Docker 鏡像基於圖層,構建圖像時,基本圖像已包含操做系統,Java運行時和應用程序。所以,在每一個構建中添加的惟一內容是部署工件的最後一個千字節薄層。與胖WAR或獨立JAR方法相比,這節省了時間和存儲 - 不只在每一個構建上,並且在圖像版本化或發佈版本時 。

不管在哪一個階段,擁有精簡的部署 artifacts 均可以實現很是快速和高效的部署管道。

7.現代應用服務器

J2EE 應用程序服務器是重量級軟件在啓動和部署時間,安裝大小和資源佔用空間方面的體現。 可是在 Java EE 的新世界中,這已再也不適用。

全部現代Java EE 7應用程序服務器(如WildFly,Payara,WebSphere Liberty,Profile和TomEE)均可在幾秒鐘內啓動和部署。因爲內部,全面的模塊化,他們只能加載所需的組件並儘快部署精簡的應用程序 artifacts。

如今的安裝尺寸和佔地面積很是合理。 應用程序服務器不會消耗比簡單的 servlet 容器更多的東西,但它具備完整的 Java EE 功能。 有趣的是,如今運行的瀏覽器實例消耗更多內存。

話雖如此,每一個服務器只部署一個應用程序是可能的,也能夠是合理的 - 不管是在容器中仍是在內部。 經過「每一個容器每一個應用程序服務器一個應用程序」方法,您能夠爲現代微服務架構提供高效且靈活的解決方案。

8.打包

在打包過程當中,不該該繼續使用EAR文件了。將整個應用程序部署在獨立的專門的服務器上,要求咱們在那個環境中必須能夠訪問全部的組件方法,這樣作能夠節省更多的構建和部署時間。除此以外,這還避免了EAR文件傾向於致使的類加載層次結構問題。

在大多數雲和微服務部署中,使用獨立的JAR包。 它們包含應用程序和運行時實現。 在Java EE領域,這種方法可使用特定於供應商的工具鏈來實現,例如 WildFly Swarm,Payara Micro 或TomEE Embedded。

可是,因爲上述緣由,我強烈建議儘量將業務邏輯與運行時分開。 這意味着將應用程序打包在僅包含應用程序代碼的WAR文件中。

在我看來,若是因爲公司「政治」問題而不是技術緣由而沒法控制安裝或操做流程,則獨立 JAR 文件是一種有用的解決方法。 而後運送部署工件中所需的全部內容而且只須要 JRE 時能夠解決至關多的非技術問題。

9.關於高效研發進程的建議

企業項目最有效的解決方案之一以下:

  • 僅在提供 API 時使用 Java EE 7 和 Java 8
  • 構建一個千字節大小的 WAR 文件,其中僅包含業務邏輯和最小管道(例如 JAX-RS 資源或JPA)
  • 構建 Docker 鏡像 - 僅將 WAR 文件添加到包含已配置的應用程序服務器的基礎鏡像
  • 經過使用容器部署應用程序的 CD 管道進行傳送

10.結論

「重量級 Java EE」的日子確定結束了。 Java EE 中包含的 API 提供了高效且愉快的開發人員體驗以及標準內的無縫集成。 特別是,將應用程序代碼與運行時分離的方法可實現快速,高效的開發過程。

經過由多個供應商發起的新MicroProfile計劃,未來可能會進一步縮小Java EE所需的組件。

參考資料

> 原文:https://community.oracle.com/docs/DOC-1008823 > > 做者:Sebastian Daschner > > 譯者:[KeepGoingPawn](https://blog.csdn.net/hengji666

9月福利,關注公衆號 ​ 後臺回覆:004,領取8月翻譯集錦! ​ 往期福利回覆:001,002, 003便可領取!

img</notplayedyet,>

相關文章
相關標籤/搜索