Spring3+Hibernate4+SpringMVC整合Ext:開發Ext界面

jopen 12年前發布 | 138K 次閱讀 SpringMVC JEE框架

前言

Spring3+Hibernate4+SpringMVC整合Ext:項目架構搭建中已經介紹了Spring3、Hibernate4和SpringMVC的整合,下面介紹的是開發一個典型的Ext后臺管理界面:

Spring3+Hibernate4+SpringMVC整合Ext:開發Ext界面

        開發這個界面使用了Ext MVC,好多人都叫我用MVC方法去實現,其實MVC不是每個場景都適合。就我現在這個界面的場景而言并不適合用MVC開發,本來一個js文件就可以處理硬生生的分成了好幾個文件,效果不是很好。代碼是通過MVC實現的,MVC具體怎么樣用大家可以去參考下官方的例子,在這里就不在贅述。下面的代碼通過mvc的方式進行分層展示:

前臺界面


頁面

<%@ page language="java" pageEncoding="UTF-8"%>
<%
    String extLibPath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/ext4";
    String ctx = request.getContextPath();
    pageContext.setAttribute("extLibPath", extLibPath);
    pageContext.setAttribute("ctx", ctx);
%>
<html>
    <head>
        <title>業務基礎平臺</title>

    </head>
    <body>
        <div id="loading-tip" style="border-radius:3px;position: absolute;z-index: 1;border: solid 1px #ccc;background-color: #fff;padding: 10px;">
            <div class="loading-indicator" style="color: #444;font: bold 13px tahoma, arial, helvetica;padding: 10px;height: auto;">
                <img src="${ctx}/images/loading32.gif" width="31" height="31"
                    style="margin-right: 8px; float: left; vertical-align: top;" />
                業務基礎平臺V1.0
                <br />
                <span id="loading-msg" style="font: normal 10px arial, tahoma, sans-serif;">加載樣式和圖片...</span>
            </div>
        </div>
        <script type="text/javascript">
            var extLibPath = "${extLibPath}";
            var ctx = "${ctx}";
            var tip = document.getElementById("loading-tip");
            tip.style.top = (document.body.scrollHeight - tip.style.top - 100) / 2;
            tip.style.left = (document.body.scrollWidth - 200) / 2;
        </script>
        <link rel="stylesheet" type="text/css" href="${extLibPath}/resources/css/ext-all.css" />
        <link rel="stylesheet" type="text/css" href="icon.css" />
        <script type="text/javascript">
            document.getElementById("loading-msg").innerHTML = "加載核心組件...";
        </script>
        <script type="text/javascript" src="${extLibPath}/ext-all-debug.js"></script>
        <script type="text/javascript" src="${extLibPath}/locale/ext-lang-zh_CN.js"></script>
        <script type="text/javascript" src="app.js"></script>
    </body>
</html>
這個是index.jsp頁面,整個界面的代碼就在app.js里面:
Ext.Loader.setConfig({
            enabled : true
        });

Ext.Loader.setPath({
            'Ext.ux' : extLibPath + '/examples/ux',
            'Ext.app' : extLibPath + '/examples/app',
            'Fes' : 'module'
        });

Ext.require(['Fes.MsgBox']);

Ext.Ajax.on('requestexception', function(conn, response, options) {
            var msg = '訪問系統資源時發生異常<br/>' + '異常狀態:' + response.status + '('
                    + response.statusText + ')<br/>' + '異常信息:'
                    + response.responseText
            Ext.Msg.show({
                        title : '系統異常',
                        msg : msg,
                        width : 400,
                        icon : Ext.MessageBox.ERROR,
                        buttonText : {
                            ok : '  提交錯誤報告  '
                        },
                        buttons : Ext.MessageBox.OKCANCEL
                    });
        });
Ext.get('loading-msg').update('加載系統組件...');
Ext.create('Fes.desktop.Desktop');
在app.js的文件中主要是做了一些全局的配置,配置了ext的動態加載和ajax訪問時異常的處理,最后創建“Fes.desktop.Desktop”組件開始初始化界面

控制層


控制層的作用是對界面的行為進行控制、邏輯判斷和事件響應
module/desktop/Desktop.js
Ext.define('Fes.desktop.Desktop', {
            extend : 'Ext.app.Application',
            appFolder : 'module/desktop',

            name : 'Desktop',

            controllers : ['Desktop'],

            enableQuickTips : true,

            autoCreateViewport: true

        });
Fes.desktop.Desktop繼承Ext.app.Application,這個是Ext MVC中規定要繼承的父類。配置了autoCreateViewport為true時Ext會自動創建一個Desktop.view.Viewport的組件,這個規則是appname+view .Viewport。

module/desktop/controller/Desktop.js
Ext.define('Desktop.controller.Desktop', {
    extend : 'Ext.app.Controller',

    models : ['Node'],

    refs : [{
                ref : 'navigation',
                selector : 'navigation'
            }, {
                ref : 'container',
                selector : 'fescontainer'
            }],

    init : function() {
        var me = this;
        this.control({
                    'viewport' : {
                        render : me.onRender
                    },
                    scope : me
                });
    },

    onRender : function() {
        var me = this;
        Ext.get('loading-msg').update('正在加載菜單...');
        Ext.Ajax.request({
                    url : 'resource/root',// 獲取面板的地址
                    method : 'GET',
                    callback : function(options, success, response) {
                        me.createTree(Ext.JSON.decode(response.responseText));
                    }
                });
    },

    createTree : function(datas) {
        var me = this;
        Ext.each(datas, function(data) {
                    var tree = Ext.create("Ext.tree.Panel", {
                                title : data.text,
                                iconCls : data.iconCls,
                                useArrows : true,
                                autoScroll : true,
                                rootVisible : false,
                                viewConfig : {
                                    loadingText : "正在加載..."
                                },
                                store : me.createTreeStore(data.id)
                            });
                    tree.on('itemclick', me.onTreeItemClick, me);
                    me.getNavigation().add(tree);
                });
        Ext.get('loading-msg').update('加載完成.');
        Ext.Function.defer(function() {
                    Ext.get('loading-tip').remove();
                }, 1000);
    },

    onTreeItemClick : function(view, node) {
        console.log(node.data.component);
        var tab = this.getContainer();
        if (node.isLeaf()) { // 判斷是否是根節點
            if (node.data.type === 'URL') { // 判斷資源類型
                var panel = Ext.create('Ext.panel.Panel', {
                    title : node.data.text,
                    closable : true,
                    iconCls : 'icon-activity',
                    html : '<iframe width="100%" height="100%" frameborder="0" src="http://www.baidu.com"></iframe>'
                });
                tab.add(panel);
                tab.setActiveTab(panel);
            } else if (node.data.type === 'COMPONENT') {
                var panel = Ext.create(node.data.component, {
                            title : node.data.text,
                            closable : true,
                            iconCls : 'icon-activity'
                        });
                tab.add(panel);
                tab.setActiveTab(panel);
            }
        }
    },

    createTreeStore : function(id) {
        var me = this;
        return Ext.create("Ext.data.TreeStore", {
                    defaultRootId : id, // 默認的根節點id
                    model : this.getNodeModel().$className,
                    proxy : {
                        type : 'ajax', // 獲取方式
                        url : 'resource/child' // 獲取樹節點的地址
                    },
                    clearOnLoad : true,
                    nodeParam : 'id'// 設置傳遞給后臺的參數名,值是樹節點的id屬性
                });
    }
});
這個是整個界面的控制層,在init的方法中為viewport添加了一個render事件,在整個界面渲染完成后開始加載菜單。在菜單加載完成之后添加菜單的點擊事件。

視圖層


視圖層只頁面的展示,不做任務的邏輯操作和事件處理
module/desktop/view/Viewport.js
Ext.define('Desktop.view.Viewport', {
            extend : 'Ext.container.Viewport',
            requires : ['Desktop.view.Container', 'Desktop.view.Header',
                    'Desktop.view.Navigation'],

            layout : 'border',
            initComponent : function() {
                var me = this;
                Ext.apply(me, {
                            items : [Ext.create('Desktop.view.Container'),
                                    Ext.create('Desktop.view.Header'),
                                    Ext.create('Desktop.view.Navigation')]
                        });
                this.callParent(arguments);
            }
        });
定義Desktop.view.Viewport組件,這個組件會在控制器中被創建。viewport中定義了整個界面的布局,包含了Desktop.view.Container,Desktop.view.HeaderDesktop.view.
Navigation3個組件。

module/desktop/view/Container.js
Ext.define('Desktop.view.Container', {
            alias: 'widget.fescontainer',
            extend : 'Ext.tab.Panel',
            requires : ['Ext.app.Portlet', 'Ext.app.PortalColumn', 'Ext.app.PortalPanel',
                       'Ext.app.PortalDropZone', 'Ext.ux.TabReorderer','Ext.ux.TabCloseMenu'],
            activeTab : 0,
            enableTabScroll : true,
            animScroll : true,
            border : true,
            autoScroll : true,
            region : 'center',
            split : true,
            plugins : [
                Ext.create('Ext.ux.TabReorderer'),
                Ext.create('Ext.ux.TabCloseMenu',{
                            closeTabText: '關閉面板',
                            closeOthersTabsText: '關閉其他',
                            closeAllTabsText: '關閉所有'
                          })
            ],
            items : [{
                        iconCls : 'icon-activity',
                        title : '平臺首頁',
                        xtype : 'portalpanel',
                        layout : 'column',
                        items : [{
                                    xtype : 'portalcolumn',
                                    columnWidth : 0.7,
                                    items : [{
                                                title : '新聞動態',
                                                height : 150,
                                                iconCls : 'icon-news'
                                            }, {
                                                title : '最新通知',
                                                height : 150,
                                                iconCls : 'icon-notice'
                                            }, {
                                                title : '業績報表',
                                                height : 150,
                                                iconCls : 'icon-chart'
                                            }, {
                                                title : '郵件列表',
                                                height : 150,
                                                iconCls : 'icon-email-list'
                                            }]
                                }, {
                                    xtype : 'portalcolumn',
                                    columnWidth : 0.3,
                                    items : [{
                                                title : '功能鏈接',
                                                height : 150,
                                                iconCls : 'icon-link'
                                            }, {
                                                title : '待辦事項',
                                                height : 150,
                                                iconCls : 'icon-note'
                                            }, {
                                                title : '郵件列表',
                                                height : 150,
                                                iconCls : 'icon-email-list'
                                            }, {
                                                title : '郵件列表',
                                                height : 150,
                                                iconCls : 'icon-email-list'
                                            }]
                                }]
                    }]
        });
Desktop.view.Container是一個標簽頁集合的面板,是整個界面的操作區域。

module/desktop/view/Header.js
Ext.define('Desktop.view.Header', {
    extend : 'Ext.panel.Panel',
    height : 80,
    html : '業務基礎平臺',
    region : 'north',
    split : true,
    bbar : [{
                iconCls : 'icon-user',
                text : '管理員'
            }, '-', {
                text : Ext.Date.format(new Date(), 'Y年m月d日')
            }, '->', {
                text : '退出',
                iconCls : 'icon-logout'
            }],
    bodyStyle : 'backgroud-color:#99bbe8;line-height : 50px;padding-left:20px;' +
            'font-size:22px;color:#000000;font-family:黑體;font-weight:bolder;'+ 
            'background: -webkit-gradient(linear, left top, left bottom, ' +
            'color-stop(0%, rgba(153,187, 232, 0.4) ),' +
            'color-stop(50%, rgba(153, 187, 232, 0.8) ),' +
            'color-stop(0%, rgba(153, 187, 232, 0.4) ) );' ,
    initComponent : function(){
        this.callParent();
    }
});
Desktop.view.Header是界面的頭部

module/desktop/view/Navigation.js
Ext.define('Desktop.view.Navigation', {
            alias: 'widget.navigation',
            extend : 'Ext.panel.Panel',
            region : 'west',
            title : '系統菜單',
            width : 250,
            iconCls : "icon-tree",
            autoScroll : false,
            layout : 'accordion',
            collapsible : true,
            layoutConfig : {
                animate : true
            },
            id : 'navigation',
            split : true,
            initComponent : function(){
                this.callParent();
            }
        });
Desktop.view.Navigation是界面的導航部分,樹形菜單的展示區域

模型層


模型層主要是定義了前后臺數據交互的模型
module/desktop/model/Node.js
Ext.define('Desktop.model.Node', { 
    extend: 'Ext.data.Model',
    fields : [{name : "id",type : "string"},
            {name : "text",type : "string"},
            {name : "iconCls",type : "string"},
            {name : "leaf",type : "boolean"},
            {name : 'type'},
            {name : 'component'}]
});
Desktop.model.Node定義了菜單數據模型

后臺處理


整個界面的數據交互個入口在module/desktop/controller/Desktop.js文件中的對定義了viewport進行的事件響應:
init : function() {
        var me = this;
        this.control({
                    'viewport' : {
                        render : me.onRender
                    },
                    scope : me
                });
    },

    onRender : function() {
        var me = this;
        Ext.get('loading-msg').update('正在加載菜單...');
        Ext.Ajax.request({
                    url : 'resource/root',// 獲取面板的地址
                    method : 'GET',
                    callback : function(options, success, response) {
                        me.createTree(Ext.JSON.decode(response.responseText));
                    }
                });
    },

    createTree : function(datas) {
        var me = this;
        Ext.each(datas, function(data) {
                    var tree = Ext.create("Ext.tree.Panel", {
                                title : data.text,
                                iconCls : data.iconCls,
                                useArrows : true,
                                autoScroll : true,
                                rootVisible : false,
                                viewConfig : {
                                    loadingText : "正在加載..."
                                },
                                store : me.createTreeStore(data.id)
                            });
                    tree.on('itemclick', me.onTreeItemClick, me);
                    me.getNavigation().add(tree);
                });
        Ext.get('loading-msg').update('加載完成.');
        Ext.Function.defer(function() {
                    Ext.get('loading-tip').remove();
                }, 1000);
    },
在viewport渲染完成后發送到resource/root請求獲取菜單的根目錄,后臺java代碼:
ResourceController.java
package com.avicit.fes.system.resource.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.avicit.fes.system.resource.service.ResourceService;
import com.avicit.fes.system.resource.vo.ResourceNode;

@Controller
@RequestMapping("/resource")
public class ResourceController {

    @Autowired
    private ResourceService resourceService;

    @RequestMapping(value="root",method=RequestMethod.GET)
    public @ResponseBody List<ResourceNode> root() throws Exception{
        return this.resourceService.getRoot();
    }

    @RequestMapping(value="child",method=RequestMethod.GET)
    public @ResponseBody List<ResourceNode> child(@RequestParam("id") Integer id) throws Exception{
        return this.resourceService.getChildren(id);
    }
}
在ResourceController類中定義了root方法攔截resource/root請求,在resourceService中獲取菜單的根目錄發送到頁面中,下面看ResourceServiceImpl中的代碼:
package com.avicit.fes.system.resource.service.impl;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.avicit.fes.system.resource.dao.ResourceDAO;
import com.avicit.fes.system.resource.entity.Resource;
import com.avicit.fes.system.resource.service.ResourceService;
import com.avicit.fes.system.resource.vo.ResourceNode;
import com.avicit.framework.util.ListUtils;

@Service("resourceService")
public class ResourceServiceImpl implements ResourceService {

    protected Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    protected ResourceDAO<Resource, Integer> resourceDAO;

    @Override
    public List<ResourceNode> getRoot() throws Exception {
        return ListUtils.transform(this.resourceDAO.getRootResource(),ResourceNode.class);
    }

    public List<ResourceNode> getChildren(Integer id) throws Exception{
        return ListUtils.transform(this.resourceDAO.getChildrenByParent(id),ResourceNode.class);
    }

}
在ResourceServiceImpl類中getRoot方法中從后臺數據庫中獲取到跟目錄的數據返回給ResourceController,這樣就完成了數據的交互。
在獲取根目錄之后創建樹組件,并通過父節點獲取子節點,從而完成了界面菜單的交互。

來自:http://blog.csdn.net/leecho571/article/details/8043264
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!