不久前在Jdon网站看到一篇很久的文章,说的是一个小型的Web项目中对MVC的简单实现,核心的观点就是:
1.只有一个Controller的servlet 类
2.一个Service接口
3.一些实现Service接口的类
其中Controller类是一个核心的请求分发器,用于对请求进行分配,Service是一个接口,其下有若干个实现类,每个Service实现类其实就是一个具体的业务层逻辑。我注意到其中关于控制的一段核心代码是这样的:
try {
//TODO:hashmap to reduce the generated instance?
Class serviceClass = Class.forName(serviceName);
Service service = (Service) serviceClass.newInstance();
service.execute(request, response, servletcontext);
} catch (ClassNotFoundException classnotfoundexception) {
throw new ServletException(classnotfoundexception.getMessage());
} catch (IllegalAccessException illegalaccessexception) {
throw new ServletException(illegalaccessexception.getMessage());
} catch (Exception exception) {
throw new ServletException(exception.getMessage());
}
forward(request, response, targetName);
可以看到它是采用类的动态加载的方式来获取服务,服务的类型来自于请求的URL,也就是说每个请求后面都会付着一个ServiceName。
个人觉得这是一个不错的MVC实现。实际上是采用了Command模式。
下面是我对这种方法的一个扩展:(目前仅限于想法,还没有具体的实现)
·DispatchServlet:
该Servlet是核心控制Servlet,在容器启动时即被加载,所有的请求都首先被该Servlet所捕捉,根据该请求的类型转发给相应的子控制器。
·SubController:
当服务比较多且多数的请求可以被归类成对某一类型的请求时,我们推荐使用SubController(注意:此处的SubController是一个总称,代表了对应于各个服务类型的请求,实际中可能有UserController、JobController类等)。这样当中心Servlet将请求转交到SubController之后,可以由子控制器决定要调用服务层的那个方法。同时可以在此处根据业务需要,设置一些参数,用于控制或指定业务层的业务逻辑处理流程。
·Service:
Service是eFrame中一个核心的接口,它代表了面向客户的一系列操作集合,如果从设计模式上看可以看成是Facade模式,屏蔽了用户和多个底层类的直接交互。Service接口有一个ServiceResult execute(Message message)方法,它接受一个Message对象作为服务的参数。并返回一个ServiceResult对象,告诉调用者服务的执行结果和具体内容。
·NonStatusService:
无状态服务,代表了一次短期完成、不会被打断的服务。其下有一子类:
·HTTPService:
HTTP服务类,代表了一次HTTP Call,通常是控制器将请求,上下文参数传给该服务,该服务在实现了业务逻辑后,将响应输出至页面
·StatusService:
有状态服务,代表了一次长时间运行、可能会被随时中断的后台操作,例如从后台数据库中取出一批数据发送到客户端,该服务除了具备其父类的execute方法,还具备了一个表示服务当前状态的标志,以及启动、停止、执行服务的方法。
·MMSService:
有状态服务的一个例子,该例子是用于从后台数据库中取出一批数据,然后采用多线程的方式向服务器发送数据由于发送量比较大,可能会被中途中断。所以系统需要记录该服务的起始时间、当前状态。
·ServiceResult:
ServiceResult代表了一次服务的执行结果,它具有两个常量:SUCCESS和FAILED。分别代表了一次服务的成功执行和失败。除此之外它还拥有一个用于记录执行具体结果或返回值的HashMap对象:ResultDetail。
·ServiceLocator:
ServiceLocator是一个服务定位器,用于根据服务类的全称或者JNDI名称查找相应的服务类对象,这是一个接口。在其下有一个Service locate(String servieName)方法,用定位服务对象。
·ClassLoaderServiceLocator:使用Java的动态加载机制、反射机制创建服务对象
·JNDIServiceLocator:使用JNDI方式查找加载服务
·ServiceManager:
ServiceManager是一个接口,它用于管理系统中存在的各个Service对象。由于Service对象多数采用动态加载或JNDI查询的方式产生,所以再性能上会比较慢,由于该类中包含了一个HashMap对象,所有生成的Service对象都会被缓存到其中,所以我们可以对运行时刻的Servcie对象具有完全的控制。
ServiceManager接口包含下列方法:
·register(String serviceId, Service service):注册一个服务
·get(String serviceId):获取一个Service对象
·remove(String serviceId):移除一个Service对象
·clear():清空所有的Service对象
ServiceManager有两个实现类,分别对应于无状态服务和有状态服务的管理
·NonStatuesServiceManager:
实现了ServiceManager接口的所有方法
·StautsServiceManager:
除了实现接口的方法之外,还具备了对服务状态的记录,服务的启动、停止的管理
·start(String serviceId):启动一个服务
·stop(String serviceId):停止一个服务
·getStatus(String serviceId):获取一个服务
·Message:
Message类代表了一次服务执行中调用者向执行者传递的消息。它包含了以下几个元素:
·messageFrom:消息的来源
·messagTo:消息的接收者
·action:消息的目标动作
·paramters:消息的目标动作执行时所需的参数
此外Message还具备以下方法:
·设置/获取消息的来源
·设置/获取消息的目的地
·设置/获取消息的目标动作
·设置/获取消息的目标动作所需参数
对Message对象的创建和传递通常发生在子控制器调用相应的业务逻辑之前
·AbstractFactory:
AbstractFactory是一个抽象工厂类,它代表了一个能够根据用户需求而产生出不同类型对象的工厂,它具有一个抽象的方法
·public abstract Product getProduct(String productType):返回一个指定类型的产品
AbstractFactory下可以有多个继承的子类,这些继承的子类都集中于某一类型构建,比如说DaoFactory类
·DaoFactory:
DaoFactory类是继承了AbstracFactory类的子类,它的目标集中于DAO对象的构建,它返回的是一个实现了Product接口的Dao类实例
·Dao:
Dao类是一个抽象类,它具备了对数据库操作的一系列基本元素,包括获取数据库连接、获取执行语句,迭代结果集等等。它有3个抽象的方法。分别是:
·public abstract int insert(Object object):插入一个对象
·public abstract int modify(Object object):修改一个对象
·public abstract int delete(Object object):删除一个对象
由于Dao类对象也属于工厂中生产出来的产品,所以这里我们让Dao类实现了Product接口。Dao类下面可以有多个继承的子类。不同的子类对于如何插入、更新、删除一个对象是不同的。
·Product:
Product是一个虚拟的概念,它代表了一个从工厂中生产出来的产品。这个接口本身没有任何的方法
也就是说,每次Web层的请求的处理流程如下:
·Web请求
|--->DispatchServlet
|--->SubController
|--->Service
|--->SubService(NonStatusService / StatusService)
|--->DaoFactory
|--->Dao
|--->SubDao
|--Product
Web页面<----------------------------------- Domain|
其中在SubController加载相应的Service时,会将相应的参数封装在Message对象中传递给Service对象。服务在执行后会返回一个
ServiceResult对象表示执行的结果情况。
Servcie的加载就像上面提到的可以采用Class.forName,也可以采用JNDI的方式。
附录:Jdon论坛参考文章地址:一个小的WEB项目中的实现方法讨论
-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2008-01-09 17:30
Paul Lin 阅读(2609)
评论(6) 编辑 收藏 所属分类:
J2EE 框架