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));
  • 相关阅读:
    CEF调试符号下载地址
    Koa搭建静态文件服务器
    查看requireJS已经加载的模块
    Android Unterminated string at character
    【微信支付】公众号 JSAPI支付 HTML5(使用MUI前端框架)+WebApi 实现流程
    winform 替换word文档中的字段(包含图片添加),生成导出PDF文件(也可是word文件)
    小程序 获取用户信息及手机号码
    winform PictureBox图片上动态添加Label或其他控件
    Html5+Mui前端框架,开发记录(四):下拉菜单绑定数据、搜索、时间控件
    Html5+Mui前端框架,开发记录(三):七牛云 上传图片
  • 原文地址:https://www.cnblogs.com/avivaye/p/4897414.html
Copyright © 2011-2022 走看看