Beschreiben der Architektur, die Sie für Java-Webanwendungen verwenden. [geschlossen]


146

Lassen Sie uns Java-basierte Webanwendungsarchitekturen teilen!

Es gibt viele verschiedene Architekturen für Webanwendungen, die mit Java implementiert werden sollen. Die Antworten auf diese Frage können als Bibliothek verschiedener Webanwendungsdesigns mit ihren Vor- und Nachteilen dienen. Obwohl mir klar ist, dass die Antworten subjektiv sein werden, versuchen wir, so objektiv wie möglich zu sein und die Vor- und Nachteile zu motivieren, die wir auflisten.

Verwenden Sie die von Ihnen bevorzugte Detailebene zur Beschreibung Ihrer Architektur. Damit Ihre Antwort von Wert ist, müssen Sie zumindest die wichtigsten Technologien und Ideen beschreiben, die in der von Ihnen beschriebenen Architektur verwendet werden. Und zu guter Letzt, wann sollten wir Ihre Architektur verwenden?

Ich fange an ...


Überblick über die Architektur

Wir verwenden eine dreistufige Architektur, die auf offenen Standards von Sun wie Java EE, Java Persistence API, Servlet und Java Server Pages basiert.

  • Beharrlichkeit
  • Unternehmen
  • Präsentation

Die möglichen Kommunikationsflüsse zwischen den Schichten werden dargestellt durch:

Persistence <-> Business <-> Presentation

Dies bedeutet beispielsweise, dass die Präsentationsschicht niemals Persistenzoperationen aufruft oder ausführt, sondern immer über die Geschäftsschicht. Diese Architektur soll die Anforderungen einer hochverfügbaren Webanwendung erfüllen.

Beharrlichkeit

Führt CRUD- Persistenzvorgänge zum Erstellen, Lesen, Aktualisieren und Löschen aus . In unserem Fall verwenden wir ( Java Persistence API ) JPA und verwenden derzeit Hibernate als unseren Persistenzanbieter und verwenden dessen EntityManager .

Diese Schicht ist in mehrere Klassen eingeteilt, wobei jede Klasse beschäftigt sich mit einer bestimmten Art von Einheiten (dh Einheiten zu einem Einkaufswagen im Zusammenhang könnten durch eine einzige Persistenz Klasse behandelt werden) und wird verwendet , um ein und nur ein Manager .

Zusätzlich speichert diese Schicht auch JPA - Entitäten , die Dinge sind wie Account, ShoppingCartusw.

Unternehmen

Die gesamte Logik, die an die Funktionalität der Webanwendung gebunden ist, befindet sich in dieser Schicht. Diese Funktion kann eine Geldüberweisung für einen Kunden initiieren, der ein Produkt online mit seiner Kreditkarte bezahlen möchte. Es könnte genauso gut sein, einen neuen Benutzer zu erstellen, einen Benutzer zu löschen oder das Ergebnis eines Kampfes in einem webbasierten Spiel zu berechnen.

Diese Ebene ist in mehrere Klassen unterteilt, und jede dieser Klassen wird mit @Statelesseinem SLSB ( Stateless Session Bean ) versehen. Jeder SLSB wird als Manager bezeichnet, und beispielsweise kann ein Manager eine Klasse sein, die wie erwähnt mit Anmerkungen versehen ist AccountManager.

Wenn AccountManagerCRUD-Operationen ausgeführt werden müssen, werden die entsprechenden Aufrufe an eine Instanz von ausgeführt AccountManagerPersistence, die eine Klasse in der Persistenzschicht ist. Eine grobe Skizze von zwei Methoden in AccountManagerkönnte sein:

...
public void makeExpiredAccountsInactive() {
    AccountManagerPersistence amp = new AccountManagerPersistence(...)
    // Calls persistence layer
    List<Account> expiredAccounts = amp.getAllExpiredAccounts();
    for(Account account : expiredAccounts) {
        this.makeAccountInactive(account)
    }
}
public void makeAccountInactive(Account account) {
    AccountManagerPersistence amp = new AccountManagerPersistence(...)
    account.deactivate();
    amp.storeUpdatedAccount(account); // Calls persistence layer
}

Wir verwenden Container-Manager-Transaktionen, damit wir keine eigenen Transaktionsabgrenzungen vornehmen müssen. Was im Grunde genommen unter der Haube passiert, ist, dass wir bei der Eingabe der SLSB-Methode eine Transaktion initiieren und diese unmittelbar vor dem Beenden der Methode festschreiben (oder zurücksetzen). Es ist ein Beispiel für eine Konvention über die Konfiguration, aber wir brauchten bisher nur die Standardeinstellung Erforderlich.

So erklärt das Java EE 5-Lernprogramm von Sun das erforderliche Transaktionsattribut für Enterprise JavaBeans (EJBs):

Wenn der Client innerhalb einer Transaktion ausgeführt wird und die Enterprise-Bean-Methode aufruft, wird die Methode innerhalb der Transaktion des Clients ausgeführt. Wenn der Client keiner Transaktion zugeordnet ist, startet der Container eine neue Transaktion, bevor die Methode ausgeführt wird.

Das Attribut Erforderlich ist das implizite Transaktionsattribut für alle Enterprise-Bean-Methoden, die mit einer vom Container verwalteten Transaktionsabgrenzung ausgeführt werden. Normalerweise legen Sie das Attribut Erforderlich nur fest, wenn Sie ein anderes Transaktionsattribut überschreiben müssen. Da Transaktionsattribute deklarativ sind, können Sie sie später problemlos ändern.

Präsentation

Unsere Präsentationsschicht ist verantwortlich für ... Präsentation! Es ist für die Benutzeroberfläche verantwortlich und zeigt dem Benutzer Informationen an, indem es HTML-Seiten erstellt und Benutzereingaben über GET- und POST-Anforderungen empfängt. Wir verwenden derzeit die alte JSP- Kombination ( Servlet + Java Server Pages ).

Die Schicht ruft Methoden in Managern der Geschäftsschicht auf, um vom Benutzer angeforderte Vorgänge auszuführen und Informationen zu erhalten, die auf der Webseite angezeigt werden sollen. Manchmal handelt es sich bei den von der Geschäftsschicht empfangenen Informationen um weniger komplexe Typen wie String's und integers, manchmal um JPA-Entitäten .

Vor- und Nachteile mit der Architektur

Vorteile

  • Wenn wir in dieser Ebene alles haben, was mit einer bestimmten Art der Persistenz zu tun hat, können wir nur von der Verwendung von JPA zu etwas anderem wechseln, ohne etwas in der Business-Ebene neu schreiben zu müssen.
  • Es fällt uns leicht, unsere Präsentationsebene in etwas anderes zu tauschen, und es ist wahrscheinlich, dass wir es tun, wenn wir etwas Besseres finden.
  • Es ist schön, den EJB-Container Transaktionsgrenzen verwalten zu lassen.
  • Die Verwendung von Servlets + JPA ist (zunächst) einfach und die Technologien sind weit verbreitet und auf vielen Servern implementiert.
  • Die Verwendung von Java EE soll es uns erleichtern, ein Hochverfügbarkeitssystem mit Lastausgleich und Failover zu erstellen . Beides haben wir das Gefühl, dass wir es haben müssen.

Nachteile

  • Mit JPA können Sie häufig verwendete Abfragen als benannte Abfragen speichern, indem Sie die @NamedQueryAnnotation für die JPA-Entitätsklasse verwenden. Wenn Sie wie in unserer Architektur so viel wie möglich mit der Persistenz in den Persistenzklassen zu tun haben, werden die Stellen verteilt, an denen Sie möglicherweise Abfragen finden, die auch die JPA-Entitäten einschließen. Es wird schwieriger sein, einen Überblick über Persistenzoperationen zu erhalten, und es wird daher schwieriger sein, diese zu warten.
  • Wir haben JPA-Entitäten als Teil unserer Persistenzschicht. Aber Accountund ShoppingCart, sind sie nicht wirklich Geschäftsobjekte? Dies geschieht auf diese Weise, da Sie diese Klassen berühren und in Entitäten umwandeln müssen, mit denen JPA umgehen kann.
  • Die JPA-Entitäten, die auch unsere Geschäftsobjekte sind, werden wie Datenübertragungsobjekte ( DTOs ) erstellt, die auch als Value Objects (VOs) bezeichnet werden. Dies führt zu einem anämischen Domänenmodell, da die Geschäftsobjekte außer Zugriffsmethoden keine eigene Logik haben. Die gesamte Logik wird von unseren Managern in der Geschäftsschicht ausgeführt, was zu einem prozeduraleren Programmierstil führt. Es ist kein gutes objektorientiertes Design, aber vielleicht ist das kein Problem? (Schließlich ist die Objektorientierung nicht das einzige Programmierparadigma, das Ergebnisse geliefert hat.)
  • Die Verwendung von EJB und Java EE führt zu einer gewissen Komplexität. Und wir können nicht nur Tomcat verwenden (das Hinzufügen eines EJB-Mikrocontainers ist nicht nur Tomcat).
  • Es gibt viele Probleme bei der Verwendung von Servlets + JPA. Verwenden Sie Google, um weitere Informationen zu diesen Problemen zu erhalten.
  • Da die Transaktionen beim Verlassen der Business-Schicht geschlossen werden, können keine Informationen von JPA-Entitäten geladen werden, die so konfiguriert sind, dass sie aus der Datenbank geladen werden, wenn sie fetch=FetchType.LAZYinnerhalb der Präsentationsschicht benötigt (verwendet ) werden. Es wird eine Ausnahme ausgelöst. Bevor wir eine Entität zurückgeben, die diese Art von Feldern enthält, müssen wir sicherstellen, dass wir die entsprechenden Getter aufrufen. Eine andere Möglichkeit besteht darin, Java Persistence Query Language ( JPQL ) zu verwenden und a FETCH JOIN. Beide Optionen sind jedoch etwas umständlich.

1
Es scheint, dass Sie die Messlatte mit Ihrer eigenen Antwort zu hoch gelegt haben - es könnte andere entmutigt haben :)
Jonik

5
Vielleicht sollte Ihre Einstellung auch eine normale Antwort sein, nicht Teil der Frage, damit über sie zusammen mit anderen Antworten abgestimmt werden kann?
Jonik

Diese Frage wurde auf Meta verwiesen .
D4V1D

Antworten:


20

Ok, ich mache eine (kürzere):

  • Frontend: Tapisserie (3 für ältere Projekte, 5 für neuere Projekte)
  • Geschäftsschicht: Frühling
  • DAOs: Ibatis
  • Datenbank: Oracle

Wir verwenden die Sping-Transaktionsunterstützung und starten Transaktionen beim Betreten der Serviceschicht, die bis zu den DAO-Aufrufen weitergegeben werden. Die Service-Schicht verfügt über die meisten Geschäftsmodellkenntnisse, und die DAOs erledigen relativ einfache CRUD-Arbeiten.

Einige kompliziertere Abfragen werden aus Leistungsgründen von komplizierteren Abfragen im Backend behandelt.

Die Verwendung von Spring hat in unserem Fall den Vorteil, dass wir länder- / sprachabhängige Instanzen haben können, die hinter einer Spring Proxy-Klasse stehen. Basierend auf dem Benutzer in der Sitzung wird beim Tätigen des Anrufs die richtige Länder- / Sprachimplementierung verwendet.

Das Transaktionsmanagement ist nahezu transparent, Rollback bei Laufzeitausnahmen. Wir verwenden so oft wie möglich ungeprüfte Ausnahmen. Früher haben wir geprüfte Ausnahmen gemacht, aber mit der Einführung von Spring sehe ich die Vorteile ungeprüfter Ausnahmen, die Ausnahmen nur dann behandeln, wenn Sie können. Es vermeidet eine Menge Boilerplate "Catch / Rethrow" oder "Throws" Zeug.

Sorry, es ist kürzer als dein Beitrag, hoffe du findest das interessant ...


Gute Antwort! Dieser Thread scheint etwas Verkehr anzulocken, schade, dass andere Leute nicht das Gefühl haben, Zeit zu haben, ihre Architekturen zu beschreiben, oder andere Gründe haben, nicht teilzunehmen.

19

Ideale Java-basierte Webentwicklungstechnologien heute.

Webebene:

HTML + CSS + Ajax + JQuery

RESTFul Web Controller / Aktions- / Anforderungsverarbeitungsschicht:

Framework spielen

Geschäftslogik / Serviceschicht:

Verwenden Sie so lange wie möglich reinen Java-Code. Hier kann man Webdienste fusionieren.

XML / JSon-Datentransformationsschicht:

XMLTool (Suche nach Google Code), JSoup, Google GSon, XStream, JOOX (Suche nach Google Code)

Persistenzschicht:

CRUD: JPA oder SienaProject oder QueryDSL / Komplexe Abfragen: JOOQ, QueryDSL


9

Hier sind meine 5 Cent

Präsentation

Android, Angular.JS WebClient, OAUTHv2

API

REST, Jersey (JAX-RS), Jackson (JSON-De- / Serialisierung), DTO-Objekte (anders als Geschäftslogikmodelle)

Geschäftslogik

Feder für DI- und Event-Handling. DDD-artiger Ansatz von Modellobjekten. Länger laufende Jobs werden mit SQS in Worker-Modulen ausgelagert.

DAO

Repository-Modell mit Spring JDBC-Vorlagen zum Speichern von Entitäten. Redis (JEDIS) für Bestenlisten unter Verwendung geordneter Listen. Memcache für Token Store.

Datenbank

MySQL, Memcached, Redis


Dies ähnelt dem, was wir auch in unseren Projekten verfolgen! Zusätzlich JBPM für Business Workflow. Warum kein Frühling, frage ich mich?
Ininprsr

Ich sollte ein Update mit unserem aktuellen Bogen durchführen: Derzeit verwenden wir Spring DI- und JDBC-Vorlagen für die Datenzugriffsschicht.
Pepster

6

Was wir in unserem Projekt verfolgt haben, ist:

Front-End-Technologie

  • AngularJS
  • HTML5
  • css3
  • Javascript
  • Bootstrap 3

API

  1. SICH AUSRUHEN
  2. JERSEY (JAX-RS)
  3. SEIEN SIE VERSICHERT
  4. FRÜHLINGSSTIEFEL
  5. Jackson
  6. Federsicherheit

Geschäftslogik

  • FRÜHLINGSDATEN

  • FRÜHLINGSDATEN MongoDB

Datenbank

  • MongoDB

Server (zum Zwischenspeichern)

  • redis

4

Wir verwenden immer noch den üblichen Struts-Spring-Hibernate-Stack.

Für zukünftige Apps untersuchen wir Spring Web Flow + Spring MVC + Hibernate oder Spring + Hibernate + Web Services mit Flex-Frontend.

Ein besonderes Merkmal unserer Architektur ist die Modularisierung. Wir haben eine Reihe von Modulen, von denen einige mit 3 bis maximal 30 Tabellen in der Datenbank beginnen. Die meisten Module bestehen aus Business- und Webprojekten. Das Geschäftsprojekt enthält die Geschäfts- und Persistenzlogik, während das Web die Präsentationslogik enthält.
Auf logischer Ebene gibt es drei Ebenen: Business, Persistence und Presentation.
Abhängigkeiten: Die
Präsentation hängt vom Geschäft und der Persistenz ab.
Die Beharrlichkeit hängt vom Geschäft ab.
Das Geschäft hängt nicht von anderen Schichten ab.

Die meisten Geschäftsprojekte verfügen über drei Arten von Schnittstellen (Hinweis: keine grafische Benutzeroberfläche, sondern eine programmatische Java-Schnittstellenschicht).

  1. Schnittstelle, die diese Präsentation als Client verwendet
  2. Schnittstelle, die andere Module verwenden, wenn sie der Client des Moduls sind.
  3. Schnittstelle, die für Verwaltungszwecke des Moduls verwendet werden kann.

Oft erweitert 1 2. Auf diese Weise ist es einfach, eine Implementierung eines Moduls durch eine andere zu ersetzen. Dies hilft uns, uns an verschiedene Kunden anzupassen und einfacher zu integrieren. Einige Kunden kaufen nur bestimmte Module und wir müssen bereits vorhandene Funktionen integrieren. Da Schnittstelle und Implementierungsschicht getrennt sind, ist es einfach, die Implementierung von Ad-Hock-Modulen für diesen bestimmten Client einzuführen, ohne die abhängigen Module zu beeinflussen. Und Spring Framework macht es einfach, verschiedene Implementierungen einzufügen.

Unsere Geschäftsschicht basiert auf POJOs. Eine Tendenz, die ich beobachte, ist, dass diese POJOs DTOs ähneln. Wir leiden unter einem anämischen Domänenmodell . Ich bin mir nicht ganz sicher, warum dies geschieht, aber es kann an der Einfachheit der Problemdomäne vieler unserer Module liegen, der größte Teil der Arbeit ist CRUD oder an Entwicklern, die Logik lieber woanders platzieren.


3

Hier ist eine weitere Webarchitektur, an der ich gearbeitet habe:

Eine Hauptanforderung war, dass die Anwendung Handys / andere Geräte unterstützen sollte. Die Anwendung sollte auch erweiterbar oder flexibel sein, um Änderungen bei der Auswahl der Technologie zu ermöglichen.

Präsentationsstufe:

  • JSP / JQuery (clientseitige MVC)
  • Native Android
  • Natives iPhone
  • Mobiles Web (HTML5 / CSS3 / Responsive Design)

  • Feder-REST-Controller (Kann zu JAX-RS wechseln)

Business Service Tier:

Spring @Service (Kann zu Stateless EJB wechseln)

Datenzugriffsebene:

Spring @Repository (Kann zu Stateless EJB wechseln)

Ressourcenebene:

JPA-Entitäten (Hibernate) (können zu jedem ORM geändert werden)

Weitere Informationen zu dem Buch, das dieser Architektur folgt, finden Sie hier .


2

IMHO haben die meisten von uns einen gemeinsamen Nenner. Zumindest im Backend haben wir eine Art IOC / DI-Container und ein Persistenz-Framework. Persönlich benutze ich dafür Guice und Mybatis. Die Unterschiede bestehen darin, wie wir die Ansichts- / UI- / Präsentationsschicht implementieren. Hier gibt es zwei Hauptoptionen (möglicherweise mehr). Aktionsbasiert (URLs, die Controllern zugeordnet sind) und komponentenbasiert. Derzeit verwende ich eine komponentenbasierte Präsentationsschicht (mit Wicket). Es ahmt perfekt eine Desktop-Umgebung nach, in der ich Komponenten und Ereignisse im Gegensatz zu URLs und Controllern verwende. Ich suche derzeit nach einem Grund, warum ich auf diese URL-Controller-Architektur migrieren sollte (so bin ich auf diese Seite gekommen). Warum der Hype um RESTful- und Stateless-Architekturen?

Um diese Frage kurz zu beantworten: Ich schreibe Stateful-Webanwendungen mit einem komponentenorientierten Framework über den Guice-IOC-Container und speichere Daten mit Mybatis in einer relationalen Datenbank.


1

Ein bisschen anders, und ich würde hier eine modularere Java-Architektur beanspruchen. Wir haben:

  1. Spring WS / Rest / JSP-Frontend
  2. Spring MVC für Business Service-Logik, die Präsentationsschichtlogik sowie Spring-Transaktionen enthält
  3. Component Service Communication Interface, über EJB von Business Services nachgeschlagen. EJBs legen ihre eigenen Transaktionsgrenzen fest, die Spring-Transaktionen beitreten können.
  4. Komponentenservice-Implementierungen, wieder Federkomponenten
  5. Integrationsschicht, MyBatis für Datenbankintegrationen, Spring WS für Webdienstintegrationen, andere Integrationstechnologien für andere Dienste
  6. Mainframes, Datenbanken, andere Dienste auf anderen Servern ...

Darüber hinaus verfügen wir über die gemeinsam genutzten Bibliotheksmodule, die für alle Dienste ein gemeinsamer Funktionsanbieter sind.

Die Verwendung verschiedener Schichten ermöglicht uns eine vollständige Entkopplung und die von uns benötigte Modularität. Wir können auch die Leistung von Java EE und Spring voll ausnutzen. Nichts hindert uns daran, JSF beispielsweise für das Frontend bei Bedarf zu verwenden.

Im Vergleich zur Beispielarchitektur von OP kann dies meiner Meinung nach mit vier statt drei Hauptschichten beschrieben werden, wenn auch mit einer Wendung.


0

Ich habe an Projekten gearbeitet, die dieses starre Manager-Muster verwenden. Historisch gesehen war ich ein großer Befürworter der starren Hierarchie, in der alles in eine ordentliche Schachtel passte. Im Laufe meiner Karriere finde ich es in vielen Fällen erzwungen. Ich glaube, dass eine agilere Einstellung zum Anwendungsdesign zu einem besseren Produkt führt. Was ich damit meine, eine Reihe von Klassen zu erstellen, die das vorliegende Problem lösen. Anstatt zu sagen "Haben Sie einen Manager für dies und das gebaut?"

Das aktuelle Projekt, an dem ich arbeite, ist eine Web-App mit einer Kombination aus Spring MVC- und RestEasy JSON / Ajax-Aufrufen. Auf der Serverseite, die in unsere Controller eingebettet ist, befindet sich eine sinnvolle fassadenbasierte Datenebene mit JPA / Hibernate für den direkten Datenbankzugriff, einige EJB-Zugriffe und einige SOAP-basierte Webdienstaufrufe. All dies ist ein benutzerdefinierter Java-Controller-Code, der festlegt, was als JSON serialisiert und an den Client zurückgegeben werden soll.

Wir verbringen fast keine Zeit damit, ein einheitliches Muster zu erstellen, sondern entscheiden uns für die Idee "Schlimmer ist besser" der Unix-Designphilosophie. Da es viel besser ist, außerhalb der Linien zu färben und schnell etwas Sinnvolles zu bauen, als etwas zu bauen, das einer Reihe strenger Designmandate entspricht.


0

Die Komponenten in der Webanwendungsarchitektur umfassen:

1: Browser: Client-Interaktion

        HTML
        JavaScript
        Stylesheet

2: Internet

3: Webserver

        CSS
        Image
        Pages(Java render )

4: Anwendungsserver

        App Webapp (Java interaction)
        Others WebApps

5: Datenbankserver

        Oracle, SQL, MySQL

6: Daten

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.