JSF 控制器、服务和 DAO [英] JSF Controller, Service and DAO

查看:19
本文介绍了JSF 控制器、服务和 DAO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力适应 JSF 在访问数据方面的工作方式(来自 Spring 背景)

I'm trying to get used to how JSF works with regards to accessing data (coming from a spring background)

我正在创建一个维护用户列表的简单示例,我有类似的内容

I'm creating a simple example that maintains a list of users, I have something like

<h:dataTable value="#{userListController.userList}" var="u">
    <h:column>#{u.userId}</h:column>
    <h:column>#{u.userName}</h:column>
</h:dataTable>

然后控制器"有类似的东西

Then the "controller" has something like

@Named(value = "userListController")
@SessionScoped
public class UserListController {
    @EJB
    private UserListService userListService;

    private List<User> userList;

    public List<User> getUserList() {
        userList = userListService.getUsers();
        return userList;
    }
}

而服务"(虽然它看起来更像是一个 DAO)有

And the "service" (although it seems more like a DAO) has

public class UserListService {

    @PersistenceContext
    private EntityManager em;

    public List<User> getUsers() {
        Query query = em.createQuery("SELECT u from User as u");
        return query.getResultList();
    }
}

这是正确的做事方式吗?我的术语对吗?服务"感觉更像是一个 DAO?并且控制器感觉它正在做一些服务的工作.

Is this the correct way of doing things? Is my terminology right? The "service" feels more like a DAO? And the controller feels like it's doing some of the job of the service.

推荐答案

这是正确的做事方式吗?

除了在托管 bean getter 方法中以低效的方式执行业务逻辑,以及使用过于广泛的托管 bean 范围之外,它看起来还可以.如果将服务调用从 getter 方法移动到 @PostConstruct 方法并使用 @RequestScoped@ViewScoped 而不是 @SessionScoped,看起来会更好.

Apart from performing business logic the inefficient way in a managed bean getter method, and using a too broad managed bean scope, it looks okay. If you move the service call from the getter method to a @PostConstruct method and use either @RequestScoped or @ViewScoped instead of @SessionScoped, it will look better.

我的术语对吗?

没关系.只要您与它保持一致并且代码以合理的方式可读.只有您命名类和变量的方式有点笨拙(不合逻辑和/或重复).例如,我个人会使用 users 而不是 userList,并使用 var="user" 而不是 var="u",并使用 idname 而不是 userIduserName.此外,UserListService"听起来它只能处理用户列表而不是一般用户.我宁愿使用UserService"因此您还可以使用它来创建、更新和删除用户.

It's okay. As long as you're consistent with it and the code is readable in a sensible way. Only your way of naming classes and variables is somewhat awkward (illogical and/or duplication). For instance, I personally would use users instead of userList, and use var="user" instead of var="u", and use id and name instead of userId and userName. Also, a "UserListService" sounds like it can only deal with lists of users instead of users in general. I'd rather use "UserService" so you can also use it for creating, updating and deleting users.

服务"感觉更像是一个 DAO?

它不完全是一个 DAO.基本上,JPA 是这里真正的 DAO.以前,当 JPA 不存在时,每个人都自己开发 DAO 接口,这样即使底层实现(普通的"JDBC,或旧的"Hibernate 等)发生变化,服务方法也可以继续使用它们.服务方法的真正任务是透明地管理事务.这不是 DAO 的责任.

It isn't exactly a DAO. Basically, JPA is the real DAO here. Previously, when JPA didn't exist, everyone homegrew DAO interfaces so that the service methods can keep using them even when the underlying implementation ("plain old" JDBC, or "good old" Hibernate, etc) changes. The real task of a service method is transparently managing transactions. This isn't the responsibility of the DAO.

并且控制器感觉它正在执行服务的一些工作.

我可以想象它在这个相对简单的设置中做到了这一点.然而,控制器实际上是前端而不是后端的一部分.该服务是后端的一部分,其设计方式应使其可在所有不同的前端(例如 JSF、JAX-RS、普通")中重用.JSP+Servlet,甚至 Swing 等.此外,特定于前端的控制器(也称为支持 bean"或演示者")允许您以特定于前端的方式处理成功和/或异常结果,例如在 JSF 的情况下,在服务抛出异常时显示faces 消息.

I can imagine that it does that in this relatively simple setup. However, the controller is in fact part of the frontend not the backend. The service is part of the backend which should be designed in such way that it's reusable across all different frontends, such as JSF, JAX-RS, "plain" JSP+Servlet, even Swing, etc. Moreover, the frontend-specific controller (also called "backing bean" or "presenter") allows you to deal in a frontend-specific way with success and/or exceptional outcomes, such as in JSF's case displaying a faces message in case of an exception thrown from a service.

总而言之,正确的方法如下:

All in all, the correct approach would be like below:

<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();
    }

}

您可以在此处找到使用规范 Java EE/JSF/CDI/EJB/JPA 实践的真实世界启动项目:Java EE 启动应用.

You can find here a real world kickoff project here utilizing the canonical Java EE / JSF / CDI / EJB / JPA practices: Java EE kickoff app.

这篇关于JSF 控制器、服务和 DAO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆