Partageons les architectures d'applications web basées sur Java !
Il existe de nombreuses architectures différentes pour les applications web qui doivent être mises en œuvre à l'aide de Java. Les réponses à cette question peuvent servir de bibliothèque des différentes conceptions d'applications Web avec leurs avantages et inconvénients. Bien que je réalise que les réponses seront subjectives, essayons d'être aussi objectifs que possible et de 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, le plus important, quand devons-nous utiliser votre architecture ?
Je vais commencer...
Aperçu de l'architecture
Nous utilisons une architecture à trois niveaux basée sur les normes ouvertes de Sun comme Java EE, Java Persistence API, Servlet et Java Server Pages.
- Persistance
- Entreprise
- 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 ou n'effectue jamais d'opérations de persistance, elle le fait toujours par le biais de la couche métier. Cette architecture est destinée à répondre aux exigences d'une application web à haute disponibilité.
Persistance
Effectue la création, la lecture, la mise à jour et la suppression ( CRUD ) des opérations de persistance. Dans notre cas, nous utilisons ( API de persistance Java ) JPA et nous utilisons actuellement Hibernate comme fournisseur de persistance et utiliser son EntityManager .
Cette couche est divisée en plusieurs classes, chaque classe traitant un certain type d'entités (par exemple, les entités liées à un panier d'achat peuvent être traitées par une seule classe de persistance). utilisé par un et un seul manager .
En outre, cette couche stocke également Entités de l'APP qui sont des choses comme Account
, ShoppingCart
etc.
Entreprise
Toute la logique qui est liée à la fonctionnalité de l'application web se trouve dans cette couche. Cette fonctionnalité peut consister à initier un transfert d'argent pour un client qui souhaite payer un produit en ligne à l'aide de sa carte de crédit. Il peut tout aussi bien s'agir de créer un nouvel utilisateur, de supprimer un utilisateur ou de calculer l'issue d'une bataille dans un jeu en ligne.
Cette couche est divisée en plusieurs classes et chacune de ces classes est annotée avec @Stateless
pour devenir un Haricot de session apatride (SLSB). Chaque SLSB est appelé un manager et par exemple, un gestionnaire pourrait être une classe annotée comme mentionné appelée AccountManager
.
Lorsque AccountManager
a besoin d'effectuer des opérations CRUD, il fait les appels appropriés à une instance de AccountManagerPersistence
qui est une classe de la couche de persistance. Une ébauche de deux méthodes dans AccountManager
pourrait ê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 transactions du gestionnaire de conteneurs pour qu'on n'ait pas à faire la démarcation des transactions entre nous. Ce qui se passe essentiellement sous le capot, c'est que nous lançons une transaction lorsque nous entrons dans la méthode SLSB et que nous la validons (ou la rétablissons) immédiatement avant de quitter la méthode. C'est un exemple de convention par rapport à la configuration, mais nous n'avons pas encore eu besoin d'autre chose que la valeur par défaut, Required, pour le moment.
Voici comment The Java EE 5 Tutorial de Sun explique le processus d'intégration. Attribut de transaction requis pour les Enterprise JavaBeans (EJB's) :
Si le client s'exécute dans une transaction et invoque la méthode de l'enterprise la méthode du haricot d'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 implicite de la transaction pour toutes les méthodes de haricot d'entreprise exécutées avec transaction gérée par le conteneur géré par le conteneur. En général, vous ne définissez pas l'attribut Required, sauf si vous devez pour remplacer un autre attribut de la transaction. Les attributs de transaction sont déclaratifs, vous pouvez facilement facilement les modifier ultérieurement.
Présentation
Notre couche de présentation est en charge de... la présentation ! Elle est responsable de l'interface utilisateur et montre les informations à l'utilisateur en construisant des pages HTML et en recevant les entrées de l'utilisateur par des requêtes GET et POST. Nous utilisons actuellement l'ancien Servlet + Java Server Pages ( JSP ) combinaison.
La couche appelle des méthodes dans gestionnaires de la couche métier pour effectuer les opérations demandées par l'utilisateur et pour recevoir les informations à afficher dans la page web. Parfois, les informations reçues de la couche métier sont des types moins complexes comme String
et int
egers, et à d'autres moments Entités de l'APP .
Avantages et inconvénients de l'architecture
Pour
- Le fait d'avoir tout ce qui est lié à une façon 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 de remplacer notre couche de présentation par une 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 une bonne chose.
- L'utilisation de Servlet + JPA est facile (pour commencer) et les technologies sont largement utilisées et mises en œuvre dans de nombreux serveurs.
- L'utilisation de Java EE est censée nous permettre de créer plus facilement un système à haute disponibilité avec équilibrage des charges et basculer . Tous deux nous semblent indispensables.
Cons
- Avec JPA, vous pouvez stocker les requêtes souvent utilisées sous forme de requêtes nommées en utilisant la fonction
@NamedQuery
sur la classe d'entité JPA. Si vous avez autant de choses que possible liées à la persistance dans les classes de persistance, comme dans notre architecture, cela répartira les endroits où vous pouvez trouver des requêtes pour inclure également les entités JPA. Il sera plus difficile d'avoir une vue d'ensemble des opérations de persistance et donc plus difficile à maintenir. - Nous avons des entités JPA dans le cadre de notre couche de persistance. Mais
Account
etShoppingCart
Mais si l'on veut que les classes de JPA soient utilisées, ne s'agit-il pas d'objets métier ? C'est ainsi que cela se passe, car vous devez toucher ces classes et les transformer en entités que JPA sait gérer. - Les entités JPA, qui sont aussi nos objets d'entreprise, 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 effectuée par nos gestionnaires dans la couche métier, ce qui donne lieu à 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 un problème pour nous). purement Tomcat).
- L'utilisation de Servlet + JPA pose de nombreux problèmes. Utilisez Google pour obtenir plus d'informations sur ces questions.
- Comme les transactions sont fermées à la sortie de la couche métier, nous ne pouvons pas charger d'informations à partir des entités JPA qui sont configurées pour être chargées à partir de la base de données lorsqu'elles sont nécessaires (à l'aide de la fonction
fetch=FetchType.LAZY
) depuis l'intérieur de la couche de présentation. Cela déclenchera une exception. Avant de retourner une entité contenant ce type de champs, nous devons nous assurer d'appeler les getter's appropriés. Une autre option consiste à utiliser le Java Persistence Query Language ( JPQL ) et faire unFETCH JOIN
. Cependant, ces deux options sont un peu lourdes.