如何在servlet应用程序中实现服务层

mar*_*n72 1 java service servlets

假设我想为我的使用 servlet 的 web 应用程序创建一个服务层,我应该怎么做?(我没有使用 web 应用程序框架..所以,请耐心等待)。我应该将它实现为侦听器吗?该服务旨在进行数据库访问。也就是说,我应该能够从我的 servlet 调用

class MyServlet{
...
    doPost(...){
    ...
        MyEntity entity = dbAccessService.getMyEntity(someId);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

dbAccessService 应该在哪里处理休眠会话、事务等。以前我曾经在 dao 方法中完成所有这些,但我被告知这不是一个好主意。

欢迎任何建议

谢谢

标记

下面给出了示例代码片段

    class DBAccessServiceImpl{
    ...
        private MyEntity getMyEntity(Long id){
                Transaction tx = null;
                MyEntity me = null;
                Session session = HibernateUtil.getCurrentSession();
                try{
                    tx = session.beginTransaction();
                    return entitydao.findEntityById(id);
                }catch(RuntimeException e){
                    logger.info("problem occurred while calling findEntityById()");
                    throw e;
                }
            }
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个监听器来实例化DBAccessService

class MyAppListener implements ServletContextListener {

    @Override

    public void contextInitialized(ServletContextEvent ctxEvent) {

        ServletContext sc = ctxEvent.getServletContext();
        DBAccessService dbservice = new DBAccessServiceImpl();
        sc.setAttribute("dbAccessService",dbservice);

    }
}
Run Code Online (Sandbox Code Playgroud)

在 web.xml 添加监听器

...
<listener>

    <listener-class>myapp.listeners.MyAppListener</listener-class>

 </listener>
...
Run Code Online (Sandbox Code Playgroud)

hom*_*ome 5

假设您不想引入框架,有两个选项是有意义的(在我看来):

  1. 使用无状态 EJB 会话 bean 定义您的服务层。您需要一个 EJB 容器。
  2. 像往常一样使用 OO 语言,创建一个接口和一个相应的实现:

定义一个接口

public interface BusinessService {
    abstract public BusinessObject performSomeOperation(SomeInput input);
}
Run Code Online (Sandbox Code Playgroud)

和一个实现

public class BusinessServiceImpl implements BusinessService {
    public BusinessObject performSomeOperation(SomeInput input) {
        // some logic here...
    }
}
Run Code Online (Sandbox Code Playgroud)

您有多种选项可用于实例化服务。如果您从头开始使用一个小型应用程序,那么在您的 Web 应用程序中简单地实例化服务可能就足够了:

BusinessService service = new BusinessServiceImpl();
service.performSomeOperation(...);
Run Code Online (Sandbox Code Playgroud)

顺便说一句:稍后您可能想要重构和实现一些围绕服务实例化的抽象(工厂模式、依赖注入等)。此外,在大型系统中,您可能必须将服务层托管在其自己的基础架构上以实现可扩展性,以便您的 web 应用程序通过开放协议与服务层通信,无论是 RESTful 还是 Web 服务。

然而,未来看起来,如果应用程序增长,拥有定义业务功能的定义良好的接口将允许您“轻松”向前推进。

对您的更新的回应: 我不会将服务本身实现为侦听器,这是没有意义的。尽管如此,您的示例代码似乎是合理的,但您必须区分Service(在本例中DBAccessService)和实例化/检索它的方式(侦听器)。您实现的侦听器实际上扮演了能够查找特定服务的ServiceLocator的角色。如果您将服务的实例存储在 servlet 上下文中,您必须提醒服务实现必须是线程安全的。

你必须小心不要过度设计你的设计——只要你不能预见到更复杂的需求,就保持简单。如果它还不复杂,我建议使用简单的静态工厂方法封装实现:

public final class ServiceFactory {

    public static DBAccessService getDBAccessService() {
        DBAccessService service = new DBAccessServiceImpl();
        return service;
    }
}
Run Code Online (Sandbox Code Playgroud)

可以使用复杂的替代方案来实现ServiceFactory,现在有些人称之为反模式。但是只要您不想从依赖注入(等)开始,这仍然是一个有效的解决方案。服务实现DBAccessServiceImpl只能在一个地方(工厂)访问。正如我之前提到的 - 密切关注多线程......希望这会有所帮助!