假设我想为使用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>
...
答案 0 :(得分:4)
假设您不想引入框架,我认为有两个选项是有道理的:
定义界面
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,它打开会话并在将请求传递到链之前启动事务,然后提交事务(或在必要时将其回滚)并关闭会话请求完成后这意味着在任何一个请求中,对持久对象的所有访问都发生在单个事务和单个会话中,这通常是执行它的正确方法(这当然是最快的方式)。