这篇文章讲述:
项目启动后,首次访问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 = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;'
}; 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首页的时候前后台处理流程的更多相关文章

  1. Saiku嵌入系统使用时传参数访问saiku(十六)

    Saiku嵌入系统使用时传参数访问saiku Saiku通过iframe嵌入其他系统使用时,我们可以设定参数信息,然后根据url中参数对结果进行筛选哦. 这里我们实现的是根据日期字段进行范围查询,UR ...

  2. 在Eclipse中启动tomcat后访问tomcat首页时出现404

    在Eclipse中配置好tomcat后,把一个web项目发布到tomcat上去,当使用http://localhost:8080访问tomcat首页时出现404错误,但可以正常访问web页面,然而当在 ...

  3. Python——通过用户cookies访问微博首页

    通过用户cookies访问微博首页 1.登录微博 self.driver.delete_all_cookies() # 删除cookies self.driver.get(self.url) time ...

  4. [saiku] 将saiku自带的H2嵌入式数据库迁移到本地mysql数据库

    saiku数据库的表和用户默认创建是在启动项目的时候,通过初始化 saiku-beans.xml 中的 h2database 这个 bean 执行org.saiku.service.Database类 ...

  5. [saiku] 通过 saiku 的 DEMO 分析 connection

    示例:FOODMART connection: foodmart catalog: FoodMart schema: FoodMart cube: Sales/HR/Sales 2/.../ ==== ...

  6. [saiku] 配置saiku实时展现查询数据

    缘起: 在默认的情况下,saiku是不能对数据进行实时展现的,只能通过刷新按钮或者重启服务器来刷新数据 这样以来会有很多的麻烦,每天得手动去刷新,这个操作只有管理员可以操作,在刷新以前客户看到的都是缓 ...

  7. tomcat配置通过域名直接访问项目首页步骤

    假设www.ctool.top.ip:192.168.122.135 step 1 申请一个域名并做好DNS解析,或者在hosts文件做域名指向 #vim /etc/hosts www.ctool.t ...

  8. 8、SpringBoot-CRUD默认访问的首页以及thyleaf的静态文件引入/WebMvcConfigurer / WebMvcConfigurationSupport

    1.导入资源 2.默认的访问首页 (1).将代码写在controller中 @RequestMapping({"/","index.html"}) public ...

  9. Https网站搭建——通过https://localhost:8443访问tomcat首页

    图片大致介绍了Https浏览器与服务器握手的过程,涉及到的名词:证书.Hash算法.随机数密码.公钥加密.私钥解密.握手消息.hash验证.摘要 tomcat服务器配置可以实现https双向认证,简单 ...

随机推荐

  1. 首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。

    package lianxi; public class Print_1 { int x; Print_1(int x) { this.x = x; } void outPut() { String ...

  2. Dev gridview新增一行自动获得焦点并打开编辑模式

    1.gridview添加一行自动获得焦点实现方式: 关键代码: GarsonZhang dt.Rows.Add("1", "2"); gridView1.Foc ...

  3. 【转载】ODBC, OLEDB, ADO, ADO.Net的演化简史

    原文:ODBC, OLEDB, ADO, ADO.Net的演化简史 1.演变历史 它们是按照这个时间先后的顺序逐步出现的,史前->ODBC->OLEDB->ADO->ADO.N ...

  4. GCC编译器代码优化

    代码优化是指编译器通过分析源代码,找出其中尚未达到最优的部分,然后对其重新进行组合,目的是改善程序的执行性能.GCC提供的代码优化功能非常强大,它通过编译选项-On来控制优化代码的生成,其中n是一个代 ...

  5. 【转】雪崩光电二极管(APD)偏置电源及其电流监测

    摘要:本文提供的参考设计用于实现APD偏置电源及其电流监测.基于MAX15031 DC-DC转换器,该电路能够将2.7V至11V范围的输入电压经过DC-DC电源转换器后得到一个70V.4mA电源. 下 ...

  6. Beaglebone Black– 智能家居控制系统 LAS - 网页服务器 Node.js 、Web Service、页面 和 TCP 请求转 UDP 发送

    上一篇,纯粹玩 ESP8266,写入了 init.lua 能收发 UDP.这次拿 BBB 开刀,用 BBB host 一个 web server ,用于与用户交互,数据来自 ESP8266 的 UDP ...

  7. POJ 3104 Drying(二分答案)

    题目链接:http://poj.org/problem?id=3104                                                                  ...

  8. iOS - Swift available 平台判断

    前言 Swift 语言中的 @available 和 #available,Swift 2.0 中,引入了可用性的概念.对于函数,类,协议等,可以使用 @available 声明这些类型的生命周期依赖 ...

  9. iOS - UITextView

    前言 NS_CLASS_AVAILABLE_IOS(2_0) @interface UITextView : UIScrollView <UITextInput> @available(i ...

  10. poj1474Video Surveillance(半平面交)

    链接 半平面交的模板题,判断有没有核.: 注意一下最后的核可能为一条线,面积也是为0的,但却是有的. #include<iostream> #include <stdio.h> ...