jhope代码分析以及网站结构

如下图所示,为Extjs部分代码提供的网页结构:
_
网站看上去本来是这样的
_
前端采用ExtJS,与后台的SpringMVC+Spring+Hibernate进行数据交互。
之前分析过登录的过程,不赘述
在loginController处理登录返回结果的最后,如下语句
_
也就是如果正确登录的话,跳转到xtype为appcentral的页面
_
这是一个普通的panel
_
它的内容是经典的四分空间
如果仔细看代码,会看到就是我们这片博文最开始的那个示意图所示的分割方式。
这里面我们重点看看“菜单”那个空间,也就是left
网页中,菜单的形式是这样的
_
下拉框的样子,挺复杂
但是点击最左侧的小三角,也可以变换形式:
_
_
看到至少有两种其他表现形式
下面看看ExtJS的代码是如何获取菜单内容的:
Central.js这个View带有一个ViewController
_
名为CentralController.js
这个View还带有一个ViewModel
_
名为CentralModel.js,样子如下
_
在它的constructor方法中
_
EU.RS();方法是作者自己定义的js方法。
发送给SpringMVC
_
_
看到buildListToTree()方法是static的,因此可以直接使用,没有什么依赖注入之类的。
也不能这么说,注入了一个一成不变的参数
_
_

@Service
public class SystemFrameService {@Resourceprivate DaoImpl dao;@SystemLogs("获取系统左侧树形菜单")public List<TreeNode> getMenuTree() {String userid = Local.getUserid();String usertype = Local.getUserBean().getUsertype();String companyid = Local.getCompanyid();String sql = "select" + "     a.menuid,a.menuname as text,a.parentid as parentId,a.icon,a.iconCls,a.iconColor, "+ "     c.moduletype as type,c.modulesource as url,c.objectid,a.menutype,a.orderno,a.isexpand as expanded "+ " from" + "      f_companymenu a,f_companymodule b,f_module c " + " where a.companyid = b.companyid "+ "      and a.cmoduleid = b.cmoduleid " + "      and b.moduleid = c.moduleid "+ "      and a.companyid = '" + companyid + "' ";if (!usertype.equals("01")) {sql += " and (" + "        (" + "           select count(1) c "+ "              from f_modulefunction mf1,f_userfunctionlimit ufl "+ "              where mf1.cmoduleid = b.cmoduleid and mf1.functionid = ufl.functionid and ufl.userid = '"+ userid + "' " + "        ) > 0" + "     or " + "     ( " + "           select count(1) c "+ "              from f_modulefunction mf2,f_rolefunctionlimit rfl,f_userrole ur "+ "              where mf2.cmoduleid = b.cmoduleid and mf2.functionid = rfl.functionid and rfl.roleid = ur.roleid and ur.userid ='"+ userid + "' " + "        ) > 0" + " ) ";}sql += " order by a.orderno";List<TreeNode> dataList = dao.executeSQLQuery(sql, TreeNode.class);Map<String, TreeNode> parentMap = new HashMap<String, TreeNode>();for (TreeNode node : dataList) {if (!CommonUtils.isEmpty(node.getParentId())) {parentNode(parentMap, node);}}for (String key : parentMap.keySet()) {dataList.add(parentMap.get(key));}return dataList;}
}

这部分获取参数的代码还是比较壮观的,执行了sql而非hql语句,返回值是自定义类型。
上述sql语句中直接使用了数据库中数据表的名字和字段,我们补充一下对应的信息:
_
_
_
其实在phpmyadmin中只能看到字段的含义,数据表的内容,是无法直观用图形的方式看到不同数据表之间关系的。推荐使用powerdesigner读取mysql导出的sql文件,形成pdm图,可以方便的看到数据库各种关系的全貌,直观而且准确。
_

_
使用powerdesigner生成pdm图的过程,可以参考
http://blog.csdn.net/duanchangqing90/article/details/38089557
这篇文章

使用chrome浏览器看看http request的内容以及response的内容
_
Request URL:http://www.jhopesoft.com:8080/cfcmms/platform/systemframe/getmenutree.do
_
_
也就是说,前端和后台的通讯完全在意料之中。
回到ExtJS代码中Central.js的ViewModel文件
_
上述文件只是初始化,为js中的变量menus赋值
这些数据,如何使用呢?
_
上图为菜单的View文件
_
_
_
这些数据从后台返回,并处理,然后存放在js变量中,赋值给store
_
_
看来我对于filterer的猜测是错的
下面看看TreeStore的root属性(config)
_
对于Ext.data.TreeStore来说,root属性中的expanded属性设置为true,意味着不管这个store是否设置为autoLoad,整个store都会直接load。
写到这里,我们还是没有搞清楚Component和Store之间是什么关系,为什么这些数据可以被显示成View中菜单的样子。
我们来看看Ext官网上 Ext.data.TreeStore 的案例代码:

//Store部分的代码
var store = Ext.create('Ext.data.TreeStore', {root: {expanded: true,children: [{ text: 'detention', leaf: true },{ text: 'homework', expanded: true, children: [{ text: 'book report', leaf: true },{ text: 'algebra', leaf: true}] },{ text: 'buy lottery tickets', leaf: true }]}
});//View部分的代码
Ext.create('Ext.tree.Panel', {title: 'Simple Tree',width: 200,height: 500,store: store,rootVisible: false,renderTo: Ext.getBody()
});

上述代码的效果图如下
_
也就是说一个View和一个Store就可以轻易创建出上述样子的菜单。
我们也看到treepanel没什么代码,store的核心就是root children 和 text。
_
很显然c必须是字符串的数组也就是

c = [{text:菜单项1},{text:菜单项2},{text:菜单项3}]

那么菜单上面的文字,必须出现在text这个属性中,如下图
_
我们看看c的来源
_
就是Ext采用Ajax()方法对某个url发送request的返回值
因此我们有必要先去浏览器的开发者工具看看,返回值究竟是怎样的形式:
_
也就是说,ajax发送的返回值,在被ExtJS的js代码处理之前,就已经有了text这个字段,那么就肯定是Spring代码的自定义返回值,就已经安排好的。
_
_
上述的POJO是自定义返回值,其中一个字段就是text
而执行查询的executeSQLQuery()方法,也是DAO中自定义返回值的查询方法(非自定义返回值意味着,采用PO作为返回类型)
上面的描述基本讲清楚了,菜单上面的中文字符串的来源。

下面看看菜单上的菜单项,点击以后,有什么效果。
菜单的View部分页面的本质是Ext.tree.Panel
_

_

_
上述js代码就是,你点击菜单上的文字后,将一个完全新的tab页,并列到“首页”tab右边的js代码

                    /*** 将标准模块加入tabpanel中了,如果已经有了,就转至该tab页 itemId:module_(moduleName)*/addModuleToMainRegion : function(menuitem, donotActive) {var moduleName = menuitem.moduleName;var menuid = menuitem.menuid;var view = this.getView().down('maincenter');var tabItemId = 'module_' + menuid; // tabPanel中的itemIdvar tab = view.down('> panel#' + tabItemId);// 查找当前主区域中是否已经加入了此模块了if (!tab) {var tabPanel = null;// type : 01=外部xtype,03=实体对象if (menuitem.type == '01') {tabPanel = Ext.getCmp(tabItemId);if (!tabPanel) {tabPanel = Ext.create(menuitem.url, {id : tabItemId,autoDestroy : true,title : menuitem.text,closable : true});}} else if (menuitem.type == '03') {tabPanel = modules.getModuleInfo(moduleName).getModulePanel(tabItemId);}if (!tabPanel)return;if (!Ext.isEmpty(menuitem.glyph))tabPanel.glyph = menuitem.glyph;if (!Ext.isEmpty(menuitem.iconCls))tabPanel.iconCls = menuitem.iconCls;tab = view.add(tabPanel);}if (!donotActive)view.setActiveTab(tab);}

这段代码应该好好学学
_

_
上图中item
_
其实写到这里我的感觉就是强弩之末。
你点击了菜单的某一个选项,你想知道都发生了什么。

其实你很清楚,不论点击那个菜单项,结果是一样的:在首页tab右边,生成一个新的tab,至于这个tab是什么结构,里面是什么内容,取决于菜单项的id之类的信息。也就是刚刚进入网站,默认load那个treePanel,也就是菜单。(菜单是个treePanel,刚进入网站的时候默认发送ajax类型的request获取了菜单的所有内容)

那么,点击了菜单项以后,究竟发生了什么呢?

我们之前分享的那段代码,有一段十分重要:

//定位到maincenter
var view = this.getView().down('maincenter');
...................
//创建tabelse if (menuitem.type == '03') {tabPanel = modules.getModuleInfo(moduleName).getModulePanel(tabItemId);}......................//把tab加到view上,也就是让它显示tab = view.add(tabPanel);

上述代码的核心就是modules
_

/*** 取得模块的定义* @param {} moduleid ,参数可以是moduleid、modulecode、objectname、objectid* @return {}*/getModuleInfo : function(moduleid){if (Ext.isEmpty(moduleid)) {EU.toastWarn('加载moduleid不能为空!');return;}var me = this,result = me.modules.get(me.modulesKeys[moduleid.toUpperCase()]);if (result) return result;var url = "platform/module/getmoduleinfo.do",params = {moduleid : moduleid};EU.RS({url : url,params : params,async : false,callback : function(moduleinfo){me.replaceRef(moduleinfo, moduleinfo);if (moduleinfo) {result = new Ext.create('app.view.platform.module.ModuleInfo', moduleinfo);me.modules.add(moduleinfo.moduleid, result);me.modulesKeys[moduleinfo.moduleid.toUpperCase()] = moduleinfo.moduleid;me.modulesKeys[moduleinfo.modulecode.toUpperCase()] = moduleinfo.moduleid;me.modulesKeys[moduleinfo.fDataobject.objectid.toUpperCase()] = moduleinfo.moduleid;me.modulesKeys[moduleinfo.fDataobject.objectname.toUpperCase()] = moduleinfo.moduleid;} else {EU.toastWarn('加载' + moduleid + '的模块数据时失败!');}}});return result;},

_
Ctrl + H 搜索一下
modulepanel 意味着:
_
同志们,我们找到所有的核心了!!!
Module.js这个文件太关键了,因为它就是模板,这个文件就是个普通panel但是这个文件中,定义了Store和Items
也就是说,你点击菜单项创建的新的tab,取哪些数据,显示哪些UI就完全取决于这个文件了~!!!
我们上代码:

initComponent : function(){var me = this;if (Ext.isObject(me.param)) Ext.apply(me, me.param)me.moduleInfo = modules.getModuleInfo(me.moduleId);me.objectName = me.moduleInfo.fDataobject.objectname;me.model = me.moduleInfo.model;me.istreemodel = me.moduleInfo.fDataobject.istreemodel;//Store是那种类型:二选一me.store =Ext.create('app.view.platform.module.' + (me.istreemodel ? 'treegrid.TreeGridStore' : 'grid.GridStore'), {module : me.moduleInfo,modulePanel : me,model : me.model});me.store.getProxy().extraParams.moduleName = me.moduleInfo.fDataobject.objectname;if (me.parentFilter) me.store.parentFilter = me.parentFilter;me.enableNavigate =!me.istreemodel && me.enableNavigate&& (me.moduleInfo.fDataobject.navigatedesign || me.moduleInfo.getNavigateSchemeCount() > 0);me.collapseNavigate = me.moduleInfo.getNavigateSchemeCount() == 0 || me.collapseNavigate;me.defaults = {moduleInfo : me.moduleInfo,objectName : me.objectName,modulePanel : me,parentFilter : me.parentFilter};//Items中的核心UI Componentvar center = {xtype : me.istreemodel ? 'moduletreegrid' : 'modulegrid',store : me.store,region : 'center',modulePanel : me,inWindow : me.inWindow};me.items = [me.centerRegionNest ? {xtype : 'panel',region : 'center',layout : 'fit',items : [Ext.apply(center, me.defaults)]} : center];

写到这里真的写不下去了,因为,你为什么这么傻呢?
读代码多枯燥啊,我们直接去chrome上看数据传递,不就很直观么?走着!
_
我们看到执行了三次request
_
getmoduleinfo.do
fetchdata.do
这明显就是发送给SpringMVC的
如果看看response中的数据:
getmoduleinfo.do
_
fetchdata.do
_
看上去上面两类request分别用来获取
整个模板的数据和数据库中对应数据的数据。
_
fetchdata.do在整个代码中,只出现一次,靠,复用啊
_
我们看到了一个经典的Store,看到了吧,完美

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/278570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu下Authentication token manipulation error或者Authentication Failure解决办法

在Ubuntu18.04使用以下命令出现以下错误: 用passwd为新建用户或者root添加密码:Authentication token manipulation error 切换root用户出现Authentication Failure. 网上出现了大致两种方法: 第一种&#xff1a;用户文件和密码文件被保护&#xff0c;用chattr命令移除保护即可…

初学者:如何使用虚拟PC将Windows 7安装到虚拟机

Continuing in our series covering how to use Virtual PC, this week we’ll be showing you how to install Windows 7 into a virtual machine. It’s a very simple process, but here’s the step-by-step guide for beginners. 继续我们的系列文章&#xff0c;介绍如何使…

arcgis本地服务快速迁移到新机

情景 在本机或服务器发布了几十、几百个gis服务&#xff0c;当换电脑或者换服务器时不可能挨个找源文件重新发布服务&#xff0c;于是就想着既然是本地文件&#xff0c;一定可以拷贝过去的&#xff0c;经过一番搜索&#xff0c;结果如下: 方案一、迁移至新站点 新机站点创建…

js中 给json对象添加属性和json数组添加元素

json对象&#xff1a; 比如现在有一个json对象为jsonObj&#xff0c;需要给这个对象添加新的属性newParam&#xff0c;同时给newParam赋值为pre。做法如下&#xff1a; var jsonObj{param1:22,param2 :33}; 现在给jsonObj添加一个新的属性newParam jsonObj.newParam pre; 新的…

zabbix中php信息缺失之后的安装

安装php下enable bcmath和gettext &#xff08;在安装php时可以添加 --enable-bcmath --enable-gettext&#xff09;1,bcmath安装方法bcmath这个扩展在php源安装包压缩包中都是有的&#xff0c;需要重新编译一下才能够支持&#xff1b;cd php-5.2.7/ext/bcmath&#xff08;源…

极客大佬用什么电脑_极客特惠:笔记本电脑,高清电视和免费应用

极客大佬用什么电脑If you love new gear but not high prices then we’ve got some deals for you; grab some deeply discounted laptops, monitors and HDTVs, and free mobile apps in this week’s Geek Deals roundup. 如果您喜欢新设备&#xff0c;但不喜欢高价&#x…

Linux内核 TCP/IP、Socket参数调优

详见http://blog.csdn.net/u010009038/article/details/51917460转载于:https://blog.51cto.com/jack88/2063979

ppt插入html(用office而不是wps)

最近新get到的技能&#xff0c;在ppt里面插入html&#xff01;注意要用 Microsoft Office PowerPoint 才行&#xff0c;而不是wps&#xff0c;一定要先安装Microsoft Office PowerPoint再执行以下操作。 1、修改注册表的值&#xff0c;才能在PowerPoint中插入 Microsoft Web B…

如何使用SkyDrive的25 GB作为映射驱动器以方便访问

SkyDrive is an online storage system included in Windows Live, which gives you 25 GB of space that you can sync to your desktop. Here’s how to connect it to your Windows 7 computer as a mapped drive. SkyDrive是Windows Live中包含的一个在线存储系统&#xff…

SpringBoot+Mybatis 框架之 @SelectProvider注解方式搭建

之前搭建了Select标签来做SringBootMybatis的集成。这次使用SelectProvider标签的方式搭建一次。 一、搭建SpringBoot的项目 https://start.spring.io/自己配置SpringBoot的项目&#xff0c;点击“Generate Project”按钮就可以下载下来一个配置好的SpringBoot项目。 二、项目结…

程鑫峰:1.23日央行推行负利率政策,伦敦金后市行情解析

程鑫峰&#xff1a;1.23日央行推行负利率政策&#xff0c;伦敦金后市行情解析 QQ截图20180123153028.png   尽管美国政府关门闹剧刚刚结束&#xff0c;但交易员、投资者和策略师对于美元的前景依然不太乐观。美国货币政策对美元的影响力减弱可能是全球通货再膨胀交易的另一个…

从购买域名到nginx,flask搭建自己的网站

搭建一个只属于自己的网站? 一、注册域名&#xff08;可选*&#xff09; 1.注册阿里云账号 网址&#xff1a;登录&#xff08;注册&#xff09; 2.购买域名&#xff1a;阿里云域名注册 有一元域名、免费域名等。 购买过程中需要创建信息模板&#xff08;必须完成邮箱真实…

alexa语音实现_如何通过语音删除Alexa录音

alexa语音实现Amazon亚马孙Amazon is rolling out new privacy features today for Alexa. In addition to an educational “privacy hub,” the company lets you delete your stored recordings by voice. But it’s off by default; you’ll need to flip a switch. 亚马逊…

linux如何查看所有的用户(user)、用户组(group)、密码(password/passwd)

linux如何查看所有的用户和组信息_百度经验https://jingyan.baidu.com/article/a681b0de159b093b184346a7.html linux添加用户、用户组、密码_百度经验https://jingyan.baidu.com/article/335530da8b7e0419cb41c3e5.html 给用户开通sudo权限 xxx is not in the sudoers file.Th…

angular之两种路由

安装angular npm install -g angular/cli ng new myapp ng g component componentName 自带路由 引入&#xff1a;angular-route.js <div ng-controllerctr1><a href#home>首页</a> <a href#mine>我的</a> <div ng-view></div><d…

用scrapy框架写爬虫

爬虫可以发送给引擎的两种请求&#xff1a; # 1、url&#xff1a;# &#xff08;爬虫&#xff09;yield scrapy.Request -> 引擎 -> 调度器&#xff08;发送给调度器入队&#xff09; -> 引擎&#xff08;调度器出队请求于引擎&#xff09;# -> 下载器&#xff08;…

audacity_如何在Audacity中快速编辑多个文件

audacityGot a bunch of files that need to be edited the same way? You can automate the process to save time and effort using Audacity’s Chain feature and modify tons of files at the same time. 有一堆需要以相同方式编辑的文件&#xff1f; 您可以使用Audacity…

通过api管理grafana

1. 生成api key 参考&#xff1a; http://docs.grafana.org/http_api/auth/ 2.点击添加后&#xff0c;生成了个获取一个deshboards的api样例 3.放到linux上运行测试&#xff0c;结果成功返回。 4. 有些api并不支持使用api key 来连接&#xff0c;如下图中的搜索用户接口&#x…

NFS服务的配置过程

NFS服务的配置过程服务端:1)安装nfs和rcp服务yum install nfs-utils rpcbind -y 因为NFS支持的功能多,不同的功能会使用不同的程序来启动每启动一个功能就会启动一些端口来传输数据,默认NFS读完启动会产生多个进程,多个端口号信息,会随机使用未被使用的端口重启又会变化,所以…

vue项目将token存在(vuex)store和localstorage中

文章目录一、准备工作和token1、准备工作2、介绍token用法二、创建storage&#xff0c;store&#xff0c;request1、src目录&#xff1a;2、封装storage&#xff08;可选&#xff09;3、创建store4、创建request三、配置代理&#xff0c;封装路由router、设置路由守卫&#xff…