现在把,没有一种共通的方法来用程序创建一个jee系统用户,各个容器厂家实现的方 法不同,你要是非要这么作,你就只能用这个平台了,不过,这就看你程序写的活不活 了,你写活点,尽量让这部分可以拔插,以便以后的更改平台时变化。(题外话,据说最 新的j2ee的jas提出了一套登陆和验证的规范,哥几个可以研究1下去) 看图把,这是一个用户登陆和注册的活动图(题外话,啥叫活动图,说白了就是一个实 例的一个动作周期),页面有两种,受保护的,不受保护的。访问受保护的页面需要登陆 Store roquest Show [User Signed On Create User request signon creato Create User Customer [Failed) [Falled] Show Invalid Creation Error 当一个用户请求保护页面的时候,应用系统判断用户是否登陆了。如果用户没有登陆, 应用系统先保存这个请求地址,然后导向到登陆界面 登陆界面提供两个功能 已经注册的用户可以登陆 页面验证客户的用户名和保密字,如果fai了,显示错误页 注册一个新用户 如果客户要创建一个新的用户,让他填写各种注册信息。然后创建,如果创建 成功,回显这些信息,否则,跳转到错误页。 如果登陆注册成功后,应用系统会把保存在 session中的信息和URL取出,跳转到那个 URL中,让用户继续购物。 用户登陆和客户登记模块实 用户的登陆处理时通过WAF组件, SignonFilter,实现的。它探测到哪些请求是导向受 保护页面的。 SignOnFilter组件是一个 servlet过虑器,它可以捕获任何的请求,在请求之前作一些预 理,也可以被挂在被请求被相应之后,作一些善后处理 宠物店应用中,一些页面,只有登陆才能看,那,到底是哪些页面呢,呵呵,别着急
现在把,没有一种共通的方法来用程序创建一个 j2ee 系统用户,各个容器厂家实现的方 法不同,你要是非要这么作,你就只能用这个平台了,不过,这就看你程序写的活不活 了,你写活点,尽量让这部分可以拔插,以便以后的更改平台时变化。(题外话,据说最 新的 j2ee 的 jaas 提出了一套登陆和验证的规范,哥几个可以研究 1 下去)。 看图把,这是一个用户登陆和注册的活动图(题外话,啥叫活动图,说白了就是一个实 例的一个动作周期),页面有两种,受保护的,不受保护的。访问受保护的页面需要登陆: 《图 15》 当一个用户请求保护页面的时候,应用系统判断用户是否登陆了。如果用户没有登陆, 应用系统先保存这个请求地址,然后导向到登陆界面。 登陆界面提供两个功能: ⚫ 已经注册的用户可以登陆: 页面验证客户的用户名和保密字,如果 fail 了,显示错误页。 ⚫ 注册一个新用户 如果客户要创建一个新的用户,让他填写各种注册信息。然后创建,如果创建 成功,回显这些信息,否则,跳转到错误页。 如果登陆/注册成功后,应用系统会把保存在 session 中的信息和 URL 取出,跳转到那个 URL 中,让用户继续购物。 用户登陆和客户登记模块实现 用户的登陆处理时通过 WAF 组件,SignOnFilter,实现的。它探测到哪些请求是导向受 保护页面的。 SignOnFilter 组件是一个 servlet 过虑器,它可以捕获任何的请求,在请求之前作一些预处 理,也可以被挂在被请求被相应之后,作一些善后处理。 宠物店应用中,一些页面,只有登陆才能看,那,到底是哪些页面呢,呵呵,别着急
都在 signon- config. xml文件中定义了, SignOnFilter会看你请求的是不是 signon-config xml 中规定的保护页面。 看图把 《图16》 SignOn Filter page [not signed on protected] protected] 与 [|[ n form SignonFilter捕获到一个请求,无非就三种情况 是个登录请求,好,那我就去读取请求传过来参数:用户名,保密字。然后使用无状 态 SignOnEJE到User实体EB去核实用户名和保密字是否匹酯 b.如果是个普通的不受保护的页面,那么直接导向 c如果是个手保护的页面,而且,用户没有登陆, Signon Filter先把请 求得URL保存起来,并且导向到 Signon页面 当然, SignOnFilter只处理己经注册得用户,对于没有注册得用户得创建,下面讲,呵呵 用户和客户的创建的实现 个客户是由好几个实体EJB组成的。User的EJB代表了客户的用户名和保密字。其他 的实体Eb代表了客户, profile,帐户,联系信息,地址和信用卡。(这几句不太会翻译) 用户创建 宠物店使用WAF来创建一个新用户,你可以看到一个很好的waf被扩展功能的好方法 下图展示了创建一个宠物店用户用到的所有的WAF相关的类和接口。一个URL请求一 来, RequestProcessor创建和执行一个 HTML Action(这里是 CreateUserHTMLAction), 来执行所有的web层的处理。由于真正的创建的处理在EJB层, CreateUserhTMlAction 仅仅返回一个事件( CreateUser event, RequestProcess会把这个事件传递给web端的控制 器( WebClientcontroller),Web端的控制器然后传递给EJB端的控制器(有状态的EJB: EJBClient Con trollerEjB)。EJB端的控制器然后,找到相应的 EJBAction来完成真正的商 业处理。这个流程是由WAF框架类来处理的,而业务相关的处理是由开发者自己编写的 代码完成
都在 signon-config.xml文件中定义了,SignOnFilter 会看你请求的是不是 signon-config.xml 中规定的保护页面。 看图把, 《图 16》 SignOnFilter 捕获到一个请求,无非就三种情况贝: a.是个登录请求,好,那我就去读取请求传过来参数:用户名,保密字。然后使用无状 态 SignOnEJB 到 User 实体 EJB 去核实用户名和保密字是否匹配。 b.如果是个普通的不受保护的页面,那么直接导向 c.如果是个手保护的页面,而且,用户没有登陆,SignOnFilter 先把请 求得 URL 保存起来,并且导向到 SignOn 页面。 当然,SignOnFilter 只处理已经注册得用户,对于没有注册得用户得创建,下面讲,呵呵。 用户和客户的创建的实现 一个客户是由好几个实体 EJB 组成的。User 的 EJB 代表了客户的用户名和保密字。其他 的实体 Ejb 代表了客户,profile,帐户,联系信息,地址和信用卡。(这几句不太会翻译) 用户创建 宠物店使用 WAF 来创建一个新用户,你可以看到一个很好的 waf 被扩展功能的好方法。 下图展示了创建一个宠物店用户用到的所有的 WAF 相关的类和接口。一个 URL 请求一 来,RequestProcessor 创建和执行一个 HTML Action(这里是 CreateUserHTMLAction), 来执行所有的 web 层的处理。由于真正的创建的处理在 EJB 层,CreateUserHTMLAction 仅仅返回一个事件(CreateUserEvent),RequestProcess 会把这个事件传递给 Web 端的控制 器(WebClientController),Web 端的控制器然后传递给 EJB 端的控制器(有状态的 EJB: EJBClientControllerEJB)。EJB 端的控制器,然后,找到相应的 EJBAction 来完成真正的商 业处理。这个流程是由 WAF 框架类来处理的,而业务相关的处理是由开发者自己编写的 代码完成
gp:EvenIName EJBAction perform WebClientControllerimpl reateUscrEJBAction a controller thandleEvun I CreateUsorHTMLAction <creates SignOn == 好,让我们看看交互图把 1。创建一个用户的请求是 createuser. do,web的配置文件 web.xm中把*do的 请求都映射到了 Main Servlet上 巴上w[rs c CreateUser scsessionpplccentit EJBAction SiqnOnEJB 2: create 4: cr 11: create 2。下面的从请求映射文件 mapping xml摘要,说明了这个URL请求 createuser.do 将要被( reateUserhTMLAction处理,并且说明了,处理完了以后,跳转到 create customer screen屏幕去。 <url-mapping url"createuser. do"screen- <action-class com.sun j2ee blueprints. petstore controller. web. actions. CreateUserHTMLAction 请求处理器 RequestProcessor在xml文件中寻找到 createuser do对应的 CreateUserHTMLAction类,创建之 3。请求处理器 RequestProcessor调用 CreateUserhTmlaction的 perform(方法 4。 CreateUserhTmlaction的 performo方法创建 CreateUser event事件,把用户 名和保密字,然后发挥这个事件给请求处理器 RequestProcessor这个事件封装了 一个命令,将来要传递到EB端的控制器(ECC)以真正完成创建工作。 5。请求处理器 RequestProcessor传递这个事件给一个WEB层的控制器 (WebClientController) 6。WEB层控制器只是个代理,它立刻把事件转手给了EJB层的控制器 (Shopping ClientControllerEJB)
好,让我们看看交互图把, 1。创建一个用户的请求是 createuser.do,web 的配置文件 web.xml 中把*.do 的 请求都映射到了 MainServlet 上。 2。下面的从请求映射文件 mapping.xml 摘要,说明了这个 URL 请求 createuser.do 将要被 CreateUserHTMLAction 处理,并且说明了,处理完了以后,跳转到 create_customer.screen 屏幕去。 com.sun.j2ee.blueprints.petstore.controller.web.actions.CreateUserHTMLAction 请 求 处理 器 RequestProcessor 在 xml 文 件中 寻 找到 createuser.do 对应的 CreateUserHTMLAction 类,创建之。 3。请求处理器 RequestProcessor 调用 CreateUserHTMLAction 的 perform()方法。 4。CreateUserHTMLAction 的 perform()方法创建 CreateUserEvent 事件,把用户 名和保密字,然后发挥这个事件给请求处理器 RequestProcessor.这个事件封装了 一个命令,将来要传递到 EJB 端的控制器(ECC),以真正完成创建工作。 5。请求处 理器 RequestProcessor 传递这 个事件给 一个 WEB 层的 控制器 (WebClientController). 6。WEB 层控制器只是个代理,它立刻把事件转手给了 EJB 层的控制器 (ShoppingClientControllerEJB)
7。然后把,EJB层的控制器就创建了个 CreateUserejbaction,这个 EBAction 中真正的创建了用户。每个事件中都有方法叫 get EventNameo,它表明了事件本 身的名字,EB层的控制器就通过这个名字到FJB层的控制器这个 sessionEJB 的 ejb-jar xm中,找到事件名字对应的 EJBAction类这样, CreateUserEJBAction 就可以被找到,里面封装了对用户的真正创建动作 CreateUserEvent java eturn "java: comp/env/param/event/CreateUserEvent": param/event/CreateUserEvent java. lang String CreateUserEJBAction</env-entry-values ts petstorecontroller ejb actions 8。EJB层的控制器调用 CreateUserejbaction的 process Event方法,方法的入参 是 CreateUser Event事件。 9 CreateUserEJBAction调用 CreateUser Event的 getUser Name和 getPassword得 到用户名和保密字。 10。 CreateUserEJBAction然后创建一个无状态 EJB: SignOnEJB,来创建/认证用 l1。 CreateUserEJBAction创建User实体EJB,用来保存用户和它的保密字。 一旦用户被创建,下一步就是创建一个客户实体( Customer entities) 客户创建 创建完一个用户user)后,要创建一个客户( customer)。WAF会导向你进入 后台的EB层的处理会创建一个和User实体EJB的内部连接,是通过 Customer 中useD保存他们的关系 客户 customer)的创建其实和用户(user)的创建过程一样 基于 mappings. xml,请求处理器 RequestProcessor找到请求“ customer.do” 对应的 CustomerhTmlaction类,然后创建它,然后调用它的 performo方法 2 CustomerHTMLActionperformo方法构建并返回一个 Customer Event事件类, 包含了创建客户必须的各种信息 3.请求处理器 RequestProcessor把 Customer Event事件传递给web层控制器 4.在容器的环境变量中获得 Customer event事件对应的 EJBAction处理类 Customerejbaction,EJB端控制器创建它,然后把 Customer event事件创给它 的 handle event方法,执行 5.读取 Customer Event事件中封装的数据, Customer EjBAction hand leEven)方 法创建一个 Customer实体EJB和相关的实体EJB 6.然后 CustomerhTMLAction do endo方法会被调用,用来完成用户的自动登陆 7.屏幕流程控制器,然后导向到屏幕 customer screen,用来回显客户的所有创建 信息给用户
7。然后把,EJB 层的控制器就创建了个 CreateUserEJBAction,这个 EJBAction 中真正的创建了用户。每个事件中都有方法叫 getEventName(),它表明了事件本 身的名字,EJB 层的控制器就通过这个名字到 EJB 层的控制器这个 sessionEJB 的 ejb-jar.xml 中,找到事件名字对应的 EJBAction 类。这样,CreateUserEJBAction 就可以被找到,里面封装了对用户的真正创建动作。 8。EJB 层的控制器调用 CreateUserEJBAction 的 processEvent 方法,方法的入参 是 CreateUserEvent 事件。 9。CreateUserEJBAction 调用 CreateUserEvent 的 getUserName 和 getPassword 得 到用户名和保密字。 10。CreateUserEJBAction 然后创建一个无状态 EJB:SignOnEJB,来创建/认证用 户。 11。CreateUserEJBAction 创建 User 实体 EJB,用来保存用户和它的保密字。 一旦用户被创建,下一步就是创建一个客户实体(Customer entities)。 客户创建 创建完一个用户(user)后,要创建一个客户(customer)。WAF 会导向你进入 create_customer.screen 屏幕。填写客户登记的各种信息,的,填完了,就提交把。 后台的 EJB 层的处理会创建一个和 User 实体 EJB 的内部连接,是通过 Customer 中 userID 保存他们的关系。 客户(customer)的创建其实和用户(user)的创建过程一样: 1. 基于 mappings.xml,请求处理器 RequestProcessor 找到请求“customer.do ” 对应的 CustomerHTMLAction 类,然后创建它,然后调用它的 perform()方法。 2.CustomerHTMLAction.perform()方法构建并返回一个 CustomerEvent 事件类, 包含了创建客户必须的各种信息。 3. 请求处理器 RequestProcessor 把 CustomerEvent 事件传递给 Web 层控制器. 4. 在容器的环境变量中获得 CustomerEvent 事件对应的 EJBAction 处理类 CustomerEJBAction,EJB 端控制器创建它,然后把 CustomerEvent 事件创给它 的 handleEvent()方法,执行。 5. 读取 CustomerEvent 事件中封装的数据,CustomerEJBAction.handleEvent()方 法创建一个 Customer 实体 EJB 和相关的实体 EJB. 6. 然后 CustomerHTMLAction.doEnd()方法会被调用,用来完成用户的自动登陆 功能。 7. 屏幕流程控制器,然后导向到屏幕 customer.screen,用来回显客户的所有创建 信息给用户
1.1.11异步消息模块 宠物店 stateless session EJB格式化订单成为一个xml文件流,并传送给 Order processing Center(OPC来处理 异步消息模块需求 宠物店和OPC之间的交互要求 通讯必须是异步的,因为订单的处理需要花费很长时间,购物过程不能在这里等待消息的传输 必须可以信赖宠物店发送一份订单要保证OPC能受到这份订单来处理 如果OPC不可用这些订单需要被保存起来等opc恢复了,再取出处理 宠物店和OPC之间的接口必须灵活对于opc和宠物店两端应该容易改变 opc的客户端甚至可以不是java程序书写 每个订单必须有全局唯一标识 异步消息模块实现 WAF开始创建一个购物订单然后传给OPC,使用 WebAction, EBEvent, EjbAction当一个用户第 次请求购买购物车里面的内容,会激活 signon过滤器,来确保用户己经登录,并且组装模板来 完成响应界面- enter order information. screenjSP页面包含了订单的其他信息,然后激活 order. do请求通过 mapping. xm中的请求映射wAF来创建一个 OrderhTMlAction,它负责产生 一个 Order Event,这个 Event会送给EJB层的 OrderEJBAction来处理 个流程图表明了这个过程 Orderejbaction执行EJB层的商业逻辑处理并且传输一个 PO(purchase order)对象(是个XML流)给OPC,是通过JMS给的图中显示的 Action类创建一个 新的购买订单它使用 Unique GeneratorEJB来创建一个全局唯一的 orderID并且,这个订单中还 有用户的运送地址,信用卡号码,这些信息实际上都是从 Order event中获得的 Orderejbaction 会重复的读取购物车中的内容把这些内容加入到购买订单中 EJBAction (EJB tier I(EJB tier OrderQueue EJBActions NS EJB>> Factory Order D 最后, Orderejbaction创建一个 AsynHelper来发送订单的XML内容给 OPC. AnsynHelper是 个商业代理( bussiness delegate-j2eeDP),它提供一个消息发送的服务同时封装了 lookup和消息 传送的细节 Asynchelper通过 JMSLocator找到消息队列,并且使用 AsyncSenderejB的 stateless ession ejb来发送XML消息然后呢OPC的异步消息Bean(MDB)会受到这个XML消息,当 然宠物店仍然继续响应着其他的请求呢宠物店根本不维护它创建过哪些 Order的历史信息 些都由OPC来做了 O类代表了购买的订单,有 orderly, userIdD,发送地址订单的货物条目等信息它有个 toXMLO 方法用来产生一个XML字符流这个XML流将通过 Asynchelper类发送一个 JMS text消息 消息队列当OPC接受到xml消息它创建和初始化一个新的OP实例用XML消息中内容
1.1.1.1 异步消息模块 宠物店 stateless session EJB 格式化订单成为一个 xml 文件流,并传送给 Order Processing Center(OPC)来处理. 异步消息模块需求 宠物店和 OPC 之间的交互要求: .通讯必须是异步的,因为订单的处理需要花费很长时间,购物过程不能在这里等待.消息的传输 必须可以信赖,宠物店发送一份订单,要保证 OPC 能受到这份订单来处理 • 如果 OPC 不可用,这些订单需要被保存起来,等 opc 恢复了,再取出处理 • 宠物店和 OPC 之间的接口必须灵活,对于 opc 和宠物店两端应该容易改变 • opc 的客户端甚至可以不是 java 程序书写 • 每个订单必须有全局唯一标识 异步消息模块实现 WAF 开始创建一个购物订单然后传给 OPC,使用 WebAction,EJBEvent,EjbAction.当一个用户第 一次请求购买购物车里面的内容,会激活 signon 过滤器,来确保用户已经登录,并且组装模板来 完成响应界面--enter_order_information.screen.JSP 页面包含了 订单的其 他信息, 然后激活 order.do 请求.通过 mapping.xml中的请求映射,WAF 来创建一个 OrderHTMLAction,它负责产生 一个 OrderEvent,这个 Event 会送给 EJB 层的 OrderEJBAction 来处理. 一个流程图表明了这个过程.OrderEJBAction 执行 EJB 层的商业逻辑处理并且传输一个 PO(purchase order)对象(是个 XML流)给OPC,是通过 JMS 给的.图中显示的,Action 类创建一个 新的购买订单.它使用 UniqueGeneratorEJB 来创建一个全局唯一的 orderID.并且,这个订单中还 有用户的运送地址,信用卡号码,这些信息实际上都是从 OrderEvent 中获得的.OrderEJBAction 会重复的读取购物车中的内容,把这些内容加入到购买订单中. 最后,OrderEJBAction 创建一个 AsynHelper 来发送订单的 XML 内容给 OPC.AnsynHelper 是一 个商业代理(bussiness delegate-j2eeDP),它提供一个消息发送的服务,同时封装了 lookup 和消息 传送的细节.AsyncHelper 通过 JMSLocator 找到消息队列,并且使用 AsyncSenderEJB 的stateless session EJB 来发送 XML 消息.然后呢,OPC 的异步消息 Bean(MDB)会受到这个 XML 消息,当 然宠物店仍然继续响应着其他的请求呢.宠物店根本不维护它创建过哪些 Order 的历史信息, 这些都由 OPC 来做了. PO 类代表了购买的订单,有 orderID,userID,发送地址,订单的货物条目等信息.它有个 toXML() 方法用来产生一个 XML 字符流.这个 XML 流将通过 AsyncHelper 类发送一个 JMS text 消息 给消息队列.当 OPC 接受到 xml 消息,它创建和初始化一个新的 OP 实例,用 XML 消息中内容
填充OPOP有个 fromM0静态方法返回值是个OP这个函数里面就是把xml消息构造成 个DOM树然后从树中提取相应的数据来填充op当 fromXMLO方法解析XML消息时,DOM 析器通过购买订单提供的DTD验证ⅹML验证是通过解析器而不是程序来做的检查xml 档数据的完整性通过使用解析器的验证,开发者只是简单的使用DTD中规则来检验数据, 而不是自己写一大堆的验证代码此外,如果XML格式变了,验证规则也只需要改变传入的 DTD就可以轻松改变 1.1.12货架目录模块 货架目录模块需求 货架目录必须满足下面的要求 每个货架中的内容,都必须有唯一的标识,和简要的说明 一种产品( product),是一堆货架内容的集合,产品( product)有一个标识,名字和描 一个货架是一堆产品的集合,有个ID,名字,和描述 货架模块,需要提供一个只读的货架目录,产品,还有内容的分页显示机制。一页 是一个有长度,完全排序的一堆目录,产品,或者内容 目录组件可以被复用 必须可以不用程序而可以动态的添加和删除 用于货架目录的存储机制必须保证能容易改变 如果需要的话,货架目录模块应该很容易被转化成一个远程组件 货架目录模块的设计 下图是一个设计结构图。目录中包含多个产品,产品又包含多个货物内容 talogLocal getTO Category getStartolPrevious Page categones demko 设计的关键在于,使用了一个无状态的 sessionEjB,EB使用DAO对象,来访问后台的 货架目录数据。因为,这些货架目录数据基本上不更新,因此没有采用实体EB,而采 用DAO,直接访问数据库,提高访问速度 具体的设计
填充 OP,OP 有个 fromXML()静态方法,返回值是个 OP.这个函数里面就是把 xml 消息构造成一 个 DOM 树,然后从树中提取相应的数据来填充 op.当 fromXML()方法解析 XML 消息时,DOM 解析器通过购买订单提供的 DTD 验证 XML.验证是通过解析器而不是程序来做的,检查 xml 文档数据的完整性.通过使用解析器的验证,开发者只是简单的使用 DTD 中规则来检验数据, 而不是自己写一大堆的验证代码.此外,如果 XML 格式变了,验证规则也只需要改变传入的 DTD 就可以轻松改变. 1.1.1.2 货架目录模块 货架目录模块需求 货架目录必须满足下面的要求: ⚫ 每个货架中的内容,都必须有唯一的标识,和简要的说明 ⚫ 一种产品(product),是一堆货架内容的集合,产品(product)有一个标识,名字和描 述 ⚫ 一个货架是一堆产品的集合,有个 ID,名字,和描述 ⚫ 货架模块,需要提供一个只读的货架目录,产品,还有内容的分页显示机制。一页 是一个有长度,完全排序的一堆目录,产品,或者内容。 ⚫ 目录组件可以被复用。 ⚫ 必须可以不用程序而可以动态的添加和删除 ⚫ 用于货架目录的存储机制必须保证能容易改变 ⚫ 如果需要的话,货架目录模块应该很容易被转化成一个远程组件 货架目录模块的设计 下图是一个设计结构图。目录中包含多个产品,产品又包含多个货物内容。 设计的关键在于,使用了一个无状态的 sessionEJB,EJB 使用 DAO 对象,来访问后台的 货架目录数据。因为,这些货架目录数据基本上不更新,因此没有采用实体 EJB,而采 用 DAO,直接访问数据库,提高访问速度。 具体的设计:
目录,产品,货物内容都存储再数据库中 这些货物目录数据都存放再数据库,你可以用数据库的管理工具来维护数据 ●货架目录数据的读取被实现成一个无状态的 sessionEje 如果货架目录访问被实现成一个web端组件,譬如 servlet,那它只能被限制只能 提供给web应用使用。如果是写成一个类,那你还得自己维护数据库连接池和缓冲 等来提高访问性能。使用无状态的 sessionEjB,这些缺点都可以避免 ·货架目录,产品,货物内容都被实现成了一般的java类 为这些内容都是只读,没必要关心更新亚,事务亚等操作,用cjb的话,没有必 货架目录,产品,货物内容这些类需要序列化 因为以后可能要远程访问这些组件,所以需要序列化他们 使用DAO对象来读取它们 DAO模式提供了一个对数据的透明访问。货架目录这些数据不是通过EJB访问的 而是通过直接访问数据库。DAO模式隐藏了后台的数据源,方便你以后对数据源 的替换。(关于DAO模式,请参考p2e设计模式) 货架目录横块的实现 实现基本上就象设计中描述的, CatalogEjB是一个无状态的 session ejb,实现了 Catalog local接口。 Catalog local提供方法返回目录 (catagory),产品( product,内容(tem)。 Catalog Local同样提供一个 searchltemso方法,根据搜索条件来搜索相应的item CatalogEJB使用 Catalogdao来获取数据。 CatalogDAo由 Catalog Factory创建,这使得 DAO是"可插拔"的。一旦有新的目录数据的数据源,你可以编写一个这个数据源访问的 DAO,实现 CatalogDAo接口,修改厂的创建方法,用来返回新的数据源类型的DAO。当 前呢,我们使用的是通过jDBC访问的关系数据库数据源 1.113客户模块 CustomerModule) 客户模块需求 客户模块必须跟踪客户的自由定制(例如喜好的语言,最喜欢的目录等),联系信息, 信用卡信息 HTTP客户端和非HTTP客户端应该都能访问模块 客户的数据可以保持,并且通过客户关联的用户i来区分 客户的数据可以被其他的应用组件重用 客户模块需求 有三种方法来实现客户模块,本地的实体FB,一般的java类,远程的实体EJB 物店是用了本地的实体EB。这是因为它可以使用上pee的各种优势( CMP CMR.事务处理 等)。以前的版本使用的是远程EJB,改进成本地的EJB后,可以降低远程通讯的成本。 客户模块实现
⚫ 目录,产品,货物内容都存储再数据库中 这些货物目录数据都存放再数据库,你可以用数据库的管理工具来维护数据 ⚫ 货架目录数据的读取被实现成一个无状态的 sessionEJB 如果货架目录访问被实现成一个 web 端组件,譬如 servlet,那它只能被限制只能 提供给 web 应用使用。如果是写成一个类,那你还得自己维护数据库连接池和缓冲 等来提高访问性能。使用无状态的 sessionEJB,这些缺点都可以避免。 ⚫ 货架目录,产品,货物内容都被实现成了一般的 java 类 因为这些内容都是只读,没必要关心更新亚,事务亚等操作,用 ejb 的话,没有必 要 ⚫ 货架目录,产品,货物内容这些类需要序列化 因为以后可能要远程访问这些组件,所以需要序列化他们 ⚫ 使用 DAO 对象来读取它们 DAO 模式提供了一个对数据的透明访问。货架目录这些数据不是通过 EJB 访问的, 而是通过直接访问数据库。DAO 模式隐藏了后台的数据源,方便你以后对数据源 的替换。(关于 DAO 模式,请参考 j2ee 设计模式) 货架目录模块的实现 实现基本上就象设计中描述的,CatalogEJB 是一个无状态的 session EJB,实现了 CatalogLocal 接口。CatalogLocal 提供方法返回目录(catagory),产品(product),内容(item)。 CatalogLocal 同样提供一个 searchItems()方法,根据搜索条件来搜索相应的 item. CatalogEJB 使用 CatalogDAO 来获取数据。CatalogDAO 由 CatalogFactory 创建,这使得 DAO 是"可插拔"的。一旦有新的目录数据的数据源,你可以编写一个这个数据源访问的 DAO,实现 CatalogDAO 接口,修改厂的创建方法,用来返回新的数据源类型的 DAO。当 前呢,我们使用的是通过 jDBC 访问的关系数据库数据源。 1.1.1.3 客户模块(CustomerModule) 客户模块需求 ⚫ 客户模块必须跟踪客户的自由定制(例如喜好的语言,最喜欢的目录等),联系信息, 信用卡信息。 ⚫ HTTP 客户端和非 HTTP 客户端应该都能访问模块 ⚫ 客户的数据可以保持,并且通过客户关联的用户 id 来区分 ⚫ 客户的数据可以被其他的应用组件重用 客户模块需求 有三种方法来实现客户模块,本地的实体 EJB,一般的 java 类,远程的实体 EJB。宠 物店是用了本地的实体 EJB。这是因为它可以使用上 j2ee 的各种优势(CMP,CMR,事务处理 等)。以前的版本使用的是远程 EJB,改进成本地的 EJB 后,可以降低远程通讯的成本。 客户模块实现
String use Profile protile Profile String myListPreference ContactInfo contactinfo String zip Code String country 上图是客户相关的实体EJB图,在用户(User)和客户 ustomer之间没有明显的关系。这 样作是经过了深思熟虑的,因为,想尽量避免用户和客户之间的耦合关系,这样,以后 用户相关的部分想单独使用的时候,就恨容易独立出去 本地EB是一个很好的选择,你只需要写很少的代码,因为容器不仅替你管理持续性和 关系,甚至不用你写 getter和 setter的代码,不信?请看下面的代码: l getters and setters for CMP fields lic abstract String getUserldor, public abstract voidsetUserld(String user ld) abstract Accountlocal getAccounto: abstract void set Account(AccountLocal account public abstract ProfileLocal getProfile(r public abstract void setProfile(ProfileLocal profile) Code Example 5 Definition of Customer's Abstract Property Accessors userID的 setter和 getter被定义成抽象方法,容器自动会实现这些方法。在EJB20的CMP 中,CMP的数据并不保存在bean的字段中了,而是,通过这些 getter方法访问 EJB20的CMP的容器管理大大简化了实体EJB的管理。而且,也加强了实体EJB之间 的关系管理,比如例子中的 setAccount和 getAccount,看上去跟个一般的属性一样,其 实呢,是和 Account实体EJB关联的 11.141购物车模块 购物车模块跟踪用户一次的购买过程 购物车模块需求 必须能够跟踪用户购买的货品内容(iem) 购物车中的每个货品内容(tem)有唯一标示ID,此外,还有iem归属的货物 product的 ID,属于的种类( catalog),名字,和单品报价 ·每个tem必须有和一个非负的数量有对应关系
上图是客户相关的实体 EJB 图,在用户(User)和客户(Customer)之间没有明显的关系。这 样作是经过了深思熟虑的,因为,想尽量避免用户和客户之间的耦合关系,这样,以后 用户相关的部分想单独使用的时候,就恨容易独立出去。 本地 EJB 是一个很好的选择,你只需要写很少的代码,因为容器不仅替你管理持续性和 关系,甚至不用你写 getter 和 setter 的代码,不信?请看下面的代码: userID 的 setter 和 getter 被定义成抽象方法,容器自动会实现这些方法。在 EJB2.0 的 CMP 中,CMP 的数据并不保存在 bean 的字段中了,而是,通过这些 getter 方法访问。 EJB2.0 的 CMP 的容器管理大大简化了实体 EJB 的管理。而且,也加强了实体 EJB 之间 的关系管理,比如例子中的 setAccount 和 getAccount,看上去跟个一般的属性一样,其 实呢,是和 Account 实体 EJB 关联的。 1.1.1.4 1 购物车模块 购物车模块跟踪用户一次的购买过程 购物车模块需求: • 必须能够跟踪用户购买的货品内容(item) • 购物车中的每个货品内容(item)有唯一标示 ID,此外,还有 item 归属的货物(product)的 ID,属于的种类(catalog),名字,和单品报价 • 每个 item 必须有和一个非负的数量有对应关系 // getters and setters for CMP fields //==================================== public abstract String getUserId(); public abstract void setUserId(String userId); // CMR Fields public abstract AccountLocal getAccount(); public abstract void setAccount(AccountLocal account); public abstract ProfileLocal getProfile(); public abstract void setProfile(ProfileLocal profile); Code Example 5 Definition of Customer's Abstract Property Accessors
·客户可以增删改和改变item数量,或者清空购物车 购物车的设计 购物车是和一个 session关联的,因为,归属与某个用户,跨越多个请求。设计的关键在于在 哪里存放购物车的状态信息,我们使用了有状态的 session ejb。此外,使用EJB层存放这些 状态信息,客户端可以不用局限成WEB客户端。 下图是购物车的结构 > LocalHome noppingCart addItem empty category deleteltem attribute updateltemQuantity 上图是购物车模块的结构图,客户端使用 Shopping CartlocalHome来创建 Shopping CartLoca hopping CartEJB这个bean中包含了所有要求的操作。购物车 Shopping CartEJB包含了一个货品 内容(item)的 Cartltem对象的 Collection,这个 Cartltem类是个普通的可序列化远程传输的类 物车模块的实现: 购物车被实现成一个有状态的 session ejb,里面包含一个货品内容(iem)的 Collection。FB同时 暴露出各种方法,来增删改里面的内容,甚至清空。 B层的组件可以直接访问购物车EJB。WEB层维护一个EJB层的控制器,这个控制器有个方法 getShopping ClientFacadeo返回 Shopping ClientFacade Loca接口,这个接口的 getShopping C arto方法 返回当前用户的购物车 session ejB引用。 112宠物店的组件 这里仅仅总结一下宠物店用到的各种组件和文件类型 EJB-代表了商业数据和执行商业逻辑处理 JSP页面一定义了整个应用的视图框架模板( template. jsp)和模板组成个各个jsp。以及 各种被引用的图形文件 ⅹML文件一用来定义屏幕,屏幕跳转控制,绑定URL到某个 HTML Action,定制 signOn,以及j2ee部署的部署XML文件 Servlet过虑器( filter)-用来校验用户安全的登陆和输出的编码 异步信息发送组件一传输使用XML封装的订单到订单处理中心 一个安装程序一用来产生 sample数据库
• 客户可以增删改和改变 item 数量,或者清空购物车 购物车的设计: 购物车是和一个 session 关联的,因为,归属与某个用户,跨越多个请求。设计的关键在于在 哪里存放购物车的状态信息,我们使用了有状态的 session EJB。此外,使用 EJB 层存放这些 状态信息,客户端可以不用局限成 WEB 客户端。 下图是购物车的结构 上图是购物车模块的结构图,客户端使用 ShoppingCartLocalHome 来创建 ShoppingCartLocal。 ShoppingCartEJB 这个 bean 中包含了所有要求的操作。购物车 ShoppingCartEJB 包含了一个货品 内容(item)的 CartItem 对象的 Collection,这个 CartItem 类是个普通的可序列化远程传输的类。 购物车模块的实现: 购物车被实现成一个有状态的 session EJB,里面包含一个货品内容(item)的 Collection。EJB 同时 暴露出各种方法,来增删改里面的内容,甚至清空。 EJB 层的组件可以直接访问购物车 EJB。WEB 层维护一个 EJB 层的控制器,这个控制器有个方法 getShoppingClientFacade()返回 ShoppingClientFacadeLocal 接口,这个接口的 getShoppingCart()方法 返回当前用户的购物车 session EJB 引用。 1.1.2 宠物店的组件 这里仅仅总结一下宠物店用到的各种组件和文件类型: EJB – 代表了商业数据和执行商业逻辑处理 JSP 页面 - 定义了整个应用的视图框架模板(template.jsp)和模板组成个各个 jsp。以及 各种被引用的图形文件 XML 文件 - 用来定义屏幕,屏幕跳转控制,绑定 URL 到某个 HTML Action,定制 signOn,以及 j2ee 部署的部署 XML 文件 Servlet 过虑器(filter) – 用来校验用户安全的登陆和输出的编码 异步信息发送组件-传输使用 XML 封装的订单到订单处理中心 一个安装程序 - 用来产生 sample 数据库
1.121宠物店的EJB 宠物店使用了 session EjB来实现商业逻辑处理,使用实体EB来存储和操纵数据。所有的EJB都提供 local 接口给客户端调用。整个应用基于p2el.3,并且,WEB层必须和EJB层在一个虚拟机里,因为有些WB 层要调用EJB的loca接口 Session EB 异步消息处理 AsyncSenderEJB-(Stateless)转化购物车内容和客户信息成为xML的订单( order)消 息,传给订单处理中心 目录 Catalogejb( Stateless)提供一个可编程的目录接口 购物车 Shopping CartEJB( Stateful)维护个人的购物车信息 EJB端控制器 Shopping ClientControllerEJB-( Stateful)提供一个EB层的集中控制,扩展了WAF B] EJB controller(EJBClientControllerEJB) 购物车门户 Shopping ClientFacadeEJB-( Stateful缓冲了引用和提供对用户,购物车,和用户ID的 登陆 Sign EJB(Stls创建和认证系统用户 唯一ID产生器 UniqueldGeneratorEJB-( Stateless)创建系统唯一标识 ans 客户 CustomerS-跟踪客户ID,帐户,和个性化 帐户 AccounteE-跟踪帐户状态,信用卡和合同信息 个性化 Profiler-跟踪喜好的语言,种类,甚至广告bar 合同 ContactInfoEB-跟踪名字,电话, email,和地址 信用卡 CreditCardEJB跟踪信用卡号,类型和过期日期 地址 Addressee-跟踪两行的地址信息,州,邮编和国家 用户 UserEJB-代表一个登陆到系统中的用户,跟踪他的用户名/保密字 收银台 CounterEJB一个帐户对应一个特殊的前缀,仅仅用在产生唯一ID时候 1122宠物店的JSP页面 下表是宠物店用到的jsp页面,大多数页面有日本版本。 JSP Page Nam Description advice banner. jsp 在页面最下面,用来显示一些提示信息 banner. jsp 用来显示图形条 cart sp 显示购物车内容 cart empty_ order error. jsp当购物车空时候,不能下订单的错误提示页 create customer. jsp 创建客户的表单页 customer. jsp 显示客户信息 duplicate account. jsp 帐户名字重复 edit customer. jsp 修改客户信息 footer. jsp 脚注显示页面
1.1.2.1 宠物店的 EJB 宠物店使用了 session EJB 来实现商业逻辑处理,使用实体 EJB 来存储和操纵数据。所有的 EJB 都提供 local 接口给客户端调用。整个应用基于 j2ee1.3,并且,WEB 层必须和 EJB 层在一个虚拟机里,因为有些 WEB 层要调用 EJB 的 local 接口。 Session EJB • 异步消息处理 AsyncSenderEJB-(Stateless) 转化购物车内容和客户信息成为 XML 的订单(order)消 息,传给订单处理中心 • 目录 CatalogEJB-(Stateless)提供一个可编程的目录接口 • 购物车 ShoppingCartEJB-(Stateful) 维护个人的购物车信息 • EJB 端控制器 ShoppingClientControllerEJB-(Stateful) 提供一个 EJB 层的集中控制,扩展了 WAF 的 EJB controller (EJBClientControllerEJB) • 购物车门户 ShoppingClientFacadeEJB-(Stateful)缓冲了引用和提供对用户,购物车,和用户 ID 的 统一访问 • 登陆 SignOnEJB-(Stateless) 创建和认证系统用户 • 唯一 ID 产生器 UniqueIdGeneratorEJB-(Stateless) 创建系统唯一标识 Entity Beans • 客户 CustomerEJB-跟踪客户 ID,帐户,和个性化 • 帐户 AccountEJB-跟踪帐户状态,信用卡和合同信息 • 个性化 ProfileEJB-跟踪喜好的语言,种类,甚至广告 bar • 合同 ContactInfoEJB-跟踪名字,电话, email,和地址 • 信用卡 CreditCardEJB-跟踪信用卡号,类型和过期日期 • 地址 AddressEJB-跟踪两行的地址信息,州,邮编和国家 • 用户 UserEJB-代表一个登陆到系统中的用户,跟踪他的用户名/保密字 • 收银台 CounterEJB-一个帐户对应一个特殊的前缀,仅仅用在产生唯一 ID 时候 1.1.2.2 宠物店的 JSP 页面 下表是宠物店用到的 jsp 页面,大多数页面有日本版本。 JSP Page Name Description advice_banner.jsp 在页面最下面,用来显示一些提示信息 banner.jsp 用来显示图形条 cart.jsp 显示购物车内容 cart_empty_order_error.jsp 当购物车空时候,不能下订单的错误提示页 create_customer.jsp 创建客户的表单页 customer.jsp 显示客户信息 duplicate_account.jsp 帐户名字重复 edit_customer.jsp 修改客户信息 footer.jsp 脚注显示页面