zoukankan      html  css  js  c++  java
  • [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 = {
        '&': '&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));
  • 相关阅读:
    uva 408 Uniform Generator
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
  • 原文地址:https://www.cnblogs.com/avivaye/p/4897414.html
Copyright © 2011-2022 走看看