什么是Design Patten? 简单来说Design Patten 就是一个常用的方案 在我们的开发过程中经常会遇到一些相同或者相近的问题每次我们都会去寻找一个新的解决方法为了节省时间提高效率我们提供一些能够解决这些常见问题的被证实可行的方案构成一个统一的资源库 一个Design Patten描述了一个被证实可行的方案这些方案非常普通是有完整定义的最常用的模式 这些模式可以被重用有良好的伸缩性而这些Design Patten的优势将在设计JEE应用时得到体现 ModelViewController a 问题 如果开发一个企业级应用只需要一种客户端的话那么一切都非常容易解决但真实情况是我们必须面对运行在各种设备上客户端象PDAWAP浏览器以及运行在桌面上的浏览器我们不得不开发不同的应用程序来处理来自不同客户端的请求数据访问与现实将混淆在一起可能会出现重复的数据访问导致整个开发周期没有必要的延长 b 建议的解决方法 ModelViewController (MVC) 开发模式被证明是有效的处理方法之一它可以分离数据访问和数据表现你可以开发一个有伸缩性的便于扩展的控制器来维护整个流程如图所示为整个模式的结构MVC模式可以被映射到多层企业级的JEE应用上 § 所有的企业数据以及商业逻辑可以作为模式 § 视图可以通过模式访问数据并根据客户端的要求来显示数据视图必须保证当模式改变的时候数据显示也必须同时改变 § 控制器用来结合模式和视图把客户端来的请求转换成模式能够理解并执行的请求并且根据请求以及执行结果来决定下一次显示那一个视图 根据以上的逻辑你可以象这样建立一个应用 § 应用的商业逻辑由MVC中的模式也就是EJB来表现模式必须处理由控制器传递过来的对数据的访问请求 § 多个页面组成了MVC中的视图这些视图必须随模式一起更新 § 控制器是一系列接收用户动作的对象他们把用户的请求转换成模式可理解的请求并决定显示那一个页面当模式处理完请求后 c 要点 § MVC结构适用于那些多用户的可扩展的可维护的具有很高交互性的系统 § MVC可以很好的表达用户的交互和系统模式 § 很方便的用多个视图来显示多套数据是系统很方便的支持其他新的客户端类型 § 代码重复达到最低 § 由于分离了模式中的流控制和数据表现可以分清开发者的责任另外也可以加快产品推向市场的时间 Front Controller a 问题 MVC给出了一个整个应用的松散的耦合架构现在来看一下这样一个经常发生的情况在某一个应用中用户看到的视图和他所做的操作密切相关这是一些具有高度交互性的页面而这些页面之间含有高度的依赖性在没有任何模式的时候这个应用只是一个许多独立的页面的集合维护和扩展变得异常困难 § 当一个页面移动后其他含有这个页面链接的文件都必须修改 § 当有一系列页面需要口令保护时许多配置文件需要修改或者页面需要包含新的标记 § 当一个页面需要一个新的表示层时页面中的标记要被重新安排 当这个系统变得复杂时这些问题将变得更糟如果用MVC来解决的话就变成一个如何管理控制器和视图之间交互的问题 b 建议的解决方法 前台控制模式可以解决这个问题这个模式中所有的请求都被传送到一个对象中这个主要的对象将处理所有的请求决定以后显示那一个视图以及实现必要的安全需求对于把视图显示以及其他功能实现集中到一个主要的对象中将使修改变得很容易对应用的修改可以在所有视图中反映出来 c 要点 § 这个模式对于需要在多个含有动态数据的页面之间进行复杂导航的系统来说是很有效的 § 这个模式对于要在所有页面中都包含模板转换等的应用来说也是很有效的 § 由于视图的选择集中在前端控制器上因此视图的导航变得更加容易理解和便于配置 § 视图重用和变更会更加容易 § 视图之间的复杂交互使得控制器变得复杂从而当应用发展的时候控制器将变得难以维护不过大部分情况下可以用XML映射来解决 § 实现应用要求的安全性检验变得很简单 § 这个模式不适合小型的只显示静态内容的应用 d 样例 § RequestMappingsxml 文件映射了传入的请求处理器以及下一个页面 useRequestHandler=true requiresSecurityCheck=true nextScreen=screenjsp> comblahblahblahrequestHandler 以上这个文件是控制器的指定配置控制器的代码如下 § FrontControllerImpljava 利用上面的XML实现了控制器 // all required imports // exceptions to be caught appropriately wherever applicable public class FrontControllerImpl extends HttpServlet { // all required declarations definitions private HashMap requestMappings; public void init() { // load the mappings from XML file into the hashmap public void doPost(HttpServletRequest request HttpServletResponse response) throws IOException ServletException { doGet(request response); } public void doGet(HttpServletRequest request HttpServletResponse response) throws IOException ServletException { String currentPage= requestgetPathInfo(); // get all mapping info for currentPage from the hashmap // if securityCheckRequired = true do the security check // if useRequestHandler = true pass on the incoming request to the specified handler // forward the results to the given nextScreen } } 用这种方法实现的控制器将很容易维护当应用有新的变动的时候只要修改XML文件就能解决了前台控制模式将使在视图和控制器之前有复杂交互的JEE应用变得简单 Session Fa?ade a 问题 前台控制给出了一个基于MVC的能有效管理用户与JEE应用之间进行的复杂交互这个模式可以使处理页面的现实顺序和用户的并发请求变得简单并且使增加和改变页面现实变得更加容易 另外一个常见的问题是当EJB或者业务逻辑发生变化的时候应用的客户端也必须随之改变我们来看一下这个问题 一般来说为了表现一个账户中的用户我们使用一个业务逻辑来表示账户中的信息象用户名和口令再用一个EJB来管理用户的个人信息象爱好语言等当要创建一个新的账号或者修改一个已经存在的账号时必须访问包含账号信息的EJB读取个人信息修改并且保存这样的一个流程 当然这只是一个非常简单的例子实际情况可能比这个复杂的多象查看用户定制了哪些服务检验客户信用卡的有效性存放订单等在这个案例中为了实现一个完整的流程客户端必须访问账户EJB来完成一系列适当的工作下面的例子显示了一个Servlet客户端如何来控制一个用户订单 A servlet that does the workflow required for placing an order // all required imports; // exceptions to be caught appropriately wherever applicable; // This servlet assumes that for placing an order the account and // credit status of the customer has to be checked before getting the // approval and committing the order For simplicity the EJBs that // represent the business logic of account credit status etc are // not listed public class OrderHandlingServlet extends HttpServlet { // all required declarations definitions public void init() { // all inits required done here } public void doPost(HttpServletRequest request HttpServletResponse response) throws IOException ServletException { // other logic as required // Get reference to the required EJBs InitialContext ctxt = new InitialContext(); Object obj = ctxtlookup(java:comp/env/ejb/UserAccount); UserAccountHome acctHome = (UserAccountHome) PortableRemoteObjectnarrow(obj UserAccountHomeclass); UserAccount acct = acctHomecreate(); obj = ctxtlookup(java:comp/env/ejb/CreditCheck); CreditCheckHome creditCheckHome = (CreditCheckHome) PortableRemoteObjectnarrow(obj CreditCheckHomeclass); CreditCheck credit = creditCheckHomecreate(); obj = ctxtlookup(java:comp/env/ejb/Approvals); ApprovalsHome apprHome = (ApprovalsHome) PortableRemoteObjectnarrow(obj ApprovalsHomeclass); Approvals appr = apprHomecreate(); obj = ctxtlookup(java:comp/env/ejb/CommitOrder); CommitOrderHome orderHome = (CommitOrderHome) PortableRemoteObjectnarrow(obj CommitOrderHomeclass); CommitOrder order = orderHomecreate(); // Acquire the customer ID and order details; // Now do the required workflow to place the order int resul |