浅谈MVC框架中View层的优雅设计及实例

     作者:EasyJF开源团队, 大峡

  在基于B/S的应用程序开发中,从基本的技术分工上来说就是两大块,一是软件显示界面,另一个是程序逻辑。在N年前的脚本语言时代,无论是asp、php还是jsp,我们基本是都是把这两者柔和在一起的。尽管我们想方设法做好很多函数或者包含文件来努力达到软件的复用,但仍然无法满足多变的用户需求,这主要是因为以前的纯脚本编码方式无法很好支持及应用面向对象(OO)领域中的强大功能。

  在常见的B/S软件项目中,界面的设计包括html界面、Wap界面及其它由文本字符协议为基本表示的界面等。以我们接触最多的html页面为例子,在做这些界面的时候往往需要美工先使用photoshop或fireworks等图形界面设计工具进行全局设计,然后再使用进行Dreamweaver等html页面制作工具进行加工制作。而强大的程序逻辑及后台处理都是由服务器端程序完成,这些程序具有较高的稳定性,其开发工具如JBuilder、Eclipse等对View层的界面无法很好的支持(当然那些用记事本写界面的应用除外),这就使得很多MVC框架的设计都无法两全齐美。

  作位一个比较友好的MVC的框架,在简化服务器应用开发的同时,还需要在View这一层设计上不要过多的影响到界面人员的工作,最基本的要求就是不要过多的加入一些设计软件不支持的标签等元素(如Struts的很多标签在Dreamweaver中都不支持)。这里我们以EasyJWeb为例,探讨在View层如何实现比较合理的设计。

  EasyJWeb作为一个快速Java Web MVC框架,其设计目标不尽是要简化软件开发人员的代码书写工作,更是要能方便界面设计人员的工作。

  当然,要使界面能跟后台程序逻辑能融合,显示界面及程序逻辑之间需要一定的对话协议在所难免。EasyJWeb作为一个MVC框架,同样也存在着这样的对话协议,这就是EasyJWeb中的界面模板标识语言。

  在当前发布的版本中,EasyJWeb界面模板标识语言使用的是Apache开源的Velocity模板引擎(template engine),当然以后会根据际需要加入更多的模板引擎以供框架应用者选择。

  Velocity是一个基于java的模板引擎(template engine),它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。作为一个比较完善的模板引擎,Velocity的功能是比较强大的,但强大的同时也增加了应用复杂性。

  理论上你可以在EasyjWeb模板使用所有Velocity的脚本及功能,但我们不推荐你在界面模板中使用过多过复杂的脚本表达方式,在万不得已的情况下,不要在界面模板中加入任何复杂的逻辑,更不要在界面模板中加入变量声明、逻辑运算符等等。

  在EasyJWeb中,我们提供了四条基本的模板脚本语句,基本上就能满足所有应用模板的要求。这四条模板语句很简单,可以直接由界面设计人员来添加。在当前很多EasyJWeb的应用实践中,我们看到,所有界面模板中归纳起来只有下面四种简单模板脚本语句即可实现:

  1、$!obj  直接返回对象结果。
  
  如:在html标签中显示java对象msg的值。<p>$!msg</p>
    在html标签中显示经过HtmlUtil对象处理过后的msg对象的值.<p>$!HtmlUtil.doSomething($!msg)</p>

  2、if($!obj) else end 判断语句

  如:在EasyJWeb各种开源应用中,我们经常看到的用于弹出提示信息msg的例子。

 
  #if($msg)
  <script>
  alert('$!msg');
  </script>
  end

上面的脚本表示当对象msg对象存在时,输出
<script>
等后面的内容。

  3、foreach( $info in $list) $info.something end  循环读取集合list中的对象,并作相应的处理。
  
  如:EasyJF开源论坛系统中论坛首页显示热门主题的html界面模板脚本


  foreach( $info in $hotList1)
<a href="/bbsdoc.ejf?easyJWebCommand=show&&cid=$!info.cid" target="_blank">$!info.title</a><br>
   end

  上面的脚本表示循环遍历hotList1集合中的对象,并输出对象的相关内容。
  
  4、macro(macroName)end 脚本函数(宏)调用,不推荐在界面模板中大量使用。

  如:在EasyJF简易订销管等系统中经常看到的一个排序状态显示的模板内容。
  函数(宏)定义,一般放在最前面


  macro(orderPic $type)
  #if ($orderField.equals($type))
  <img src="/images/ico/${orderType}.gif">
  end
  end

具体的调用如:

<font color="FFFFFF">头衔orderPic("title")</font>
  
    
  总结: 
  当然,在实际应用项目中,为了实现界面的更加友好、人性化,会出现很多复、易变的需求。如根据对象的不同状态,显示不同的提示颜色、提示语音等功能。在这种时候,仍然要慎用太多的模板脚本功能,大多数需求都可以通过变通的方式解决,有些信息可以直接在对象中增加逻辑转化信息,有些界面要求可以通过在界面中使用与特定界面有关的表达方式来实现,如html页面中使用javascript、css,Wap页面中使用WMLScript等等。只有,这样才能确保证你的系统核心不受界面的的影响及控制,才能更好的扩展及维护。

  我们希望你能成为真正的程序高手,而不只是精通某个处于表层的脚本语言,因此也不希望广大Java开发人员在View层消耗太多的时间。

  由于水平有限,本文所谈的内容有N多不合理或者需要改进的地方,恳请大家指正!


EasyJF官网:www.easyjf.com,各位朋友有空请来坐坐。

基本上我认为基于解析模板的java表示层框架将很快走向消亡,原因很简单:它是java应用倒退的表现。精力充裕,还不如多搞点项目来得实在。

它是java应用倒退的表现?
可以谈的深入吗?我觉的页面展现是大问题!,系统是通过页面来满足用户功能需求的,页面开发和维护都化费了系统大量的时间,特别是现在页面承担的功能越来越多!

tapstry的设计思想和理念,个人认为目前是最先进的!但是学习曲线和高度集成IDE的缺失。自定义组件的难度!html,page ,java。

对于在表现层使用模板的思路,实际上jsp最基本的思路就是使用模板。早先的很多cgi程序也是使用了模板的思路。并且从作者的例子中很难看出任何优雅可言。另外让界面设计人员使用这些模板元素简直就是笑话。

见识少了点,不好意思。下下试了一下,不过还是有点别扭哈,美工MM不喜欢:-)。


  先支持 楼上 doublepin 所说的前半段!呵呵

  在我举的例子中,“优雅”一词,充其量只是一个形容词,有点主观。好比大街上一个性感MM,三个哥们同时见了,一个流口水,一个流鼻血,一个喷饭。:-)

  到于“另外让界面设计人员使用这些模板元素简直就是笑话。 ”这句,强烈反对一下。:-0,因为我们的项目中设计人员也是这样用,包括早期单纯的Velocity或者tapstry框架到现在的EasyJWeb,一个新来的页面制作人员,给他说一遍那四条语句,基本就会了,不像古老的JSP及Struts,一不小心就大堆大堆的语法错误。

  若有时间及兴趣,可以下载完整示例代码来看看(地址:http://www.easyjf.com/download.htm),顺便帮忙指点指点。当然,大家若有更好、更优雅的方式,不防拿出来大家一起学习、研究。