日期:2014-05-19  浏览次数:20762 次

J2EE 核心模式(Core J2EE Patterns)学习随心理解、随手记录(二)

我看的资料和这幅图有一些出入。

资料要去这里找:http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html

?

表现层模式

?

拦截过滤器Intercepting Filter。正如图中的“Apply zero or more”和Servlet规范所述一样,应当具备一个链式结构。这个链式结构中的每个filter,互相之间应当是一个互不依赖的松耦合关系,以便于容易地组合

?

前端控制器:Front Controller。给表现层请求安排一个集中访问点。集中了控制逻辑,一定程度避免了重复代码。和拦截过滤器的区别:拦截过滤器使用的是松耦合的,结合成链式的处理器逻辑,适合进行强大的预处理、后处理的策略分布;而前端控制器则专注于集中控制,减少视图中的业务和处理逻辑,提高重用度。

在常用的Struts网站构架中,N个拦截器都是可以自由组合的,也可以自定义合适的拦截器栈来继承某个通用的基础拦截器栈,一些通用的拦截逻辑变放置在基础拦截器栈中,这里是一个拦截过滤器和前端控制器结合实现的例子。

?

Context对象:不想在与协议无关的环境上下文中使用针对特定协议的系统信息。就是说系统信息,比如请求、配置和安全数据等等,这些东西,通常应当被隐藏起来,不能被业务逻辑看到;但是在某些情形下,业务组件可能又必须用到这些信息,例如,进行终端适配的组件,需要用到HTTP报文中的一些header,那么直接使用会导致组件的灵活性和可重用性的下降,导致前一篇我提到的表现层数据结构和业务层的紧耦合

解决方法就是制定一个特定的API,将业务组件需要的部分通过API来包装和筛选,而不是直接把表现层数据结构直接暴露给它。这样一来,对于表现层的一些改变,比如协议等方面的改变,不会直接影响到业务组件的接口和运行,只需要修正API的实现逻辑。

还有个什么好处?如果我需要测试业务层的逻辑,因为有了这样一层特殊的API,我可以把整个表现层mock掉

这里有一个应用例子就是RequestContext对象,API只传输这个,而不是具体的某一Request对象,对于复杂的请求层面被隔离掉,留下一个包装好的上下文给后面的逻辑。

?

应用控制器:集中地、模块化地进行操作管理和视图管理。

操作管理:把输入请求解析到一个操作(action),让它处理该请求。

视图管理:选定返回给客户端的视图,并把请求分派到这个视图。

这两点的应用例子其实就是在struts-xxx.xml里面定义的配置,如同一个路标,对于出入视图层的数据进行方向上的导航。

举例来说,它的实现经常采用的策略是command对象的策略,命令对象的说法具体可见GoF的那本经典设计模式的书。

效果:把操作管理和视图管理分离开了,提高了模块化程度;再一个这个导航的逻辑被抽取成为一处独立的配置单独维护,方便扩展。

?

视图助手:View Helper。把视图和相关处理逻辑分离开。

这里需要先提及两个重要的阶段:视图准备阶段:这是指请求被分配到一个具体的视图上面;视图创建阶段:视图根据从模型中取得的内容来实例化自己。

因此使用视图封装显示格式的代码,而使用助手封装视图处理逻辑。助手在视图和模型之间充当了一个适配器的角色,同时也会做一些格式逻辑相关的处理

一个很好的例子就是各种标签,包括自定义标签,比如一个时间格式化的标签,对于一个时间,在不同的环境下以不同的格式展示。

视图助手终究是“视图”的助手,它的核心始终是视图,对于已经生成了的成熟的具备一定模型的数据,试图助手协助将它们以某种合适的方式展示出来,而不应当做复杂或具体的业务逻辑。

于是这里提出第一点需要注意,怎样把视图助手和后端的逻辑区分开?视图助手得到的数据应当是已经成熟的一定模型化的数据,需要做的是仅仅是做一些格式的处理,对展示效果的修正和增强,并不做任何业务逻辑的相关事宜。

第二点需要注意,应当把视图助手和JavaScript区分开来,前者在服务端完成,后者在客户端完成:把处理逻辑从页面中抽取出来,一个重要原因就是要减少在页面中直接暴露的实现细节。在实际开发中,这二者之间的区分,常常带来困扰。比如在模板或者JSP中使用if标签,还是在客户端使用JavaScript来控制逻辑?我建议这里应当有一个区分的原则:这些逻辑是否属于客户端才能决策的页面展示细节?如果是,就使用JavaScript来完成,反之还是应当隐藏到页面助手中。

?

文章系本人原创,转载请注明作者和出处