天天看點

帶有Angular JS的Java EE 7 –第1部分

今天的文章将向您展示如何使用Java EE 7和Angular JS建構非常簡單的應用程式。 在去那裡之前,讓我告訴您一個簡短的故事:

我不得不承認,我從來都不是Java語言的忠實擁護者,但是我仍然記得我第一次使用它。 我不記得确切的年份,但大概是90年代中期。 我的頁面上有3幀(是的幀!還記得嗎?那段時間很受歡迎),當我單擊第3幀上的連結時,我想重新加載2幀。 當時,Javascript被用來在網頁上做一些花哨的事情,并不是每個浏覽器都支援Javascript,甚至有些浏覽器甚至要求您打開它。 快速發展到今天,景觀發生了巨大變化。 Javascript現在是完整的開發堆棧,您可以開發僅使用Javascript編寫的整個應用程式。 對于我來說不幸的是,有時我仍然認為我回到了90年代,并且對Javascript的評價不高,是以這是我嘗試更好地了解Javascript的嘗試。

為什麼選擇Java EE 7?

好吧,我喜歡Java,而新的Java EE版本非常不錯。 使用Wildfly或Glassfish時 不會太詳細,速度很快。 它為您提供了滿足您需求的大量規範,這是Java世界的标準。

為什麼選擇Angular JS?

我可能在這裡關注有關Angular的大肆宣傳。 由于我對Javascript的經驗不足,是以我不太了解這些提議,是以我隻是聽從一些朋友的建議,并且我也注意到上一個Devoxx對Angular的廣泛接受。 每個進行Angular演講的房間都坐滿了,是以我想嘗試一下,自己找個機會。

應用程式

對于應用程式,這是一個帶有分頁的簡單清單,以及一個提供清單資料的REST服務。 每次我開始一個新的企業項目時,通常通常是我們編寫代碼的第一件事:建立表,存儲一些資料并列出一些随機資料,是以我認為這是适當的。

設定

  • Java EE 7
  • 角JS
  • ng-grid
  • UI引導程式
  • 野蠅

代碼(最終!)

後端– Java EE 7

從後端開始,讓我們定義一個非常簡單的Entity類(為簡單起見,省略了一些代碼):

人.java

@Entity
public class Person {
    @Id
    private Long id;

    private String name;

    private String description;

}
           

如果您不熟悉Java EE JPA規範,則可以通過使用注釋

@Entity

連接配接到具有相同名稱的資料庫表和使用注釋

@Id

辨別表主資料庫來将對象類模組化到資料庫表中鍵。

接下來是

persistence.xml

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="myPU" transaction-type="JTA">
        <properties>
            <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
            <property name="javax.persistence.schema-generation.create-source" value="script"/>
            <property name="javax.persistence.schema-generation.drop-source" value="script"/>
            <property name="javax.persistence.schema-generation.create-script-source" value="sql/create.sql"/>
            <property name="javax.persistence.schema-generation.drop-script-source" value="sql/drop.sql"/>
            <property name="javax.persistence.sql-load-script-source" value="sql/load.sql"/>
        </properties>
    </persistence-unit>
</persistence>
           

我在Java EE 7上最喜歡的兩個新功能:現在,您可以使用屬性

javax.persistence.schema-generation.*

以标準方式運作sql,并且如果您不提供預設資料源,它還将您綁定到預設資料源。 是以,對于這種情況,它将為我們的應用程式使用内部Wildfly H2資料庫。

最後,要提供清單資料,我們需要查詢資料庫并将其公開為REST服務:

PersonResource.java

@Stateless
@ApplicationPath("/resources")
@Path("persons")
public class PersonResource extends Application {
    @PersistenceContext
    private EntityManager entityManager;

    private Integer countPersons() {
        Query query = entityManager.createQuery("SELECT COUNT(p.id) FROM Person p");
        return ((Long) query.getSingleResult()).intValue();
    }

    @SuppressWarnings("unchecked")
    private List<Person> findPersons(int startPosition, int maxResults, String sortFields, String sortDirections) {
        Query query = entityManager.createQuery("SELECT p FROM Person p ORDER BY " + sortFields + " " + sortDirections);
        query.setFirstResult(startPosition);
        query.setMaxResults(maxResults);
        return query.getResultList();
    }

    public PaginatedListWrapper<Person> findPersons(PaginatedListWrapper<Person> wrapper) {
        wrapper.setTotalResults(countPersons());
        int start = (wrapper.getCurrentPage() - 1) * wrapper.getPageSize();
        wrapper.setList(findPersons(start,
                                    wrapper.getPageSize(),
                                    wrapper.getSortFields(),
                                    wrapper.getSortDirections()));
        return wrapper;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public PaginatedListWrapper<Person> listPersons(@DefaultValue("1")
                                                    @QueryParam("page")
                                                    Integer page,
                                                    @DefaultValue("id")
                                                    @QueryParam("sortFields")
                                                    String sortFields,
                                                    @DefaultValue("asc")
                                                    @QueryParam("sortDirections")
                                                    String sortDirections) {
        PaginatedListWrapper<Person> paginatedListWrapper = new PaginatedListWrapper<>();
        paginatedListWrapper.setCurrentPage(page);
        paginatedListWrapper.setSortFields(sortFields);
        paginatedListWrapper.setSortDirections(sortDirections);
        paginatedListWrapper.setPageSize(5);
        return findPersons(paginatedListWrapper);
    }
}
           

該代碼與普通的Java POJO完全相同,但是使用Java EE批注來增強行為。

@ApplicationPath("/resources")

@Path("persons")

将在url

yourdomain/resources/persons

處公開REST服務,

@GET

标記将由http GET方法和

@Produces(MediaType.APPLICATION_JSON)

調用)的邏輯

@Produces(MediaType.APPLICATION_JSON)

将REST響應格式化為JSON格式。 隻需幾個注釋就可以了。

為了使為分頁清單交換所需的資訊更加容易,我還建立了以下包裝器類:

PaginatedListWrapper.java

public class PaginatedListWrapper<T> {
    private Integer currentPage;
    private Integer pageSize;
    private Integer totalResults;

    private String sortFields;
    private String sortDirections;
    private List<T> list;
}
           

我們已經完成了後端工作。

UI – Angular JS

為了顯示資料,我們将使用Angular JS。 Angular通過附加的自定義标簽屬性擴充了傳統HTML,以遵循MVC方法綁定Javascript變量中表示的資料。 是以,讓我們看一下我們的html頁面:

index.html

<!DOCTYPE html>
<!-- Declares the root element that allows behaviour to be modified through Angular custom HTML tags. -->
<html ng-app="persons">
<head>
    <title></title>
    <script src="lib/angular.min.js"></script>
    <script src="lib/jquery-1.9.1.js"></script>
    <script src="lib/ui-bootstrap-0.10.0.min.js"></script>
    <script src="lib/ng-grid.min.js"></script>

    <script src="script/person.js"></script>

    <link rel="stylesheet" type="text/css" href="lib/bootstrap.min.css" target="_blank" rel="external nofollow" />
    <link rel="stylesheet" type="text/css" href="lib/ng-grid.min.css" target="_blank" rel="external nofollow" />
    <link rel="stylesheet" type="text/css" href="css/style.css" target="_blank" rel="external nofollow" />
</head>

<body>

<br>

<div class="grid">
    <!-- Specify a JavaScript controller script that binds Javascript variables to the HTML.-->
    <div ng-controller="personsList">
        <!-- Binds the grid component to be displayed. -->
        <div class="gridStyle" ng-grid="gridOptions"></div>

        <!--  Bind the pagination component to be displayed. -->
        <pagination direction-links="true" boundary-links="true"
                    total-items="persons.totalResults" page="persons.currentPage" items-per-page="persons.pageSize"
                    on-select-page="refreshGrid(page)">
        </pagination>
    </div>
</div>

</body>
</html>
           

除了Javascript和CSS聲明外,其中幾乎沒有代碼。 非常令人印象深刻。 Angular也有大量現成的元件,是以我使用ng-grid來顯示資料和提供分頁元件的UI Bootstrap 。 ng-grid也具有分頁元件,但是我更喜歡UI Bootstrap分頁元件。

仍然缺少一些東西。 一切發生的Javascript檔案:

person.js

var app = angular.module('persons', ['ngGrid', 'ui.bootstrap']);
// Create a controller with name personsList to bind to the html page.
app.controller('personsList', function ($scope, $http) {
    // Makes the REST request to get the data to populate the grid.
    $scope.refreshGrid = function (page) {
        $http({
            url: 'resources/persons',
            method: 'GET',
            params: {
                page: page,
                sortFields: $scope.sortInfo.fields[0],
                sortDirections: $scope.sortInfo.directions[0]
            }
        }).success(function (data) {
            $scope.persons = data;
        });
    };

    // Do something when the grid is sorted.
    // The grid throws the ngGridEventSorted that gets picked up here and assigns the sortInfo to the scope.
    // This will allow to watch the sortInfo in the scope for changed and refresh the grid.
    $scope.$on('ngGridEventSorted', function (event, sortInfo) {
        $scope.sortInfo = sortInfo;
    });

    // Watch the sortInfo variable. If changes are detected than we need to refresh the grid.
    // This also works for the first page access, since we assign the initial sorting in the initialize section.
    $scope.$watch('sortInfo', function () {
        $scope.refreshGrid($scope.persons.currentPage);
    }, true);

    // Initialize required information: sorting, the first page to show and the grid options.
    $scope.sortInfo = {fields: ['id'], directions: ['asc']};
    $scope.persons = {currentPage : 1};
    $scope.gridOptions = {
        data: 'persons.list',
        useExternalSorting: true,
        sortInfo: $scope.sortInfo
    };
});
           

Javascript代碼非常幹淨且井井有條。 請注意如何将所有内容添加到應用程式控制器中,進而使您可以将業務邏輯上的關注點多重分離。 為了實作所需的行為,我們隻需要添加一些函數即可通過調用REST服務來重新整理清單,并監視網格資料以重新整理視圖。 這是最終結果:

帶有Angular JS的Java EE 7 –第1部分

下一步:

對于與這些系列相關的以下文章,我打算:

  • 實施過濾
  • 實施細節視圖
  • 實施下一個/上一個浏覽
  • 在雲端部署
  • 管理Javascript依賴項

資源資源

您可以從我的github存儲庫中克隆完整的工作副本,然後将其部署到Wildfly。 您可以在此處找到說明進行部署。 也應該在Glassfish上工作。

Java EE – Angular JS源

更新資料

同時,我用有關“ 管理Javascript依賴項”的文章更新了原始代碼。 請從1.0版中下載下傳此文章的原始源。 您還可以克隆存儲庫,并使用以下指令從發行版1.0中檢出标記:

git checkout 1.0

希望您喜歡這個文章! 讓我知道您是否對此有任何評論。

翻譯自: https://www.javacodegeeks.com/2014/07/java-ee-7-with-angular-js-part-1.html