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

时间:2011-07-30 05:28:41

标签: java servlets service

假设我想为使用servlet的Web应用程序创建一个服务层,我应该怎么做?(我没有使用Web应用程序框架。所以,请耐心等待。)我应该将其实现为一个监听器?该服务是为了进行数据库访问。也就是说,我应该可以从我的servlet中调用

class MyServlet{
...
    doPost(...){
    ...
        MyEntity entity = dbAccessService.getMyEntity(someId);
        ...
    }
}

dbAccessService应该处理hibernate会话,事务等等。以前我曾经在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;
                }
            }
    ...
}

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

class MyAppListener implements ServletContextListener {

    @Override

    public void contextInitialized(ServletContextEvent ctxEvent) {

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

    }
}

在web.xml中添加侦听器

...
<listener>

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

 </listener>
...

2 个答案:

答案 0 :(得分:4)

假设您不想引入框架,我认为有两个选项是有道理的:

  1. 使用无状态EJB会话bean定义服务层。您需要一个EJB容器。
  2. 在OO语言中一如既往地做,创建一个接口和相应的实现:
  3. 定义界面

    public interface BusinessService {
        abstract public BusinessObject performSomeOperation(SomeInput input);
    }
    

    并实施

    public class BusinessServiceImpl implements BusinessService {
        public BusinessObject performSomeOperation(SomeInput input) {
            // some logic here...
        }
    }
    

    您可以使用多种方法来实例化服务。如果您从头开始使用小型应用程序,只需在Web应用程序中实例化服务即可:

    BusinessService service = new BusinessServiceImpl();
    service.performSomeOperation(...);
    

    BTW:稍后您可能想要围绕Service实例化(工厂模式,依赖注入等)重构和实现一些抽象。此外,在大型系统中,您可能必须在其自己的基础架构上托管服务层以实现可伸缩性,以便您的webapp通过开放协议与服务层进行通信,无论是RESTful还是Web服务。

    然而,未来看起来,如果有一个明确定义的业务功能接口,可以让您在应用程序增长时“轻松”前进。

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

    您必须小心不要过度设计您的设计 - 只要您无法预见更复杂的要求,请保持简单。如果它还不复杂,我建议使用一个简单的静态工厂方法封装实现:

    public final class ServiceFactory {
    
        public static DBAccessService getDBAccessService() {
            DBAccessService service = new DBAccessServiceImpl();
            return service;
        }
    }
    

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

答案 1 :(得分:2)

您建议的内容与在DAO中执行会话和事务处理没有什么不同。毕竟,您的服务类调用DAO;对于客户端代码,没有区别。

相反,我怀疑那个告诉你不要把会话处理放在DAO中的人认为你应该使用Open Session In View模式。非常简单地,以其通常的形式,涉及编写Filter,它打开会话并在将请求传递到链之前启动事务,然后提交事务(或在必要时将其回滚)并关闭会话请求完成后这意味着在任何一个请求中,对持久对象的所有访问都发生在单个事务和单个会话中,这通常是执行它的正确方法(这当然是最快的方式)。