Spring3+Hibernate4+SpringMVC整合Ext:开发Ext界面及Accordin Tree

12 篇文章 0 订阅
10 篇文章 0 订阅

前言

Spring3+Hibernate4+SpringMVC整合Ext:项目架构搭建中已经介绍了Spring3、Hibernate4和SpringMVC的整合,下面介绍的是开发一个典型的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,这样就完成了数据的交互。
在获取根目录之后创建树组件,并通过父节点获取子节点,从而完成了界面菜单的交互。

后续还会介绍@ResponseBody的用法、Ext分页的处理以及通过RESTful方式完成CURD,敬请期待

实例下载




  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
### 回答1: Spring MVCSpring 3和Hibernate 4是常用的Java开发框架和库。你可以通过以下步骤来下载它们的jar包。 1. Spring MVC的jar包下载: 你可以在Spring官方网站(https://spring.io/)的"Projects"部分找到Spring MVC的相关信息和下载链接。在该页面上,你可以找到最新版本的Spring MVC并下载与之对应的jar包。 2. Spring 3的jar包下载: 同样,你可以在Spring官方网站上找到Spring 3的相关信息和下载链接。在该网站上,你可以找到Spring 3的最新版本并下载相应的jar包。 3. Hibernate 4的jar包下载: 你可以在Hibernate官方网站(https://hibernate.org)的"Downloads"部分找到Hibernate 4的相关信息和下载链接。在该页面上,你可以找到最新版本的Hibernate 4并下载对应的jar包。 无论是Spring MVCSpring 3还是Hibernate 4,你可以选择下载官方提供的jar包来开始你的项目,也可以通过maven等构建工具来管理它们的依赖关系。在将这些jar包添加到你的项目中时,你应该将它们添加到你的构建路径下,并在项目配置文件中配置相应的引用和依赖。 希望以上的回答能够对你有所帮助! ### 回答2: 要下载Spring MVCSpring 3以及Hibernate 4的jar包,有以下几种方法可供选择: 方法一:通过官方网站下载 你可以直接访问Spring官方网站(https://spring.io/)和Hibernate官方网站(https://hibernate.org/orm/)的下载页面,在这些页面上你可以找到相关的jar包。Spring官方网站提供了关于Spring MVCSpring 3的jar包下载链接,Hibernate官方网站提供了关于Hibernate 4的jar包下载链接。 方法二:使用Maven依赖管理工具 如果你使用Maven作为项目构建工具,可以在项目的pom.xml文件中添加相关依赖,然后使用Maven自动下载这些jar包。在pom.xml文件中,你需要添加Spring MVCSpring 3和Hibernate 4的相应依赖配置,然后运行Maven命令执行依赖下载。 方法三:使用Gradle依赖管理工具 如果你使用Gradle作为项目构建工具,可以在项目的build.gradle文件中添加相关依赖,然后使用Gradle自动下载这些jar包。在build.gradle文件中,你需要添加Spring MVCSpring 3和Hibernate 4的相应依赖配置,然后运行Gradle命令执行依赖下载。 总之,你可以通过访问官方网站下载jar包,也可以使用Maven或Gradle工具自动下载。无论选择哪种方法,确保下载的jar包版本与你的项目要求的版本匹配,以确保项目能够正常运行。 ### 回答3: 可以在官方网站和第三方资源库下载Spring MVCSpring 3和Hibernate 4的JAR包。以下是一些常用的下载渠道: 1. 官方网站下载:可以通过Spring官方网站(https://spring.io/projects/spring-framework)下载Spring MVCSpring 3的JAR包。在网站上找到相应的版本并下载相关的JAR文件。 2. Maven下载:如果你使用Maven项目管理工具,你可以在pom.xml文件中添加相应的依赖关系,然后Maven会自动下载所需的JAR包。例如,你可以添加以下依赖项以下载Spring MVCSpring 3和Hibernate 4的JAR包: ```xml <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.11.Final</version> </dependency> ``` 然后,执行Maven的更新命令以下载所需的依赖项。 3. 第三方资源库下载:除了官方网站外,还可以通过其他资源库如Apache Maven仓库(https://mvnrepository.com/)或JCenter(https://bintray.com/bintray/jcenter)下载Spring MVCSpring 3和Hibernate 4的JAR包。在这些资源库的网站上搜索所需的JAR包,然后下载适合你的版本。 无论你选择哪种方式,下载所需的JAR包后,你可以将它们添加到你的项目构建路径中,以便在开发过程中使用Spring MVCSpring 3和Hibernate 4的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值