[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双向认证,简单 ...
随机推荐
- BZOJ 1565 植物大战僵尸(最大权闭合图)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1565 题意:植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: ...
- C++ const 的全面总结[转]
C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰符,常类型是指使用类 ...
- [转]Socket send函数和recv函数详解
1.send 函数 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP ...
- ServiceStack.OrmLite 6 学习笔记 查
查 根据id var result = db.SingleById<Poco>(1); 根据字段 var customer = db.Single<Customer>(new ...
- HDU 5826 physics(物理)
physics(物理) Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) D ...
- ubuntu 安装JDK
下载JDK6安装包,我的为32位系统所以选择jdk-6u35-linux-i586.bin 下载地址:http://www.oracle.com/technetwork/java/javase/dow ...
- Lodop在搜狗兼容模式下打印无边框问题
项目中原有的CAP方式打印由于只支持IE浏览器,由于目前大家使用IE的频率越来越少,迫切需要一个控件来替换项目原有的控件,比较了下选择Lodop,购买了一个最便宜的版本,使用后,有用户使用搜狗的兼容模 ...
- [转载] 为 Key-Value 数据库实现 MVCC 事务
http://mp.weixin.qq.com/s?__biz=MzA5ODM5MDU3MA==&mid=400086920&idx=1&sn=b8174184059e2886 ...
- UVA 11468【AC自动机+DP】
dp[i][j]表示走了i步走到j结点的概率.初始值dp[0][0] = 1.当走到的结点不是单词尾结点时,才能走过去. !end[i]&&last[i] == root时,该结点才可 ...
- 学习笔记day6:position index结合
z-index属性适用于定位元素(position 属性值为 relative 或 absolute 或 fixed的对象),用来确定定位元素在垂直于显示屏方向(称为Z轴)上的层叠顺序(stack o ...