[saiku] 访问saiku首页的时候前后台处理流程
这篇文章讲述:
项目启动后,首次访问SAIKU的登录页,前后台分别做了什么处理
(1) 访问的到底是什么页面?
浏览器输入:localhost:8080 啪一回车
根据web访问的尿性,访问的是 index.jsp 或者 index.html 先看看 index.jsp ,没什么内容 <%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Pentaho BI Platform</title>
<META HTTP-EQUIV="refresh" CONTENT="0;URL=./serverdocs">
</head>
<body>
</body>
</html> <meta http-equiv="refresh" content="0; url=">
表示:经过一段时间转到另外某个页面
这里0表示没有延时,直接跳转到后面的URL;把0改成1,则延时1秒后跳转。
这就是为什么有的人访问localhost:8080会跳转到localhost:8080/saiku/serverdocs的原因 再看看 index.html 代码太多,你需要知道一点:配置中引入了所有需要的JS和CSS(除了一些需要动态加载的JS和CSS)
因为不管访问什么请求,地址栏都是localhost:8080没变过,得知所有的接口调用都是ajax异步请求
因此,所有需要的JS和CSS必然都是在index.html中引入包含了 目前迫切关注这几个引入:
<script src="js/jquery/jquery.min.js" type="text/javascript"></script>//基本JS
<script type="text/javascript" src="js/backbone/backbone.js"></script>//框架JS //Saiku 重要的JS
<script type="text/javascript" src="js/saiku/Settings.js"></script>//saiku基本配置->源码
<script type="text/javascript" src="js/saiku/Saiku.js"></script>//初始化saiku基本信息
<script type="text/javascript" src="js/saiku/models/Plugin.js"></script>//访问接口动态获取JS插件
<script type="text/javascript" src="js/saiku/models/Settings.js"></script>//访问接口动态获取CSS插件
<script type="text/javascript" src="js/saiku/adapters/SaikuServer.js"></script>//URL请求交互处理
<script type="text/javascript" src="js/saiku/models/Session.js"></script>//用户状态信息操作类
<script type="text/javascript" src="js/saiku/views/LoginForm.js"></script>//创建用户登录窗口 结论:index.html
(2) 首页,你在初始化自己的时候,都干哈了好事?
Saiku.js 跳了出来 ,他说:在全部的js中,哥们儿我有唯一的一个 $(function(){
//页面初始化加载代码于此
}); 我在这里面做了以下的好事,我按顺序说了啊 1、先判断是不是作为BI的PLUGIN存在,如果不是,那我可是一个独立的系统,是需要登录的哟,是就算了撒 2、显然我是被独立了,那我就开始初始化加载吧 3、我第一件事就是要构造一个获取动态JS的接口 URL :/saiku/rest/saiku/info 4、接下来当然是要访问这个接口啦 |——失败后我不做任何处理,反正我破罐子破摔了
|——成功后嘿嘿【接口处理代码和返回的JS列表看最后】 5、我再去构造一个获取动态CSS的接口 URL:/saiku/rest/saiku/info/ui-settings 6、接下来当然还是要访问这个接口啦 |——这么说吧,我如果成功success了,我要做以下的事:
|——加载所有的JS[plugins.size次异步请求]
|——加载所有的CSS[css.size次异步请求]
|——如果我不小心失败error
|——我就只能加载所有的JS[plugins.size次异步请求]啦,你总不能要求我加载获取失败的CSS吧 |——可是不管我是成功还是失败,我要做的事就必须做完,这些事我必做的: 1)创建Session对象
Saiku.session = new Session({}, {username: Settings.USERNAME,password: Settings.PASSWORD}); 在创建的时候会调用check_session方法通过构造/saiku/rest/saiku/session并访问该接口去获取用户session信息
如果用户session信息为空就创建new LoginForm()登录页
否则调用load_session方法构建首页空间 - new SessionWorkspace()
|-其实是访问/saiku/rest/saiku/用户帐号/discover接口获取数据源,成功后返回的connectionsList
|-成功后调用process_datasources方法 传入返回的 connectionsList 作为参数
|- 根据 connectionsList 执行 prefetch_dimensions 预加载Cube -> _.delay(this.prefetch_dimensions, 20); 钻取层级
var connection = this.connections[i];
var catalog = connection.catalogs[j];
var schema = catalog.schemas[k];
var cube = schema.cubes[l]; var key = connection.name + "/" + catalog.name + "/" +
((schema.name === "" || schema.name === null) ? "null" : schema.name) +
"/" + encodeURIComponent(cube.name); this.cube[key] = new Cube({ key: key }); if (Settings.DIMENSION_PREFETCH === true) {
this.cube[key].fetch();
}
|- 最后新建Workspace或者直接打开查询 -> Saiku.tabs.add(new Workspace()); 2)创建Toolbar对象
Saiku.toolbar = new Toolbar();
(3) 动态获取JS
1、关键代码 - InfoResource.getAvailablePlugins()
filepath配置在saiku-beans的这个bean里面
<bean id="platformBean" class="org.saiku.service.PlatformUtilsService">
<property name="path" value="../webapps/saiku/js/saiku/plugins/"/>
</bean>
2、动态加载的JS如下
(4) $(function(){}); 源码详细分析
if (! Settings.BIPLUGIN) {//Settings.BIPLUGIN 在settings.js中配置为false //执行页面初始化加载
$(document).ready(function () { //这个JS对象在js/saiku/models/Plugin.js里面定义
//完成后构建了访问的url:/saiku/rest/saiku/info
/* js/saiku/models/Plugin.js
var PluginCollection = Backbone.Collection.extend({
model: Plugin,
url: 'info'
});
*/
var plugins = new PluginCollection(); //接着,执行 backbone 的 fetch 方法就去访问了这个rest服务 /saiku/rest/saiku/info
plugins.fetch({
//调用成功。返回各个模块的plugin.js的路径
success: function () { //这个JS对象在js/saiku/models/Settings.js里面定义
//完成后构建了访问的url:/saiku/rest/saiku/info/ui-settings
/* js/saiku/models/Settings.js
var SettingsOverrideCollection = Backbone.Collection.extend({
model: SettingsOverride,
url: 'info/ui-settings'
});
*/
var settingsoverride = new SettingsOverrideCollection(); //接着执行 backbone 的 fetch 方法就去访问了这个rest服务 /saiku/rest/saiku/info/ui-settings
settingsoverride.fetch({ //调用成功。返回一个全局css文件
//加载第一个接口返回的JS和第二个接口返回的CSS
//并根据创建Session对象的状态去决定到登录页还是首页
//创建Toolbar工具栏
success: function () {
var i = plugins.size();
var j = 0; //遍历第一个rest返回的plugin.js,逐个去异步获取
plugins.each(function (log) {
j = j + 1;
if (log.attributes.path != "js/saiku/plugins/I18n/plugin.js") {
jQuery.ajax({
async:false,
type:'GET',
url:log.attributes.path,
data:null,
success:function(){
//JS全部遍历完毕后,再遍历第二个接口获取到的CSS
if (j == i) { var k = settingsoverride.size();
var l = 0;
settingsoverride.each(function (log) {
l = l + 1; for (var key in log.attributes) {
Settings[key] = log.attributes[key];
}
if(Settings.CSS != undefined){
Saiku.loadCSS(Settings.CSS, null)
} //CSS全部遍历完毕后,创建一个Session:js/saiku/models/Session.js
//创建session会调用初始化方法,从而调用check_session方法
/**
check_session: function() {
if (this.sessionid === null || this.username === null || this.password === null) {
var that = this;
this.clear();
//在这里会调用本页面的url 构造的接口是/saiki/rest/saiku/session
//调用成功后调用process_session
/**
url: function() {return "session";}
**/
this.fetch({ success: this.process_session, error: this.brute_force });
} else {
this.username = encodeURIComponent(options.username);
this.load_session();
}
},
**/ /**
process_session: function(model, response) {
if ((response === null || response.sessionid == null)) {
// Open form and retrieve credentials
Saiku.ui.unblock();
if (Settings.DEMO) {
this.form = new DemoLoginForm({ session: this });
} else { //第一次访问肯定没有用户信息
//所以就创建一个LoginForm了
//至此就完成了首页初次访问登录框的加载
this.form = new LoginForm({ session: this });
}
this.form.render().open();
} else {
this.sessionid = response.sessionid;
this.roles = response.roles;
this.isAdmin = response.isadmin;
this.username = encodeURIComponent(response.username);
this.language = response.language;
if (typeof this.language != "undefined" && this.language != Saiku.i18n.locale) {
Saiku.i18n.locale = this.language;
Saiku.i18n.automatic_i18n();
}
this.load_session();
} return this;
},
**/ //再创建工具栏对象:js/saiku/views/Toolbar.js
if (k == l) {
Saiku.session = new Session({}, {
username: Settings.USERNAME,
password: Settings.PASSWORD
}); Saiku.toolbar = new Toolbar();
}
}); }
},
dataType:'script'
});
}
else{
if (j == i) { var k = settingsoverride.size();
var l = 0;
settingsoverride.each(function (log) {
l = l + 1; for (var key in log.attributes) {
Settings[key] = log.attributes[key];
}
if(Settings.CSS != undefined){
Saiku.loadCSS(Settings.CSS, null)
}
if (k == l) {
Saiku.session = new Session({}, {
username: Settings.USERNAME,
password: Settings.PASSWORD
}); Saiku.toolbar = new Toolbar();
}
}); }
} }); }, //如果ui-settings访问失败,只加载第一个接口返回的JS
//并根据创建Session对象的状态去决定到登录页还是首页
//创建Toolbar工具栏
error: function () {
var i = plugins.size();
var j = 0;
plugins.each(function (log) {
j = j + 1;
if (log.attributes.path != "js/saiku/plugins/I18n/plugin.js") {
jQuery.ajax({
async:false,
type:'GET',
url:log.attributes.path,
data:null,
success: function(){
if (j == i) {
if(Settings.CSS != undefined){
Saiku.loadCSS(Settings.CSS, null)
}
Saiku.session = new Session({}, {
username: Settings.USERNAME,
password: Settings.PASSWORD
}); Saiku.toolbar = new Toolbar();
}
},
dataType:'script'
});
}
else{
if (j == i) { if(Settings.CSS != undefined){
Saiku.loadCSS(Settings.CSS, null)
}
Saiku.session = new Session({}, {
username: Settings.USERNAME,
password: Settings.PASSWORD
}); Saiku.toolbar = new Toolbar(); }
}
}); }
});
}
});
});
}
(5) Settings.js源码
var Settings = {
VERSION: "Saiku-${version}",
BIPLUGIN: false,
BIPLUGIN5: false,
BASE_URL: window.location.origin,
TOMCAT_WEBAPP: "/saiku",
REST_MOUNT_POINT: "/rest/saiku/",
DIMENSION_PREFETCH: true,
DIMENSION_SHOW_ALL: true,
DIMENSION_SHOW_REDUCED: false,
ERROR_LOGGING: false,
I18N_LOCALE: "en",
// number of erroneous ajax calls in a row before UI cant recover
ERROR_TOLERANCE: 3,
QUERY_PROPERTIES: {
'saiku.olap.query.automatic_execution': true,
'saiku.olap.query.nonempty': true,
'saiku.olap.query.nonempty.rows': true,
'saiku.olap.query.nonempty.columns': true,
'saiku.ui.render.mode' : 'table',
'saiku.olap.query.filter' : true,
'saiku.olap.result.formatter' : "flattened"
},
TABLE_LAZY: true, // Turn lazy loading off / on
TABLE_LAZY_SIZE: 1000, // Initial number of items to be rendered
TABLE_LAZY_LOAD_ITEMS: 20, // Additional item per scroll
TABLE_LAZY_LOAD_TIME: 20, // throttling call of lazy loading items
/* Valid values for CELLSET_FORMATTER:
* 1) flattened
* 2) flat
*/
CELLSET_FORMATTER: "flattened",
// limits the number of rows in the result
// 0 - no limit
RESULT_LIMIT: 0,
MEMBERS_FROM_RESULT: true,
MEMBERS_LIMIT: 3000,
MEMBERS_SEARCH_LIMIT: 75,
ALLOW_IMPORT_EXPORT: false,
ALLOW_PARAMETERS: true,
PLUGINS: [
"Chart"
],
DEFAULT_VIEW_STATE: 'view', // could be 'edit' as well
DEMO: false,
TELEMETRY_SERVER: 'http://telemetry.analytical-labs.com:7000',
LOCALSTORAGE_EXPIRATION: 10 * 60 * 60 * 1000 /* 10 hours, in ms */,
UPGRADE: true,
EVALUATION_PANEL_LOGIN: true,
QUERY_OVERWRITE_WARNING: true,
MAPS: true,
MAPS_TYPE: 'OSM' // OSM || GMAPS
}; /**
* Extend settings with query parameters
*/
Settings.GET = function () {
var qs = document.location.search;
qs = qs.split("+").join(" ");
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g; tokens = re.exec(qs);
while (tokens) {
var value = decodeURIComponent(tokens[2]);
if (! isNaN(value)) value = parseInt(value);
if (value === "true") value = true;
if (value === "false") value = false;
if(decodeURIComponent(tokens[1].toUpperCase()).substring(0,5)==="PARAM"){
params["PARAM"+decodeURIComponent(tokens[1]).substring(5,decodeURIComponent(tokens[1]).length)] = value;
}
else{
params[decodeURIComponent(tokens[1]).toUpperCase()] = value;
} tokens = re.exec(qs);
} return params;
}();
_.extend(Settings, Settings.GET); Settings.PARAMS = (function() {
var p = {};
for (var key in Settings) {
if (key.match("^PARAM")=="PARAM") {
p[key] = Settings[key];
}
}
return p;
}()); Settings.REST_URL = Settings.TOMCAT_WEBAPP + Settings.REST_MOUNT_POINT; // lets assume we dont need a min width/height for table mode
if (Settings.MODE == "table") {
Settings.DIMENSION_PREFETCH = false;
$('body, html').css('min-height',0);
$('body, html').css('min-width',0); }
if (Settings.BIPLUGIN5) {
Settings.BIPLUGIN = true;
} Settings.INITIAL_QUERY = false;
if (document.location.hash) {
var hash = document.location.hash;
if (hash.length > 11 && hash.substring(1, 11) == "query/open") {
Settings.INITIAL_QUERY = true;
}
} Settings.MONDRIAN_LOCALES = {
"English": "en_US",
"Dutch": "nl_BE",
"French": "fr_FR"
}; /**
* < IE9 doesn't support Array.indexOf
*/
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length >>> 0; var from = Number(arguments[1]) || 0;
from = (from < 0) ? Math.ceil(from) : Math.floor(from);
if (from < 0)
from += len; for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
} var tagsToReplace = {
'&': '&',
'<': '<',
'>': '>'
}; function replaceTag(tag) {
return tagsToReplace[tag] || tag;
} function safe_tags_replace(str) {
return str.replace(/[&<>]/g, replaceTag);
} if ($.blockUI) {
$.blockUI.defaults.css = {};
$.blockUI.defaults.overlayCSS = {};
$.blockUI.defaults.blockMsgClass = 'processing';
$.blockUI.defaults.fadeOut = 0;
$.blockUI.defaults.fadeIn = 0;
$.blockUI.defaults.ignoreIfBlocked = false; } if (window.location.hostname && (window.location.hostname == "try.meteorite.bi" )) {
Settings.USERNAME = "admin";
Settings.PASSWORD = "admin";
Settings.DEMO = true;
Settings.UPGRADE = false;
} var isIE = (function(){
var undef, v = 3; var dav = navigator.appVersion; if(dav.indexOf('MSIE') != -1) {
v = parseFloat(dav.split('MSIE ')[1]);
return v> 4 ? v : false;
}
return false; }()); var isFF = (function(userAgent) {
'use strict'; return !!userAgent.match(/Firefox/);
}(navigator.userAgent)); var isMobile = (function(userAgent) {
'use strict'; return !!userAgent.match(/android|webos|ip(hone|ad|od)|opera (mini|mobi|tablet)|iemobile|windows.+(phone|touch)|mobile|fennec|kindle (Fire)|Silk|maemo|blackberry|playbook|bb10\; (touch|kbd)|Symbian(OS)|Ubuntu Touch/i);
}(navigator.userAgent));
[saiku] 访问saiku首页的时候前后台处理流程的更多相关文章
- Saiku嵌入系统使用时传参数访问saiku(十六)
Saiku嵌入系统使用时传参数访问saiku Saiku通过iframe嵌入其他系统使用时,我们可以设定参数信息,然后根据url中参数对结果进行筛选哦. 这里我们实现的是根据日期字段进行范围查询,UR ...
- 在Eclipse中启动tomcat后访问tomcat首页时出现404
在Eclipse中配置好tomcat后,把一个web项目发布到tomcat上去,当使用http://localhost:8080访问tomcat首页时出现404错误,但可以正常访问web页面,然而当在 ...
- Python——通过用户cookies访问微博首页
通过用户cookies访问微博首页 1.登录微博 self.driver.delete_all_cookies() # 删除cookies self.driver.get(self.url) time ...
- [saiku] 将saiku自带的H2嵌入式数据库迁移到本地mysql数据库
saiku数据库的表和用户默认创建是在启动项目的时候,通过初始化 saiku-beans.xml 中的 h2database 这个 bean 执行org.saiku.service.Database类 ...
- [saiku] 通过 saiku 的 DEMO 分析 connection
示例:FOODMART connection: foodmart catalog: FoodMart schema: FoodMart cube: Sales/HR/Sales 2/.../ ==== ...
- [saiku] 配置saiku实时展现查询数据
缘起: 在默认的情况下,saiku是不能对数据进行实时展现的,只能通过刷新按钮或者重启服务器来刷新数据 这样以来会有很多的麻烦,每天得手动去刷新,这个操作只有管理员可以操作,在刷新以前客户看到的都是缓 ...
- tomcat配置通过域名直接访问项目首页步骤
假设www.ctool.top.ip:192.168.122.135 step 1 申请一个域名并做好DNS解析,或者在hosts文件做域名指向 #vim /etc/hosts www.ctool.t ...
- 8、SpringBoot-CRUD默认访问的首页以及thyleaf的静态文件引入/WebMvcConfigurer / WebMvcConfigurationSupport
1.导入资源 2.默认的访问首页 (1).将代码写在controller中 @RequestMapping({"/","index.html"}) public ...
- Https网站搭建——通过https://localhost:8443访问tomcat首页
图片大致介绍了Https浏览器与服务器握手的过程,涉及到的名词:证书.Hash算法.随机数密码.公钥加密.私钥解密.握手消息.hash验证.摘要 tomcat服务器配置可以实现https双向认证,简单 ...
随机推荐
- SQL Server常用函数
---------数学函数 ) --开平方 ) --区绝对值 ) --保留小数点后1位 四舍五入保留 select COUNT(*)/5.0 from Car select CEILING(COUNT ...
- uTenux-OS-Task再探
在第一节中我由于没有拿到开发板,所以被迫无奈,只能将uTenux操作系统移植到手中的一块STM32F103的开发板上,当时对于uTenux的理解还不够,只是看了一下文件架构和效果,虽然移植成功了,但是 ...
- BZOJ 1513 [POI2006]Tet-Tetris 3D
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1513 题意:三维空间,有一些立方体在垂直下落.立方体的左下角坐标(x,y)以及长宽 ...
- 数独Sudoku
数独(すうどく,Sūdoku),是源自18世纪瑞士发明,流传到美国,再由日本发扬光大的一种数学游戏.是一种运用纸.笔进行演算的逻辑游戏.玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并 ...
- Create Custom Modal Dialog Windows For User Input In Oracle Forms
An example is given below to how to create a modal dialog window in Oracle Forms for asking user inp ...
- Python基础学习笔记(三)运算符
参考资料: 1. <Python基础教程> 2. http://www.runoob.com/python/python-chinese-encoding.html 3. http://w ...
- maven环境快速搭建(转)
主要介绍maven在本地安装使用 http://www.cnblogs.com/fnng/archive/2011/12/02/2272610.html 使用Eclipse构建Maven项目 (s ...
- 顾维灏谈百度地图数据采集:POI自动处理率达90%
顾维灏谈百度地图数据采集:POI自动处理率达90% 发布时间:2015-12-21 22:37 来源:cnsoftnews.com 作者: 百度地图还创新研发高精地 ...
- aop前传之代理
一.jdk提供proxy类对目标对象实现代理,简单的说对方法的调用交给代理对象来操作. 代理目标 代理的具体实现: 代理测试; 简单说:利用proxy生成一个委托类实现代理.这个委托类是目标类的接口的 ...
- 适应各浏览器图片裁剪无刷新上传jQuery插件(转)
看到一篇兼容性很强的图片无刷新裁剪上传的帖子,感觉很棒.分享下!~ 废话不多说,上效果图. 一.首先建立如下的一个page <!DOCTYPE html> <html xmlns=& ...