Partageons les 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 conceptions d’applications Web variées avec leurs avantages et inconvénients. Bien que je sache que les réponses seront subjectives, essayons d’être aussi objectifs que possible et motivons 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 soit utile, vous devez au moins décrire les principales technologies et idées utilisées dans l'architecture que vous décrivez. Et enfin, quand devrions-nous utiliser votre architecture?
Je vais commencer...
Nous utilisons une architecture à 3 niveaux basée sur les standards ouverts de Sun comme Java EE, Java API de persistance, Servlet et Java = Pages du serveur.
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 d'opérations de persistance, elle le fait toujours à travers la couche de gestion. Cette architecture est conçue pour répondre aux exigences d'une application Web à haute disponibilité.
Effectue les opérations de persistance suivantes: création, lecture, mise à jour et suppression ( CRUD ). Dans notre cas, nous utilisons JPA ( Java Persistence API ) 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 associées à un panier peuvent être gérées par une seule classe de persistance) et est utilisé par un et un seul manager.
En outre, cette couche stocke également entités JPA , qui sont des éléments tels que Account
, ShoppingCart
etc.
Toute la logique liée à la fonctionnalité de l'application Web se trouve dans cette couche. Cette fonctionnalité pourrait initier 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 basé sur le Web.
Cette couche est divisée en plusieurs classes et chacune de ces classes est annotée avec @Stateless
pour devenir un Stateless Session Bean (SLSB). Chaque SLSB s'appelle un manager et, par exemple, un manager peut être une classe annotée comme mentionné ci-dessus, appelée AccountManager
.
Lorsque AccountManager
doit exécuter des opérations CRUD, il appelle de manière appropriée une instance de AccountManagerPersistence
, qui est une classe de la couche de persistance. Un croquis approximatif 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 de gestionnaire de conteneur afin que nous n'ayons pas à faire la démarcation de transaction nous-mêmes. Ce qui se passe fondamentalement sous le capot est que nous initions une transaction lorsque nous entrons dans la méthode SLSB et la validons (ou l'annulons) immédiatement avant de quitter la méthode. C'est un exemple de convention sur la configuration, mais nous n'avons pas encore eu besoin de rien, mais de la valeur par défaut, Obligatoire, pour le moment.
Voici comment le Java EE 5 Tutorial de Sun explique le attribut de transaction requis pour Enterprise JavaBeans (EJB):
Si le client est en cours d’exécution dans une transaction et appelle la méthode du bean enterprise, celle-ci 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 d'entreprise exécutées avec une démarcation de transaction gérée par le conteneur. Généralement, vous ne définissez pas l'attribut Required sauf si vous devez remplacer un autre attribut de transaction. Les attributs de transaction étant déclaratifs, vous pouvez facilement les modifier ultérieurement.
Notre couche de présentation est en charge de ... présentation! Il est responsable de l'interface utilisateur et montre les informations à l'utilisateur en créant des pages HTML et en recevant les entrées de l'utilisateur via GET et POST demandes. Nous utilisons actuellement l'ancien Servlet ' s + Java Pages serveur ( JSP )).
La couche appelle des méthodes dans managers de la couche de gestion pour effectuer les opérations demandées par l'utilisateur et recevoir les informations à afficher dans la page Web. Parfois, les informations reçues de la couche de gestion sont des types moins complexes que String
'et int
egers, et à d'autres moments entités JPA .
@NamedQuery
annotation sur la classe d’entités JPA. Si vous avez autant que possible lié à la persistance dans les classes de persistance, comme dans notre architecture, cela dispersera les emplacements où vous pourrez trouver des requêtes pour inclure également les entités JPA. Il sera plus difficile d’observer les opérations de persistance et donc plus difficile à maintenir.Account
et ShoppingCart
ne sont-ils pas vraiment des objets métier? C’est ainsi que vous devez toucher à ces classes et les transformer en entités que JPA sait gérer.fetch=FetchType.LAZY
) depuis l'intérieur de la couche de présentation. Cela déclenchera une exception. Avant de renvoyer une entité contenant ce type de champs, nous devons nous assurer d'appeler le getter correspondant. Une autre option consiste à utiliser Java Langage de requête de persistance ( JPQL ) et à effectuer un FETCH JOIN
. Cependant, ces deux options sont un peu lourdes.Ok je vais en faire un (plus court):
Nous utilisons le support des transactions Sping et commençons les transactions en entrant dans la couche service, en se propageant jusque dans l'appel DAO. La couche Service possède le plus de connaissances en matière de modèles d’entreprise et les DAO effectuent un travail CRUD relativement simple.
Certaines requêtes plus complexes sont gérées par des requêtes plus complexes dans le back-end pour des raisons de performances.
L'avantage d'utiliser Spring dans notre cas est que nous pouvons avoir des instances dépendantes du pays/de la langue, qui se trouvent derrière une classe Spring Proxy. En fonction de l'utilisateur de la session, la mise en œuvre pays/langue correcte est utilisée lors d'un appel.
La gestion des transactions est presque transparente et annule les 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, en ne gérant que les exceptions lorsque vous le pouvez. Cela évite beaucoup de choses "attrape/rethrow" ou "jette".
Désolé, c'est plus court que votre message, j'espère que vous trouverez cela intéressant ...
Idéal Java Technologies de développement Web basées aujourd'hui.
HTML + CSS + Ajax + JQuery
Cadre de jeu
Utilisez pur Java aussi longtemps que possible. On peut faire la fusion des services Web ici.
XMLTool (Recherche sur Google Code), JSoup, Google GSon, XStream, JOOX (Recherche sur Google Code)
CRUD: JPA ou SienaProject ou QueryDSL/Requêtes complexes: JOOQ, QueryDSL
Voici mes 5 cents
Android, Angular.JS WebClient, OAUTHv2
REST, Jersey (JAX-RS), Jackson (de-/sérialisation JSON), objets DTO (différents des modèles de logique métier)
Ressort pour la gestion des ID et des événements. Approche DDD-ish des objets du modèle. Les tâches plus longues sont déchargées avec SQS dans des modules de travail.
Modèle de référentiel avec Spring JDBC-templates pour stocker des entités. Redis (JEDIS) pour les classements, à l'aide de listes ordonnées. Memcache pour Token Store.
MySQL, Memcached, Redis
Ce que nous avons suivi dans notre projet est:
Technologie frontale
API
logique d'entreprise
DONNÉES DE PRINTEMPS
PRINTEMPS données MongoDB
base de données
Serveur (pour la mise en cache)
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 système frontal Flex.
Une caractéristique distincte de notre architecture est la modularisation. Nous avons un certain nombre de modules, certains commençant par 3 à 30 maximum dans la base de données. La plupart des modules sont constitués d’affaires et de projets Web. Le projet d'entreprise contient la logique commerciale et de persistance, tandis que le Web contient la logique de présentation.
Au niveau logique, il y a trois couches: activité, persistance et présentation.
Dépendances:
La présentation dépend de Business et de Persistance.
La persistance dépend des affaires.
Les entreprises ne dépendent pas d’autres couches.
La plupart des projets d’entreprise ont trois types d’interfaces (note: ce n’est pas une interface graphique, c’est une couche de programmation Java)).
Souvent, 1 s'étend sur 2. De cette façon, il est facile de remplacer une implémentation de module par une autre. Cela nous aide à adopter 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à. Etant donné que l'interface et la couche d'implémentation sont séparées, il est facile de déployer l'implémentation de modules 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 de 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èmes de beaucoup de nos modules; la plupart du travail est effectué avec CRUD ou au fait que les développeurs préfèrent placer la logique ailleurs.
Voici une autre architecture Web sur laquelle j'ai travaillé:
L’une des principales exigences était que l’application devait prendre en charge les téléphones portables/autres appareils. L'application doit également être extensible ou flexible aux changements de choix technologiques.
Niveau de présentation:
Web mobile (HTML5/CSS3/Responsive Design)
Spring REST Contrôleurs (peut être remplacé par JAX-RS)
Niveau de service métier:
Spring @Service (peut être remplacé par un EJB sans état)
Niveau d'accès aux données:
Spring @Repository (peut être remplacé par un EJB sans état)
Niveau de ressources:
Hibernate (JPA) entités (peut être remplacé par n'importe quel ORM)
Vous pouvez trouver plus d'informations sur le livre qui suit cette architecture ici .
IMHO, la plupart d'entre nous ont un dénominateur commun. Au moins dans le back-end, nous avons une certaine forme de conteneur IOC/DI et un cadre de persistance. Personnellement, j'utilise Guice et Mybatis pour cela. Les différences concernent la manière dont nous implémentons la couche vue/interface utilisateur/présentation. Il existe 2 options principales ici (peut-être plus). Basé sur les actions (URL mappées aux contrôleurs) et sur les composants. Actuellement, j'utilise une couche de présentation à base de composants (utilisant un guichet). Il imite parfaitement un environnement de bureau dans lequel j'utilise des composants et des événements, par opposition aux URL et aux contrôleurs. Je cherche actuellement une raison pour laquelle je devrais migrer vers ce type d'architecture de contrôleur d'URL (c'est comme ça que j'ai fini 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 dynamiques avec un framework orienté composant au-dessus de Guice IOC) et je mets les données dans une base de données relationnelle à l'aide de Mybatis.
Un peu différent, et je dirais une architecture plus modulaire Java ici. Nous avons:
En plus de ce qui précède, nous avons les modules de bibliothèque partagée, qui sont le fournisseur de fonctionnalités communes à tous les services.
L'utilisation de différentes couches nous permet un découplage total et la modularité dont nous avons besoin. Nous sommes également en mesure d'utiliser pleinement la puissance de Java EE ainsi que 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, bien qu'avec une torsion.
J'ai travaillé sur des projets utilisant ce modèle de gestionnaire rigide. Historiquement, j’étais un fervent partisan de la hiérarchie rigide où tout rentre dans une boîte soignée. Au fur et à mesure que je progresse dans ma carrière, je le trouve forcé dans de nombreux cas. Je crois que l'adoption d'un état d'esprit plus agile envers la conception d'applications conduit à un meilleur produit. Ce que je veux dire par cela crée un ensemble de classes qui résolvent le problème. Plutôt que de dire "Avez-vous construit un manager pour ceci et cela?"
Le projet en cours sur lequel je travaille est une application Web associant les appels Spring MVC et RestEasy JSON/Ajax. Sur le côté serveur, nos contrôleurs incluent un niveau de données basé sur une façade sensible avec JPA/Hibernate pour un accès direct à la base de données, un accès EJB et certains appels de services Web basés sur SOAP). un code de contrôleur personnalisé Java qui détermine ce qu'il faut sérialiser en tant que JSON et le retourner au client.
Nous ne passons presque pas de temps à essayer de créer un modèle unifié au lieu d’adopter l’idée "Pire est mieux" de la philosophie de conception Unix. Étant donné qu'il est bien préférable de colorer en dehors des lignes et de construire quelque chose de sensé, rapidement, plutôt que de construire quelque chose qui respecte un ensemble de mandats de conception stricts.
Les composants de Web Application Architecture comprennent:
1: Navigateur: interaction client
HTML
JavaScript
Stylesheet
2: Internet
3: serveur Web
CSS
Image
Pages(Java render )
4: serveur d'application
App Webapp (Java interaction)
Others WebApps
5: serveur de base de données
Oracle, SQL, MySQL
6: données