今天的文章将向您展示如何使用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服務來重新整理清單,并監視網格資料以重新整理視圖。 這是最終結果:

下一步:
對于與這些系列相關的以下文章,我打算:
- 實施過濾
- 實施細節視圖
- 實施下一個/上一個浏覽
- 在雲端部署
- 管理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