`
weakfi
  • 浏览: 97068 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

OperaMasks在电子商务网站中的应用

 
阅读更多

 

1、互联网产品特点与OperaMasks的特性

    OperaMasks作为一款Web应用开发框架已经在许多项目的开发实践中体现了其应用于IT系统的高效和敏捷。众所周知,“Web应用”或称“B/S系统”是一个相对广泛的代名词,小至一个公司内部的CRMMIS等系统,大至一个互联网的大型网站都属于这个范畴。以CRMMIS等为代表的系统可以归类为企业内部IT系统,这类系统通常包含以下特点:

 

  1. 有地域范围限制(通常建立在一个公司内部的Intranet)
  2. 用户的数量通常比较固定和有限;
  3. 对满足业务需求,系统稳定性和数据安全性方面要求比较高;
  4. 界面风格相对统一,变化不会太大,更多的关注于实用而不是人机交互。

 

有别于这类系统,互联网产品更为普通人所熟悉,主要包括了门户,搜索引擎,社区,电子商务等和我们日常生活息息相关的地方。它们的特点也恰恰和传统的IT系统相反,因此,互联网产品作为在Internet上同时被大量用户访问的系统需要遵循的最重要的原则就是“快速,简洁,用户体验好”。

一直以来,OperaMasks 在开发企业应用的领域具备很大的优势,但并不代表在开发互联网产品的时候就不具备。事实上,自从OperaMasks3.0以后,其作为适合互联网产品开发的特性已经崭露头角。接下来通过OperaMasks在电子商务网站中的应用进行介绍。

 

2、构件资源依赖的修改--性能的初步优化

OperaMasks自带了一套官方的构件库,这套构件库使用了第三方的客户端JS框架-EXTJS

EXTJS是一套功能强大的JS控件库,里面包含的控件功能全面并且使用简单。有利必有弊,这么强大的功能同时带来了让人困扰的缺点:

首先,依赖的资源过多,其次,页面繁杂的JS操作也会对老式的浏览器客户端(比如IE6)的页面渲染造成不小的挑战。

这两点都会直接导致页面的渲染时间过长,这是与“快速,简洁”的原则不相符的。再加上EXTJS控件的封装粒度大,如果想在原来的基础上进行大幅度的样式修改也是不太可行的。

总而言之,首先需要把构件对资源的依赖去除掉,在OperaMasks中修改构件的资源依赖是再简单不过的事。以w:page为例子,首先从

Apusic OperaMasks 3.0参考手册》中找到w:page对应的构件渲染类为org.operamasks.faces.render.widget.ajax.AjaxPageRenderer。然后新建一个自己的渲染类com.apusic.nsec.renderer.NSECPageRenderer继承自AjaxPageRenderer,接着覆盖getDependedJSPackagesgetDependedCSSPackages方法返回null

 

         AjaxPageRenderer.java:
    @Override
    public String[] getDependedJSPackages(FacesContext context, UIComponent component) {
        return new String[] {"Ext.Base"};
    }
 
    @Override
    public String[] getDependedCSSPackages(FacesContext context,
            UIComponent component) {
        return new String[] {"All"};
}
 
NSECPageRenderer.java:
    @Override
    public String[] getDependedJSPackages(FacesContext context, UIComponent component) {
        return null;
    }
    @Override
    public String[] getDependedCSSPackages(FacesContext context, UIComponent component) {
        return null;
    }
 

 

最后在工程的faces-config.xml中加上这段配置即可:

 

<render-kit>
    <render-kit-id>AJAX</render-kit-id>
    <renderer>
      <component-family>org.operamasks.faces.HtmlDocument</component-family>
      <renderer-type>org.operamasks.faces.HtmlPage</renderer-type>
      <renderer-class>com.apusic.nsec.renderer.NSECPageRenderer</renderer-class>
    </renderer>
</render-kit>

 这些完成之后编写一个只包含w:page构件的faces页面,然后在客户端查看这个页面的源代码时就再也看不到EXTJS的影子了。

 

 

3、主页面模板+复合构件--页面的最大复用

电子商务网站和传统的IT系统有很大的不同,网站在页面之间的跳转和链接比较频繁,因此需要编写大量的静态(html)或者动态(faces)页面,这个时候页面复用很关键,比如网站中几乎每个页面都需要一个页头,左侧菜单和页脚,如下图:


 

这个时候模版正好派上用场。模板里面包含两大部分内容,一部分是模板的固定内容(如上图中被红色边框包围的地方),另一部分是待插入的动态内容。使用模板的页面自动“继承”了模板中的固定内容,然后在动态内容的区域填上本页面实际的内容就完成了。在模板里我们还同时引入了工程依赖的一些静态资源包括Jquery JS和网站的基础CSS样式文件template.css.

 

如果你认为光这样就够了,那就错了。主角才刚刚登场:复合构件

对于许多不同的页面中总能找到一些类似的可以重用的页面代码,比如在网站的很多地方中需要用小图标的方式表示某个卖家的信誉积分,显示这些图标的逻辑是在页面进行很多的if/else判断,根据卖家的信誉分数值显示不同的图标。

这个时候可以把那些重复的代码都删掉,只留一份封装成一个复合构件creditIcon就行了,使用这个复合构件只需要传入一个具体的分值作为构件的属性值,然后剩下的事情都由creditIcon来完成。

正式使用这个复合构件之前还需要先新建一个配置文件composition_component.taglib.xml,在文件中加上这段配置:

 

<facelet-taglib>
         <namespace>http://www.nsec.com</namespace>
         <tag>
                   <tag-name>creditIcon</tag-name>
                   <source>composition/creditIcon.xhtml</source>
         </tag>
</facelet-taglib>
 

 

接下来就可以在页面中使用了,注意要先在f:view里面声明nsec的命名空间:

<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:nsec="http://www.nsec.com" xmlns:ui="http://java.sun.com/jsf/facelets"
    renderKitId="AJAX">
    <ui:decorate template="template.xhtml">
             <ui:param name="message" value="会员级别图标控件演示:会员级别图标控件"/>
        <ui:define name="content">
                 <nsec:creditIcon credit="1"></nsec:creditIcon>
                 <nsec:creditIcon credit="2"></nsec:creditIcon>
                 <nsec:creditIcon credit="4"></nsec:creditIcon>
                 <nsec:creditIcon credit="8"></nsec:creditIcon>
        </ui:define>
    </ui:decorate>
</f:view>
  

 

这样就够了?等等,还没结束,在项目里面发现仅仅显示分数还是不够,还需要根据分数查询对应的级别然后再显示级别对应的图标,这个需要在显示之前先执行一次数据库查询的动作自然也放在复合构件里面。首先给复合构件绑定一个ManagedBean:

 

<om:useBean value="composition.gradeIconBean"></om:useBean>
@ManagedBean(name = "composition.gradeIconBean", scope = ManagedBeanScope.REQUEST)
public class GradeIconBean {
    WebApplicationContext wac = WebApplicationContextUtils
            .getWebApplicationContext((ServletContext) FacesContext
                    .getCurrentInstance().getExternalContext().getContext());
    private CreditPointLevelService creditPointSvc;
    private CreditPointsLevelEnum creditPointLevel;
    public void setCreditPointLevel(CreditPointsLevelEnum creditPointLevel) {
        this.creditPointLevel = creditPointLevel;
    }
    public CreditPointsLevelEnum getCreditPointLevel() {
        return creditPointLevel;
    }
    public CreditPointLevelService getCreditPointSvc() {
        return (CreditPointLevelService) wac.getBean("creditPointLevelService");
    }
}
 

 

从这个Bean中可以获取用来根据分数值查询数据库返回具体级别的service方法,还包含了一个给页面访问的级别属性(creditPointLevel)。万事俱备,只欠Elite,接下来在页面访问creditPointLevel属性之前先用Elite执行service的查询:

 

 

<om:elite>
    <![CDATA[
composition.gradeIconBean.setCreditPointLevel(composition.gradeIconBean.creditPointSvc.getCreditPointLevel(gradePoint));
    ]]>
</om:elite>

 这样每个复合构件在渲染之前都会执行这段Elite把查询结果赋予creditPointLevel属性。

 

使用效果:


 

 4submitAction+updater--页面局部刷新的黄金组合

OperaMasks中,页面的局部刷新通常和具体的构件或构件的属性联系在一起,在上面的修改资源依赖过程中我们已经把EXTJS从工程中移除,这就意味着一些基于EXTJSUI构件我们无法使用,因此我们需要一个能实现页面局部刷新的简便方案。

ajax:updater是一个能使页面局部刷新的容器类控件,你所需要做的是用updater把需要刷新的区域包含进去,然后在后台调用控件类的repaint()方法就可以了。当然还需要一个客户端事件去触发后台的刷新方法,以前的做法是在页面放置一个隐藏的UIButton,现在完全可以用submitAction代替了,使用submitAction一样可以通过JS调用触发后台事件,一样可以把页面的请求参数通过HTTPRequest传到后台。

比如,在电子商务网站中常常有很多页面需要用表格的形式展示数据,表格的下面通常放置了一个分页条。比如卖家查看仓库资源的页面,买家查看已购买商品的页面等等。当用户点击“下一页”或者点击“搜索”的时候需要刷新表格里面的数据,在不使用w:dataGrid(基于EXTJS实现的以表格形式展现数据的强大控件)的情况下我们采用了另一种替代方案,用c:forEach遍历后台数据并以table的形式展现在前台。由于c:forEach在后台不能绑定构件类,无法调用自身的reloadrepaint去刷新数据。因此在c:forEachtable外面再放置一个updater容器,并同时在里面放置一个submitAction。

这样就可以在用户点击的时候执行submitActionsubmit方法触发后台更新数据源并刷新updater。这种用法在项目的页面中已经大量使用,基本上,submitAction+updater是在不使用其他具有AJAX特性的构件的情况下实现页面局部刷新的黄金搭档,能满足99%的功能需求。

5、自定义构件--这里还能用JQUERY

由于OperaMasks默认提供了一套完整的基于EXTJS的构件库,以至于许多人可能一开始会觉得OperaMasks==Ext JS。其实不然,OperaMasks同时是一个能开发自定义构件的框架EXT JS只是默认提供的一套构件而已,你完全可以用现有的任何浏览器客户端框架(例如DOJOHTML5等等)或者自己编写原生的JavaScript去实现自定义的构件。

由于我们在页面的主模版中已经引入了Jquery JS。因此我们基于Jquery UI编写了一个自动下拉提示的输入构件autocomplete

首先,编写autocomplete的构件类UIAutocomplete,这个构件类是基于普通输入控件的扩展,只需要在继承HtmlInputText的基础上添加一个数据源去获取自动提示的内容。这个自动提示的数据源可以通过EL从后台获取,也可以在页面写静态的JSON。因此定义了autocomplete构件类的两个属性为:

 

 

  public class UIAutocomplete extends HtmlInputText{
         /** 静态数据源  **/
    protected String jsonSource;
    /** 动态数据源 **/
    protected MethodExpression listSource;
}

 

 接着,编写AjaxAutocompleteHandler在构件创建的时候对listSource进行初始化:

 

public class AjaxAutocompleteHandler extends ComponentHandler {
    private TagAttribute listSource;
    public AjaxAutocompleteHandler(ComponentConfig config) {
        super(config);
        this.listSource=this.getAttribute("listSource");
    }
    @Override
    protected void onComponentCreated(FaceletContext ctx, UIComponent c, UIComponent parent) {
        if(this.listSource != null){
            ((UIAutocomplete)c).setListSource(this.listSource.getMethodExpression(ctx, List.class, null));
        }
    }
}

 这个HandleronComponentCreated()方法会在facelets构建构件树的时候被自动调用。

然后,开始编写渲染类AjaxAutocompleteRendererAjaxAutocompleteRenderer继承AjaxInputRenderer,渲染HTML代码的工作由父类完成,autocomplete渲染类只需要返回正确的资源依赖字符串和渲染一段用来初始化并绑定数据到输入框的JS脚本:

 

    public String[] getDependedCSSPackages(FacesContext context, UIComponent component) {
        return new String[] {"jquery-ui-autocomplete-css"};
    }   
public void encodeInitScriptEnd(FacesContext context, ResourceManager rm, UIComponent component) throws IOException {
         … … // 此次省略初始化代码
        fmt.format("%s={};", jsvar);
        fmt.format("%s.data=%s;", jsvar, jsonSource);
        fmt.format("$(function() {");
        fmt.format("$( '#%s' ).autocomplete({ source: %s.data, minLength:0 });", clientId, jsvar);
        fmt.format("$('#%s').bind('focus',function(){$(this).autocomplete('search','');});", clientId);
        fmt.format("%s.source=function(data){$('#%s').autocomplete( 'option' , 'source' , data );%s.data=data;};",
                   jsvar,
                   clientId,
                   jsvar);
        fmt.format("});");
        ComponentResource resource = ComponentResource.getResourceInstance(rm);
        resource.addInitScript(fmt.toString());
}

 

最后配置一下taglibfaces-config文件就可以运行了,值得注意的是配置taglib的时候需要配置<handler-class>AjaxAutocompleteHandler:

composition_component.taglib.xml

 

         <tag>
                   <tag-name>autocomplete</tag-name>
                   <component>
          <component-type>com.apusic.nsec.component.autocomplete.autocomplete</component-type>
          <renderer-type>com.apusic.nsec.component.autocomplete.autocomplete</renderer-type>
          <handler-class>com.apusic.nsec.component.autocomplete.AjaxAutocompleteHandler</handler-class>
                   </component>
          </tag>

 faces-config.xml

 

          <component>
          <component-type>com.apusic.nsec.component.autocomplete.autocomplete</component-type>
          <component-class>com.apusic.nsec.component.autocomplete.UIAutocomplete</component-class>
          </component>
          <renderer>
          <component-family>com.apusic.nsec.component.autocomplete.autocomplete</component-family>
          <renderer-type>com.apusic.nsec.component.autocomplete.autocomplete</renderer-type>
          <renderer-class>com.apusic.nsec.component.autocomplete.AjaxAutocompleteRenderer</renderer-class>
          </renderer>

 运行效果


 

 

更多示例请参看:http://www.dt1688.com

http://demo.operamasks.org/bpdemos/index.faces

  • 大小: 191.5 KB
  • 大小: 38.7 KB
  • 大小: 9.8 KB
  • 大小: 4.9 KB
分享到:
评论
13 楼 lazybird86 2011-03-31  
AOM已经越来越强大了,相信有更多的人愿意去使用它。
任何东西都有不好的一面,但是如果把AOM的版本都拿出来对比,我们可以看到其实越做越好,而且是积累项目的经验的
!更重要的是,AOM的团队和它的领导者!
我不是托,我只是见证过、路过的。。。
12 楼 borball 2011-03-31  
......托?
11 楼 denger 2011-03-31  
这玩意儿一年前就用过了,BUG一堆不说,还慢的要死。
10 楼 opal 2011-03-31  
用 FreeMarker 模板,分分钟搞定了。
9 楼 jieyuan_cg 2011-03-31  
不错~~支持楼主
8 楼 weakfi 2011-03-31  
飞天不不 写道
写得真好,http://www.dt1688.com大通网,上回在官方论坛(http://www.operamasks.org/forum)的一个贴子里我就看到一次了,
做得真不错.
楼主的功底也很强大,ext功能是强大,但是如果做为商务站的确是厚重了一些,把ext剥离而用更轻量级的jQuery无疑是一个好选择
不过好消息是,目前的aom3.2以及将来的4.0都不再绑定extjs,可以自支持ext3.3以及jquery或者其他组件包了

谢谢楼上,以前JSF刚出来的时候被许多人怀疑,可能很多人觉得这种基于组件的开发方式不适合网站类的系统。事实上只要用对地方,有选择性的使用还是可以提高开发效率的。我们已经用AOM证明了这点。
7 楼 飞天不不 2011-03-31  
写得真好,http://www.dt1688.com大通网,上回在官方论坛(http://www.operamasks.org/forum)的一个贴子里我就看到一次了,
做得真不错.
楼主的功底也很强大,ext功能是强大,但是如果做为商务站的确是厚重了一些,把ext剥离而用更轻量级的jQuery无疑是一个好选择
不过好消息是,目前的aom3.2以及将来的4.0都不再绑定extjs,可以自支持ext3.3以及jquery或者其他组件包了
6 楼 mfkvfn 2011-03-31  
鼓掌。内容不错。文笔也很好。
5 楼 genious987 2011-03-31  
非常不错,使用AOM使用了extjs,依赖的资源过多,导致页面的渲染时间过长,看了楼主的文章,有帮助,谢谢。。
4 楼 gaowenming 2011-03-31  
很不错哦,以后的项目中但愿还可以用到吧!
3 楼 lyg8266 2011-03-31  
总结的很好,
2 楼 haiyupeter 2011-03-31  
很开心,国内的开源框架还是非常不错的。
如果做项目的话,我会选择它。
其实我也是一个开源迷,OperaMasks迷。
1 楼 eclipse07 2011-03-31  
aom的复合组件、自定义组件确实强悍,不过看这文章感觉意犹未尽,如果能分享下项目中遇到的问题和AOM能完成及完成不了的事儿就更好了

相关推荐

    operaMasks_studio应用手册

    通过本文的介绍,我们不仅了解到了operaMasks_studio的基本概念及其在JSF开发中的作用,而且还深入探讨了其主要功能和使用方法。作为一款专门为JSF量身打造的开发工具,operaMasks_studio凭借其强大的功能和易用性,...

    operamasks-ui-2.0-doc

    通过深入学习这份"operamasks-ui-2.0-doc",开发者不仅可以掌握Operamasks的集成和自定义方法,还能了解到区块链技术在Web应用中的实际应用,这对于构建基于以太坊或其他区块链平台的DApp至关重要。同时,了解这些...

    operamasks-ui 帮助文档

    只是我在网上找的 operamasks-ui api 文档 , 希望对你们有帮助

    operamasks官方jsf教程

    **OperaMasks** 是一个专为Opera浏览器设计的JSF组件库,它扩展了JSF的功能,使得在Opera中使用JSF应用更加顺畅。 **教程概述:** "operamasks官方jsf教程"是针对初学者的一个资源,旨在介绍如何使用JSF和...

    operamasks安装包

    在使用过程中,用户可以根据自己的需求调整operamasks-options.jar中的设置,或者利用operamasks-api.jar提供的接口与其他软件或扩展进行交互,以实现更个性化的浏览体验。总的来说,OperaMasks通过这些组件提供了一...

    operamasks-sdk_3.2

    1. **集成能力**:Operamasks SDK 3.2 提供了与金蝶中间件系统的无缝对接,使得开发者能够轻松地在自己的应用程序中整合金蝶的各项服务,如数据管理、工作流控制等。 2. **API接口**:SDK 包含了一套完整的API接口...

    operamasks-ui-2.1-demo

    在这个项目中,readme.txt可能会详述如何运行和测试OperaMasks UI 2.1的演示版本,以及如何在自己的项目中集成这个UI框架。阅读这个文件是了解和开始使用该框架的第一步。 而"operamasks-ui.war"文件是一个Web应用...

    OperaMasks查询、模糊查询、源码

    在这个Demo中,开发者展示了如何运用这些技术来创建一个具备模糊查询功能的应用。让我们深入探讨一下这个主题。 **OperaMasks框架** OperaMasks是一款专为Web应用程序设计的前端框架,它提供了丰富的UI组件和强大的...

    operamasks整合spring、hibernate实现grid增删改查

    在IT行业中,Web开发是一项核心任务,而"operamasks整合spring、hibernate实现grid增删改查"是常见的Web应用开发实践。这个主题涵盖了多个关键的技术组件,包括OperaMasks、Spring框架和Hibernate持久化层,以及Grid...

    operamasks开发的程序连接mysql数据库

    在IT行业中,数据库连接是应用程序开发中的基础环节,特别是对于Web应用来说,连接数据库以便存储和检索数据至关重要。本示例介绍了如何使用OperaMasks框架(可能是Apusic应用服务器的一部分)来开发Java程序,实现...

    operamasks-faces_1.0

    从标签"faces"和"operamasks"我们可以推断,这个包可能包含了一些定制化的图形元素,尤其是与人脸相关的图案,这些图案可能用于聊天、社交媒体或者在Opera浏览器的特定功能中。 在“operamasks-faces_1.0”这个...

    operamasks-ui-2.0.zip

    在实际应用中,OperaMasks UI 2.0常被用于企业级管理系统的构建,尤其在财务、人力资源、供应链等领域。与金蝶的其他产品相结合,如ERP、CRM系统,能够为企业提供一体化的信息管理平台,提升工作效率。 关于...

    operamasks_ui

    通过深入理解和运用这些文件,开发者可以充分利用OperaMasks UI的强大功能,创建出具备优秀标签管理功能的现代Web应用,提升用户在浏览和操作上的流畅度和满意度。同时,由于其高度可定制性,也允许开发者根据项目...

    Apusic OperaMasks-jsfdemo

    Apusic OperaMasks很全的JSF的例子,什么都有,如:TREE 、GRID、FORM、BOX、MENU、DIALOG、AJAX。都很漂亮的。

    operamasks2.1整合spring、hebernate实现grid增删改查

    在这个项目中,OperaMasks 2.1版本可能被用到了创建grid(表格)展示数据,以及处理用户的增删改查操作,提供友好的用户界面。 其次,Spring是一个全面的Java企业级应用开发框架,它提供了依赖注入(Dependency ...

    operamasks-ui-2.0-demo--.zip

    2. **示例代码**:通过实例代码,开发者可以学习如何在实际项目中应用这些API,理解如何触发特定的事件和响应用户操作。 3. **样式表(CSS)**:UI设计的核心部分,可能会包含定制主题、布局和组件样式的CSS文件。...

    operamasks-ui

    "Operamasks-UI" 是一个专为Opera浏览器设计的用户界面增强插件的源代码包,其版本为1.2,存储在一个名为"operamasks-ui-1.2.zip"的压缩文件中。这个插件的目标是提供更加个性化、高效且易用的浏览体验。在了解这个...

    OperaMasks-in-action.zip_action _operamasks_金蝶

    压缩包中只有一个文件“OperaMasks in action.doc”,这可能是一份详细文档,涵盖了OperaMasks平台的实际应用场景、使用教程、最佳实践,或者是展示了其在不同项目中的功能演示。通过阅读这份文档,开发者可以更好地...

Global site tag (gtag.js) - Google Analytics