在三层结构的web应用中,现在,我们总是被要求支持多种客户端,浏览器、手机、REST风格的服务请求等,它们之间的不同主要是格式和编排(html/xml/json等),我们通过不同的展示层即可实现,业务层提供给展现层的数据模型是不变的,因此我们希望保持业务层的唯一和复用。比如,当需要支持wap时,新建一个jsp,调用同样的bean,但新jsp输出xml格式的数据,就此实现多客户端支持而复用业务层。而三层结构中,业务层还负责控制,特别是传统的web交互规则:表单提交和返回响应,例如“增加用户”这个请求:一个表单提交(假设提交了新用户的资料)后,业务层处理完成后(保存用户信息到数据库),需要返回响应,用户可能希望看到一个新的用户列表,要么是转发(forward)要么是重定向(sendRedirect)到用户列表请求,此时返回的响应并非“增加用户”业务的,而是“用户列表”的,“增加用户”这个业务根本没有展示层或者说没有到展示层就转向了。传统的web开发这当然没问题,但要求支持多客户端则遇到了挑战,1、当请求以Ajax方式提交(或者使用flex或flash构建富客户端)时,“增加用户”业务需要返回xml或json数据,也需要展示层来组装返回数据;2、支持服务请求,可能并非浏览器而是另一个应用发起的,也需要返回xml或json数据,以告之该请求是否完成或更多信息。在这种情况下,我们需要“增加用户”这个请求走到展示层并提供返回而不中途转向,这与前述转发或重定向的模式是完全不同的。1、是否放弃表单提交模式,即传统的表单提交后转发或重定向的做法,改为Ajax方式提交并返回响应。(因为表单提交必然导致页面刷新,因此也必须要求返回的内容是html呈现给用户)2、--别的方法我还没有想到问题的关键似乎在于:表单提交导致页面刷新,要求返回内容是html呈现给用户,而多客户端支持要求返回不同的数据格式而不仅是html谢谢您的关注,请大家讨论或提出建议。

解决方案 »

  1.   

    既然问题的根结在于控制转发上, 那么把控制转发抽出来, 如果我们的struts做的事情一样. 一个action接受了一次增加用户的业务请求之后, 首先去调用"添加用户"这个业务接口, 添加用户的业务接口会返回一个添加成功或失败的响应(注意: 在添加用户的业务上不要试图返回用户列表, 添加用户的业务中可以做的是为用户添加一个默认角色等业务操作), 那么, 在添加用户的action请求中, 我们接收到了"添加用户"这个业务接口的响应, 如果添加成功, 我们需要再次调用"查询所有用户"这个业务接口, 然后跳转给用户界面, 如果"添加用户"这个业务接口响应失败了, 我们的action就跳转到添加失败的提示界面.这样, 我们的原来的"添加用户"业务接口实际上被解耦合成两个接口"添加用户"和"查询所有用户".  此时, 你上层的控制转发做业务调用的时候, 调用的就是独立的多个业务接口, 上层使用什么表现层技术就都无所谓了, "添加用户"接口返回true或false的结果, 而查询所有用户以xml, json等数据格式将数据返回来.  上层和下层就很好的进行了隔离..如下图:
      

  2.   

    ER模型发展后期有一种半结构化关系模式专门针对你这种部署方式。但是这个是针对持久和临时的一个方案。你可以把VIEW看成临时方案,自己去套用吧!!先做好中间数据设计。
      

  3.   

    lgg201讲的模型,“增加用户”返回的仍是用户列表数据,但对于有些客户端,增加用户后可能想返回的就是添加成功或失败的响应,而不是用户列表。传统的web交互,表单提交后必须要返回html给用户看的,如果取消表单提交,改为Ajax方式提交(flex/flash客户端与Ajax提交方式类似),就可以把所有请求都统一成请求并返回响应,所有请求都有自己的展示层。当然,返回控制的确不在“增加用户”这个业务中,但却在“增加用户”这个请求中,我认为似应在请求中去掉转发控制才能适应多客户端的情况,原来的转发控制仅是针对返回HTML给浏览者的。
      

  4.   

    三层架构中业务层怎么会负责控制流程呢,把流程控制层分离出来就是要解决这个问题啊,一般我们把控制层和展示层称为web层,跟业务层严格分离的啊,只要你的业务层够纯粹,是当然可以复用的,除非你对不同的展现层提供不同的业务。
      

  5.   

    数据层、业务层、控制层、展示层,heixia2025说的其实是四层了,针对“增加用户”这个请求,如果有时需要执行完转向或重定向(浏览器作为客户端),而有时则需要直接返回是否执行成功的影响,那么只好在控制层写两个了,当然这也是一种方法