Java >> Java Tutorial >  >> Java

Java EE 7 mit Angular JS – Teil 1

Der heutige Beitrag zeigt Ihnen, wie Sie eine sehr einfache Anwendung mit Java EE 7 und Angular JS erstellen. Bevor ich dorthin gehe, möchte ich Ihnen eine kurze Geschichte erzählen:

Ich muss gestehen, dass ich nie ein großer Fan von Javascript war, aber ich erinnere mich noch an das erste Mal, als ich es benutzt habe. Ich erinnere mich nicht genau an das Jahr, aber wahrscheinlich Mitte der 90er Jahre. Ich hatte eine Seite mit 3 Frames (ja, Frames! Erinnern Sie sich an die? Damals sehr beliebt) und ich wollte 2 Frames neu laden, als ich auf einen Link im 3. Frame klickte. Zu der Zeit wurde Javascript verwendet, um einige ausgefallene Dinge auf Webseiten zu machen, nicht jeder Browser unterstützt Javascript und einige verlangten sogar, dass Sie es einschalten. Schneller Vorlauf bis heute hat sich die Landschaft dramatisch verändert. Javascript ist jetzt ein vollständiger Entwicklungsstack und Sie können ganze Anwendungen entwickeln, die nur in Javascript geschrieben sind. Leider denke ich manchmal immer noch, ich bin zurück in den 90ern und traue Javascript nicht genug zu, deshalb ist dies mein Versuch, Javascript besser kennenzulernen.

Warum Java EE 7?

Nun, ich mag Java und die neue Java EE-Version ist ziemlich gut. Weniger ausführlich und sehr schnell mit Wildfly oder Glassfish. Es bietet Ihnen eine große Auswahl an Spezifikationen für Ihre Anforderungen und ist ein Standard in der Java-Welt.

Warum Angular JS?

Wahrscheinlich verfolge ich hier den großen Hype um Angular. Da ich wenig Erfahrung mit Javascript habe kenne ich die Angebote nicht so gut, daher folge ich nur dem Rat einiger Freunde und habe auch im letzten Devoxx eine große Akzeptanz von Angular festgestellt. Jeder Raum mit einem Angular-Vortrag war voll, also wollte ich es versuchen und es selbst herausfinden.

Die Anwendung

Für die Anwendung ist es eine einfache Liste mit Paginierung und einem REST-Dienst, der die Listendaten speist. Jedes Mal, wenn ich ein neues Unternehmensprojekt starte, ist es normalerweise das Erste, was wir programmieren:eine Tabelle erstellen, einige Daten speichern und einige zufällige Daten auflisten, also denke ich, dass es angemessen ist.

Die Einrichtung

  • JavaEE 7
  • Angular JS
  • ng-grid
  • UI-Bootstrap
  • Wildfliege

Der Kodex (endlich!)

Backend – Java EE 7

Beginnen wir mit dem Backend und definieren wir eine sehr einfache Entity-Klasse (einige Codes werden der Einfachheit halber weggelassen):

Person.java

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

    private String name;

    private String description;

}

Wenn Sie mit der Java EE JPA-Spezifikation nicht vertraut sind, können Sie eine Objektklasse mithilfe der Annotation @Entity in eine Datenbanktabelle modellieren um sich mit der gleichnamigen Datenbanktabelle und der Annotation @Id zu verbinden um den Primärschlüssel der Tabelle zu identifizieren.

Gefolgt von einem persistence.xml :

persistenz.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>

Zwei meiner liebsten neuen Funktionen in Java EE 7:Jetzt können Sie SQL auf standardmäßige Weise ausführen, indem Sie die Eigenschaften javax.persistence.schema-generation.* verwenden und es bindet Sie auch an eine Standarddatenquelle, wenn Sie keine angeben. In diesem Fall wird also die interne Wildfly H2-Datenbank für unsere Anwendung verwendet.

Um schließlich die Listendaten bereitzustellen, müssen wir die Datenbank abfragen und als REST-Dienst verfügbar machen:

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);
    }
}

Der Code ist genau wie ein normales Java-POJO, verwendet jedoch die Java EE-Anmerkungen, um das Verhalten zu verbessern. @ApplicationPath("/resources") und @Path("persons") stellt den REST-Dienst unter der URL yourdomain/resources/persons bereit , @GET markiert die von der http GET-Methode aufzurufende Logik und @Produces(MediaType.APPLICATION_JSON) formatiert die REST-Antwort im JSON-Format. Ziemlich cool mit nur wenigen Anmerkungen.

Um es etwas einfacher zu machen, die benötigten Informationen für die paginierte Liste auszutauschen, habe ich auch die folgende Wrapper-Klasse erstellt:

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;
}

Und wir sind mit dem Backend-Zeug fertig.

UI – Angular JS

Um die Daten anzuzeigen, verwenden wir Angular JS. Angular erweitert das traditionelle HTML mit zusätzlichen benutzerdefinierten Tag-Attributen, um Daten zu binden, die in Javascript-Variablen dargestellt werden, indem es einem MVC-Ansatz folgt. Schauen wir uns also unsere HTML-Seite an:

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"/>
    <link rel="stylesheet" type="text/css" href="lib/ng-grid.min.css"/>
    <link rel="stylesheet" type="text/css" href="css/style.css"/>
</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>

Abgesehen von den Javascript- und CSS-Deklarationen ist dort nur sehr wenig Code enthalten. Sehr beeindruckend. Angular hat auch eine große Auswahl an gebrauchsfertigen Komponenten, daher verwende ich das ng-Grid, um die Daten anzuzeigen, und UI Bootstrap, das eine Paginierungskomponente bereitstellt. Das ng-Grid hat auch eine Paginierungskomponente, aber ich mochte die UI Bootstrap-Paginierungskomponente mehr.

Es fehlt noch etwas. Die Javascript-Datei, in der alles passiert:

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
    };
});

Der Javascript-Code ist sehr sauber und organisiert. Beachten Sie, wie alles zu einem App-Controller hinzugefügt wird, sodass Sie Ihre Geschäftslogik mehrfach trennen können. Um das erforderliche Verhalten zu implementieren, müssen wir nur ein paar Funktionen hinzufügen, um die Liste zu aktualisieren, indem wir unseren REST-Dienst aufrufen und die Rasterdaten überwachen, um die Ansicht zu aktualisieren. Das ist das Endergebnis:

Nächste Schritte:

Für die folgenden Posts, die sich auf diese Serien beziehen, plane ich:

  • Filterung implementieren
  • Detailansicht implementieren
  • Nächstes/Zurück-Browsing implementieren
  • In der Cloud bereitstellen
  • Javascript-Abhängigkeiten verwalten

Ressourcen

Sie können eine vollständige Arbeitskopie aus meinem Github-Repository klonen und auf Wildfly bereitstellen. Dort finden Sie Anweisungen zur Bereitstellung. Sollte auch auf Glassfish funktionieren.

Java EE – Angular JS-Quelle

Aktualisieren

Inzwischen habe ich den Originalcode mit dem Post über Javascript-Abhängigkeiten verwalten aktualisiert. Bitte laden Sie die Originalquelle dieses Beitrags aus der Version 1.0 herunter. Sie können das Repo auch klonen und das Tag aus Version 1.0 mit dem folgenden Befehl auschecken:git checkout 1.0 .

Ich hoffe, dir hat der Beitrag gefallen! Lassen Sie mich wissen, wenn Sie irgendwelche Kommentare dazu haben.

Java-Tag