Décrivez l'architecture que vous utilisez pour les applications Web Java? [fermé]


146

Partageons les architectures d'applications Web basées sur Java!

Il existe de nombreuses architectures différentes pour les applications Web qui doivent être implémentées à l'aide de Java. Les réponses à cette question peuvent servir de bibliothèque de diverses conceptions d'applications Web avec leurs avantages et leurs inconvénients. Bien que je réalise que les réponses seront subjectives, essayons d'être aussi objectifs que possible et motiver les avantages et les inconvénients que nous énumérons.

Utilisez le niveau de détail que vous préférez pour décrire votre architecture. Pour que votre réponse ait une quelconque valeur, vous devrez au moins décrire les principales technologies et idées utilisées dans l'architecture que vous décrivez. Et enfin, quand devons-nous utiliser votre architecture?

Je vais commencer...


Vue d'ensemble de l'architecture

Nous utilisons une architecture à 3 niveaux basée sur des standards ouverts de Sun comme Java EE, Java Persistence API, Servlet et Java Server Pages.

  • Persistance
  • Affaires
  • Présentation

Les flux de communication possibles entre les couches sont représentés par:

Persistence <-> Business <-> Presentation

Ce qui signifie par exemple que la couche de présentation n'appelle ni n'effectue aucune opération de persistance, elle le fait toujours via la couche de gestion. Cette architecture est destinée à répondre aux exigences d'une application Web haute disponibilité.

Persistance

Effectue créer, lire, mettre à jour et de suppression ( CRUD ) la persistance des opérations. Dans notre cas, nous utilisons ( Java Persistence API ) JPA et nous utilisons actuellement Hibernate comme fournisseur de persistance et utilisons son EntityManager .

Cette couche est divisée en plusieurs classes, où chaque classe traite un certain type d'entités (c'est-à-dire que les entités liées à un panier peuvent être gérées par une seule classe de persistance) et est utilisée par un et un seul gestionnaire .

De plus, cette couche stocke également des entités JPA qui sont des choses comme Account, ShoppingCartetc.

Affaires

Toute la logique liée à la fonctionnalité de l'application Web se trouve dans cette couche. Cette fonctionnalité pourrait être le lancement d'un transfert d'argent pour un client qui souhaite payer un produit en ligne en utilisant sa carte de crédit. Cela pourrait tout aussi bien être la création d'un nouvel utilisateur, la suppression d'un utilisateur ou le calcul du résultat d'une bataille dans un jeu Web.

Cette couche est divisée en plusieurs classes et chacune de ces classes est annotée @Statelesspour devenir un Stateless Session Bean (SLSB). Chaque SLSB est appelé un gestionnaire et par exemple un gestionnaire pourrait être une classe annotée comme mentionné appelé AccountManager.

Lorsqu'il AccountManagerdoit effectuer des opérations CRUD, il effectue les appels appropriés à une instance de AccountManagerPersistence, qui est une classe de la couche de persistance. Une esquisse approximative de deux méthodes AccountManagerpourrait être:

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

Nous utilisons des transactions de gestionnaire de conteneurs afin de ne pas avoir à faire la démarcation des transactions nous-mêmes. Ce qui se passe essentiellement sous le capot, c'est que nous initions une transaction lors de la saisie de la méthode SLSB et la validons (ou la restituons) immédiatement avant de quitter la méthode. C'est un exemple de convention sur la configuration, mais nous n'avons encore besoin de rien d'autre que de la valeur par défaut, Required.

Voici comment le didacticiel Java EE 5 de Sun explique l' attribut de transaction requis pour Enterprise JavaBeans (EJB):

Si le client s'exécute dans une transaction et appelle la méthode du bean entreprise, la méthode s'exécute dans la transaction du client. Si le client n'est pas associé à une transaction, le conteneur démarre une nouvelle transaction avant d'exécuter la méthode.

L'attribut Required est l'attribut de transaction implicite pour toutes les méthodes de bean entreprise exécutées avec la démarcation de transaction gérée par le conteneur. En général, vous ne définissez pas l'attribut Obligatoire, sauf si vous devez remplacer un autre attribut de transaction. Les attributs de transaction étant déclaratifs, vous pouvez facilement les modifier ultérieurement.

Présentation

Notre couche présentation est en charge de ... la présentation! Il est responsable de l'interface utilisateur et affiche des informations à l'utilisateur en créant des pages HTML et en recevant les entrées de l'utilisateur via des requêtes GET et POST. Nous utilisons actuellement l'ancienne combinaison Servlet + Java Server Pages ( JSP ).

La couche appelle des méthodes dans les gestionnaires de la couche de gestion pour effectuer les opérations demandées par l'utilisateur et pour recevoir des informations à afficher dans la page Web. Parfois, les informations reçues de la couche de gestion sont de types moins complexes que Stringles s et integers, et parfois les entités JPA .

Avantages et inconvénients de l'architecture

Avantages

  • Avoir tout ce qui est lié à une manière spécifique de faire de la persistance dans cette couche signifie seulement que nous pouvons passer de l'utilisation de JPA à autre chose, sans avoir à réécrire quoi que ce soit dans la couche métier.
  • Il est facile pour nous d'échanger notre couche de présentation en quelque chose d'autre, et il est probable que nous le ferons si nous trouvons quelque chose de mieux.
  • Laisser le conteneur EJB gérer les limites des transactions est bien.
  • L'utilisation de Servlet + JPA est facile (pour commencer) et les technologies sont largement utilisées et implémentées dans de nombreux serveurs.
  • L'utilisation de Java EE est censée nous faciliter la création d'un système à haute disponibilité avec équilibrage de charge et basculement . Les deux que nous pensons que nous devons avoir.

Les inconvénients

  • En utilisant JPA, vous pouvez stocker des requêtes souvent utilisées sous forme de requêtes nommées en utilisant l' @NamedQueryannotation sur la classe d'entité JPA. Si vous avez autant que possible lié à la persistance dans les classes de persistance, comme dans notre architecture, cela répartira les emplacements où vous pouvez trouver des requêtes pour inclure également les entités JPA. Il sera plus difficile de visualiser les opérations de persistance et donc plus difficile à maintenir.
  • Nous avons des entités JPA dans notre couche de persistance. Mais Accountet ShoppingCart, ne sont-ils pas vraiment des objets métier? Cela se fait de cette façon car vous devez toucher ces classes et les transformer en entités que JPA sait gérer.
  • Les entités JPA, qui sont également nos objets métier, sont créées comme des objets de transfert de données ( DTO ), également appelés objets de valeur (VO). Il en résulte un modèle de domaine anémique car les objets métier n'ont pas de logique propre à l'exception des méthodes d'accès. Toute la logique est réalisée par nos responsables dans la couche métier, ce qui se traduit par un style de programmation plus procédural. Ce n'est pas une bonne conception orientée objet, mais ce n'est peut-être pas un problème? (Après tout, l'orientation objet n'est pas le seul paradigme de programmation qui a donné des résultats.)
  • L'utilisation d'EJB et de Java EE introduit un peu de complexité. Et nous ne pouvons pas utiliser uniquement Tomcat (l'ajout d'un micro-conteneur EJB n'est pas purement Tomcat).
  • Il y a beaucoup de problèmes avec l'utilisation de Servlet + JPA. Utilisez Google pour plus d'informations sur ces problèmes.
  • Comme les transactions sont fermées à la sortie de la couche de gestion, nous ne pouvons pas charger d'informations à partir d'entités JPA qui sont configurées pour être chargées à partir de la base de données lorsque cela est nécessaire (en utilisant fetch=FetchType.LAZY) depuis l'intérieur de la couche de présentation. Cela déclenchera une exception. Avant de renvoyer une entité contenant ces types de champs, nous devons nous assurer d'appeler le getter approprié. Une autre option consiste à utiliser le langage de requête de persistance Java ( JPQL ) et à effectuer un FETCH JOIN. Cependant, ces deux options sont un peu lourdes.

1
Il semble que vous ayez placé la barre trop haut avec votre propre réponse - cela a peut-être découragé les autres :)
Jonik

5
Aussi, peut-être que votre opinion devrait être une réponse normale, et non une partie de la question, afin qu'elle puisse être mise aux voix avec d'autres réponses?
Jonik

Cette question a été référencée sur meta.
D4V1D

Réponses:


20

Ok, je vais en faire un (plus court):

  • Frontend: Tapestry (3 pour les projets plus anciens, 5 pour les projets plus récents)
  • Couche métier: printemps
  • DAO: Ibatis
  • Base de données: Oracle

Nous utilisons la prise en charge des transactions Sping et démarrons les transactions dès l'entrée dans la couche de service, en se propageant jusqu'aux appels DAO. La couche Service a la plus grande connaissance du modèle de bus, et les DAO font un travail CRUD relativement simple.

Certaines requêtes plus complexes sont gérées par des requêtes plus compliquées dans le backend pour des raisons de performances.

Les avantages de l'utilisation de Spring dans notre cas sont que nous pouvons avoir des instances dépendantes du pays / de la langue, qui sont derrière une classe Spring Proxy. En fonction de l'utilisateur dans la session, l'implémentation correcte du pays / de la langue est utilisée lors d'un appel.

La gestion des transactions est presque transparente, annulation des exceptions d'exécution. Nous utilisons autant que possible des exceptions non contrôlées. Nous avions l'habitude de faire des exceptions vérifiées, mais avec l'introduction de Spring, je vois les avantages des exceptions non vérifiées, ne traitant les exceptions que lorsque vous le pouvez. Cela évite beaucoup de trucs passe-partout "attraper / relancer" ou "jeter".

Désolé, il est plus court que votre message, j'espère que vous trouverez cela intéressant ...


Bonne réponse! Ce fil semble attirer du trafic, dommage que d'autres personnes n'aient pas le temps de décrire leurs architectures ou ont d'autres raisons de ne pas participer.

19

Technologies de développement Web basées sur Java idéales aujourd'hui.

Couche Web:

HTML + CSS + Ajax + JQuery

Couche de traitement RESTFul Web Controller / Action / Request:

Cadre de jeu

Logique métier / couche de service:

Utilisez Pure Java Code aussi longtemps que possible. On peut faire la fusion des services Web ici.

Couche de transformation de données XML / JSon:

XMLTool (recherche sur Google Code), JSoup, Google GSon, XStream, JOOX (recherche sur Google Code)

Couche de persistance:

CRUD: JPA ou SienaProject ou QueryDSL / Requêtes complexes: JOOQ, QueryDSL


9

Voici mes 5 cents

Présentation

Android, Angular.JS WebClient, OAUTHv2

API

REST, Jersey (JAX-RS), Jackson (dé- / sérialisation JSON), objets DTO (différents des modèles de logique métier)

Logique métier

Ressort pour la gestion des DI et des événements. Approche DDD-ish des objets de modèle. Les travaux plus longs sont déchargés avec SQS dans les modules de travail.

DAO

Modèle de référentiel avec des modèles Spring JDBC pour stocker des entités. Redis (JEDIS) pour les classements, en utilisant des listes ordonnées. Memcache pour Token Store.

Base de données

MySQL, Memcached, Redis


C'est quelque chose de similaire à ce que nous suivons dans nos projets aussi! En outre JBPM pour le flux de travail d'entreprise. Pourquoi pas de printemps je me demande?
ininprsr

Je devrais faire une mise à jour avec notre arc actuel: actuellement, nous utilisons des modèles Spring DI et JDBC pour la couche d'accès aux données.
Pepster

6

Ce que nous avons suivi dans notre projet est:

Technologie frontale

  • AngularJS
  • HTML5
  • css3
  • Javascript
  • Bootstrap 3

API

  1. DU REPOS
  2. JERSEY (JAX-RS)
  3. REPOS ASSURÉ
  4. BOTTE DE PRINTEMPS
  5. Jackson
  6. sécurité du printemps

Logique métier

  • DONNÉES DE PRINTEMPS

  • Données PRINTEMPS MongoDB

Base de données

  • MongoDB

Serveur (pour la mise en cache)

  • redis

4

Nous utilisons toujours la pile habituelle Struts-Spring-Hibernate.

Pour les futures applications, nous examinons Spring Web Flow + Spring MVC + Hibernate ou Spring + Hibernate + Web Services avec Flex frontal.

Une caractéristique distincte de notre architecture est la modularisation. Nous avons un certain nombre de modules, certains commençant par 3 à 30 tables maximum dans la base de données. La plupart des modules se composent de projets commerciaux et Web. Le projet d'entreprise contient une logique commerciale et de persistance tandis que le Web contient une logique de présentation.
Au niveau logique, il existe trois couches: Business, Persistance et Présentation.
Dépendances: la
présentation dépend de l'activité et de la persistance.
La persévérance dépend des affaires.
Les affaires ne dépendent pas d'autres couches.

La plupart des projets d'entreprise ont trois types d'interfaces (note: pas de GUI, c'est une couche d'interface Java programmatique).

  1. Interface que la présentation utilise en tant que client
  2. Interface que d'autres modules utilisent lorsqu'ils sont le client du module.
  3. Interface qui peut être utilisée à des fins administratives du module.

Souvent, 1 étend 2. De cette façon, il est facile de remplacer une implémentation de module par une autre. Cela nous aide à nous adapter à différents clients et à nous intégrer plus facilement. Certains clients n'achèteront que certains modules et nous devons intégrer les fonctionnalités dont ils disposent déjà. Étant donné que l'interface et la couche d'implémentation sont séparées, il est facile de déployer l'implémentation du module ad-hock pour ce client spécifique sans affecter les modules dépendants. Et Spring Framework facilite l'injection de différentes implémentations.

Notre couche métier est basée sur les POJO. Une tendance que j'observe est que ces POJO ressemblent à des DTO. Nous souffrons d'un modèle de domaine anémique . Je ne sais pas trop pourquoi cela se produit, mais cela peut être dû à la simplicité du domaine de problème de beaucoup de nos modules, la plupart du travail est CRUD ou à des développeurs préférant placer la logique ailleurs.


3

Voici une autre architecture Web sur laquelle j'ai travaillé:

Une exigence majeure était que l'application devrait prendre en charge les mobiles / autres appareils. L'application doit également être extensible ou flexible aux changements de choix technologiques.

Niveau de présentation:

  • JSP / JQuery (MVC côté client)
  • Android natif
  • IPhone natif
  • Web mobile (HTML5 / CSS3 / Conception réactive)

  • Contrôleurs Spring REST (peuvent changer en JAX-RS)

Niveau de service commercial:

Spring @Service (peut changer en EJB sans état)

Niveau d'accès aux données:

Spring @Repository (peut changer en EJB sans état)

Niveau de ressource:

Entités Hibernate (JPA) (peut changer en n'importe quel ORM)

Vous pouvez trouver plus d'informations sur le livre qui suit cette architecture ici .


2

IMHO, la plupart d'entre nous ont un dénominateur commun. Au moins dans le back-end, nous avons une forme de conteneur IOC / DI et un cadre de persistance. Personnellement, j'utilise Guice et Mybatis pour cela. Les différences résident dans la manière dont nous implémentons la couche vue / interface utilisateur / présentation. Il y a 2 options principales ici (peut-être plus). Basé sur l'action (URL mappées aux contrôleurs) et basé sur les composants. J'utilise actuellement une couche de présentation basée sur des composants (en utilisant un guichet). Il imite parfaitement un environnement de bureau dans lequel j'utilise des composants et des événements plutôt que des URL et des contrôleurs. Je cherche actuellement une raison pour laquelle je devrais migrer vers ce type d'architecture de contrôleur d'URL (c'est ainsi que je me suis retrouvé sur cette page). Pourquoi le battage médiatique sur les architectures RESTful et Stateless.

Pour répondre à cette question en bref: j'écris des applications Web avec état en utilisant un framework orienté composants au-dessus du conteneur Guice IOC et je mets des données dans une base de données relationnelle à l'aide de Mybatis.


1

Un peu différent, et je revendiquerais ici une architecture Java plus modulaire. Nous avons:

  1. Extrémité avant Spring WS / Rest / JSP
  2. Spring MVC pour la logique de service métier, contenant la logique de la couche de présentation ainsi que les transactions Spring
  3. Interface de communication des services de composants, recherchée via EJB par les services métier. Les EJB définissent leurs propres limites de transaction qui peuvent rejoindre les transactions Spring.
  4. Implémentations de services de composants, encore une fois les composants Spring
  5. Couche d'intégration, MyBatis pour les intégrations de bases de données, Spring WS pour les intégrations de services Web, autres technologies d'intégration pour d'autres services
  6. Mainframes, bases de données, autres services sur d'autres serveurs ...

En plus de ce qui précède, nous avons les modules de bibliothèque partagée qui sont un fournisseur de fonctionnalités communes pour tous les srevices.

L'utilisation de différentes couches nous permet un découplage complet et la modularité dont nous avons besoin. Nous sommes également en mesure d'utiliser pleinement la puissance de Java EE ainsi que de Spring. Rien ne nous empêche d'utiliser JSF, par exemple, pour le front-end si nécessaire.

Par rapport à l'exemple d'architecture d'OP, je pense que cela peut être décrit comme ayant quatre couches principales au lieu de trois, mais avec une torsion.


0

J'ai travaillé sur des projets qui utilisent ce modèle de gestionnaire rigide. Historiquement, j'étais un fervent partisan de la hiérarchie rigide où tout rentre dans une boîte ordonnée. Au fur et à mesure que je progresse dans ma carrière, je trouve que c'est forcé dans de nombreux cas. Je crois qu'adopter un état d'esprit plus agile envers la conception d'applications conduit à un meilleur produit. Ce que je veux dire par la création d'un ensemble de classes qui résolvent le problème à résoudre. Plutôt que de dire "Avez-vous créé un gestionnaire pour ceci et cela?"

Le projet actuel sur lequel je travaille est une application Web avec une combinaison d'appels Spring MVC et RestEasy JSON / Ajax. Du côté serveur intégré à nos contrôleurs, il y a un niveau de données basé sur une façade sensible avec JPA / Hibernate pour un accès direct à la base de données, certains accès EJB et certains appels de service Web basés sur SOAP. Lier tout cela ensemble est un code de contrôleur Java personnalisé qui détermine ce qu'il faut sérialiser en tant que JSON et retourner au client.

Nous ne passons presque pas de temps à essayer de créer un modèle unifié à la place, optant pour l’idée «Pire est Mieux» de la philosophie de conception Unix. Étant donné qu'il est préférable de colorer en dehors des lignes et de construire quelque chose de sensé, rapidement que de construire quelque chose qui adhère à un ensemble de mandats de conception stricts.


0

Les composants de l' architecture d'application Web comprennent:

1: Navigateur: interaction avec le client

        HTML
        JavaScript
        Stylesheet

2: Internet

3: serveur Web

        CSS
        Image
        Pages(Java render )

4: serveur d'applications

        App Webapp (Java interaction)
        Others WebApps

5: serveur de base de données

        Oracle, SQL, MySQL

6: Données

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.