Contrôleur JSF, Service et OAC
j'essaie de m'habituer au fonctionnement de JSF en ce qui concerne l'accès aux données (provenant d'un arrière-plan de printemps)
je crée un exemple simple qui maintient une liste d'utilisateurs, j'ai quelque chose comme
<h:dataTable value="#{userListController.userList}" var="u">
<h:column>#{u.userId}</h:column>
<h:column>#{u.userName}</h:column>
</h:dataTable>
, Puis le "contrôleur" a quelque chose comme
@Named(value = "userListController")
@SessionScoped
public class UserListController {
@EJB
private UserListService userListService;
private List<User> userList;
public List<User> getUserList() {
userList = userListService.getUsers();
return userList;
}
}
et le "service" (bien qu'il semble plus comme un DAO) a
public class UserListService {
@PersistenceContext
private EntityManager em;
public List<User> getUsers() {
Query query = em.createQuery("SELECT u from User as u");
return query.getResultList();
}
}
Est-ce la bonne façon de faire les choses? Est mon la terminologie de droit? Le "service" ressemble plus à un DAO? Et le contrôleur a l'impression de faire une partie du travail du service.
2 réponses
Est-ce la bonne façon de faire les choses?
en dehors de la logique de l'entreprise la manière inefficace dans une méthode managed bean getter, et l'utilisation d'une trop large portée managed bean, il semble bien. Si vous déplacez l'appel de service de la méthode getter à une @PostConstruct
méthode et utiliser soit @RequestScoped
ou @ViewScoped
au lieu de @SessionScoped
, il aura l'air mieux.
voir aussi:
est-ce que ma terminologie est correcte?
c'est bon. Tant que vous êtes cohérent et que le code est lisible de façon raisonnable. Seulement votre façon de nommer les classes et les variables est quelque peu délicat (illogique et/ou la duplication). Par exemple , j'utiliserais personnellement users
au lieu de userList
, et j'utiliserais var="user"
au lieu de var="u"
, et j'utiliserais id
et name
au lieu de userId
et userName
. En outre, un "UserListService" semble comme il ne peut traiter que des listes d'utilisateurs au lieu des utilisateurs en général. Je préfère utiliser "UserService" de sorte que vous pouvez également l'utiliser pour la création, la mise à jour et la suppression des utilisateurs.
voir aussi:
le "service" ressemble plus à un DAO?
ce n'est pas vraiment un DAO. En gros, JPA est le vrai DAO ici. Auparavant, lorsque JPA n'existait pas, tout le monde homegrew DAO interfaces afin que les méthodes de service peut continuer à les utiliser même si l'implémentation sous-jacente ("simple old" JDBC, ou "good old" Hibernate, etc.) change. La véritable tâche d'une méthode de service est la gestion transparente des transactions. Ce n'est pas la responsabilité du DAO.
voir aussi:
- j'ai trouvé JPA, ou similaire, ne pas encourager DAO modèle
- relation entre DAO et JDBC?
- quand est-il nécessaire ou commode d'utiliser le ressort ou EJB3 ou tous ensemble?
et le contrôleur a l'impression de faire une partie du travail du service.
je peux imaginer qu'il fait cela dans cette configuration relativement simple. Toutefois, le contrôleur fait en fait partie de l'interface et non de l'arrière-plan. Le le service fait partie du backend qui devrait être conçu de telle manière qu'il soit réutilisable à travers tous les frontend différents, tels que JSF, JAX-RS, "plain" JSP+Servlet, même Swing, etc. De plus, le controller spécifique à un frontal (également appelé "Backup bean" ou "presenter") vous permet de traiter de manière spécifique un frontal avec succès et/ou des résultats exceptionnels, comme dans le cas de JSF en affichant un message face en cas d'exception lancée d'un service.
voir aussi:
dans l'ensemble, l'approche correcte serait la suivante:
<h:dataTable value="#{userBacking.users}" var="user">
<h:column>#{user.id}</h:column>
<h:column>#{user.name}</h:column>
</h:dataTable>
@Named
@RequestScoped // Use @ViewScoped once you bring in ajax (e.g. CRUD)
public class UserBacking {
private List<User> users;
@EJB
private UserService userService;
@PostConstruct
public void init() {
users = userService.listAll();
}
public List<User> getUsers() {
return users;
}
}
@Stateless
public class UserService {
@PersistenceContext
private EntityManager em;
public List<User> listAll() {
return em.createQuery("SELECT u FROM User u", User.class).getResultList();
}
}
vous pouvez trouver ici un projet de coup d'envoi du monde réel en utilisant le Java EE canonique / JSF / CDI / EJB / JPA pratiques: Java EE coup d'envoi de l'app .
voir aussi:
- créer des pages de maître-détail pour les entités, comment les lier et quelles sont les possibilités de choisir
- passer un haricot commun géré par la FJ2 dans la base de données EJB ou mettre ce qui est requis dans un objet de transfert
- Filtre de ne pas initialiser l'EntityManager
- javax.persistance.TransactionRequiredException in small facelet application
C'est un dao, eh bien, en fait un référentiel mais ne vous inquiétez pas à propos de la différence de trop, comme c'est accéder à la base de données en utilisant le contexte de persistance.
vous devez créer une classe de service, qui enveloppe cette méthode et est où les transactions sont invoquées.
parfois les classes de service se sentent inutiles, mais quand vous avez une méthode de service qui appelle de nombreuses méthodes de l'ofa, leur utilisation est plus justifiée.
normalement, je finis par créer le service, même si cela ne me semble pas nécessaire, pour m'assurer que les modèles restent les mêmes et que l'ofa ne soit jamais injecté directement.
ceci ajoute une couche supplémentaire d'abstraction rendant le remaniement futur plus flexible.