• 实现跨域的项目实践


    1.功能描述:

       实现在系统主窗口点击 “Export to excel” link,open一个新的窗口提示用户‘下载即将开始,正在下载’字样, 同时“Export to excel” link 灰显, 当新窗口下载完成后,提示下载成功或失败信息,同时主窗口的 “Export to excel” link 恢复正常,即可再次点击下载。

    2.主要技术:

    (1)html5的postMessage 实现两个跨域的通信,下载完成的通知

    (2)用动态加载 <script> 标签引入require.js , 指定data-main 程序的主模块,引入主域的公共库文件,方法等

    3.实现过程:

     Main 窗口:

    exportReportToExcel:function (e){
        …
            var baseUrl = window.location.host;
            var protocol = window.location.protocol;
            var href = protocol + "//" + baseUrl;
    
        window.open(href+"/exportReportToExcel.html?"+reportId);    //打开新的子窗口
    }

    Son 窗口:

    <!Doctype html>
        <head>
            <meta charset="utf-8"/>
            <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
           <link rel="stylesheet" type="text/css" href="/styles.css?x.x.x.css"/>
           <link type="text/css" rel="stylesheet" href="/exportStyle.css"/>
           <title>ACTIVE Works Camp &amp; Class Manager</title>
           <script type="text/javascript">
           var reportId = document.location.href.split("?")[1].split('&')[0];  //通过get方式先获取到reportId
           window.onbeforeunload =function() {    //在即将离开当前页面(刷新或关闭)时执行,广发postMessage,内容就是这个reportId
               window.opener.postMessage(reportId,'*');
           };
           </script>
        </head>
        <body>
            <header id="globalHeader" class="show-html">
              <nav id="topNav">
                  <img src="/static/images/camps/CampsLogo.png">
              </nav>
            </header>
            <div class="downloadPrompt">
                <p>Your Report is being generated. Please do not close this window.</p><br/>
                <p>Download will begin automatically as soon as your report has been generated.</p>
                <br/><br/>
                <div id="loadMessage" style="color:red;font-size:12px;"></div>
            </div>
    <!—   下面这块是实现一个失败时提示一个弹出框的特效 (遮罩,弹出框 ) —>
             <div id="bg"></div>
             <div class="promPit" id="promPit">
               <div class="prompt">
                   <div class="title">
                      Could not download report
                      <span class="closeIcon" onclick="closePrompt()">X</span>
                   </div>
                   <div class="content" id="content">Sorry, there was a problem trying to download your report. Please try again and contact technical support if the problem persists.</div>
                   <div class="okbutton" onclick="closePrompt()">OK</div>
               </div>
             </div>
            <script>
            window.onload = function(){
                closePrompt();
                var newtimestamp = Date.parse(new Date());
                var timestamp=document.location.href.split("?")[1].split('&')[1];
                var d = (newtimestamp - timestamp)/1000;
                //when the time more than 5s, the href will failture.
                if(d > 30){ 
                  showPrompt('The link have grown stale. Please try again and contact technical support if the problem persists.');
                   return;
                }else{  
                  document.getElementById('loadMessage').innerHTML = "";
                  var oBody = document.getElementsByTagName('body').item(0); 
                  var oScript= document.createElement("script"); 
                  oScript.type = "text/javascript"; 
                  oScript.src="/arch/requirejs/require.js";    
                  oScript.setAttribute('data-main','exportToExcelMain.js')  
    //这里也关键,引入require.js, 并通过data-main属性,指定网页程序的主模块,这样主模块的一些组件就可以直接require进来使用 oBody.appendChild(oScript); } } function closePrompt(){ document.getElementById('promPit').style.display = "none"; document.getElementById('bg').style.display = "none"; } function showPrompt(str){ if(str){ document.getElementById('content').innerHTML = str; } document.getElementById('promPit').style.display = "block"; document.getElementById('bg').style.display = "block"; } </script> </body> </html>


    exportToExcelMain.js 的实现:
    "use strict";
    require.config({
        baseUrl: "./arch",
        waitSeconds: 180,
        paths: {
            'underscore': 'lib/underscore',
            'jquery': 'lib/jquery',
            'WaitManager': '../camps/Application/WaitManager'
        },
        shim: {
            'jquery': {
                exports: 'jQuery'
            },
            'underscore': {
                deps: ['jquery'],
                exports: '_'
            }
        }
    });
    
    
    
    define([
        'polling',
        'jquery',
        'underscore',
        'WaitManager'
        ], 
    //这是主域实现下载的通用方法,拿过来用就好了
    function (polling, $, _, WaitManager) {
    
        var exportReport = function(reportId) {
            return $.ajax({
               type: 'POST',
               url: '/service/json/aui/report/customerReport/'+reportId,
               contentType: 'application/json'
           });
        };
        var pollForCompleteReport = function(token) {
           var data = {
               pollForReportDto: {
                   reportTokenDto: {
                       value: token
                   },
                   timeout: 1
               }
             };
        return $.ajax({
              type:'POST',
              contentType: 'application/json',
              url:'json/ReportProxyService/pollForReportResult',
              data:JSON.stringify(data)
           });
        }; 
        
        var showPrompt = function(){
            document.getElementById('promPit').style.display = "block";
             document.getElementById('bg').style.display = "block";
         };
         
        WaitManager.startWaiting();
        var reportId = document.location.href.split("?")[1].split('&')[0];
        var fileId;
        var promise = exportReport(reportId);
        promise.then(function(response){
          if(!response.isError){
             var token = response.value;
             polling.start({
                id:token,
                interval:1000,
                onPoll: function(onPollResult){
                   var promiseToken = pollForCompleteReport(token);
                   promiseToken.then(function(pollingResult){
                     if(!pollingResult.isError){
                         fileId = pollingResult.fileId;
                         onPollResult(!!fileId);
                      }else{
                        WaitManager.stopWaiting();
                        window.opener.postMessage(reportId,'*'); // 关键在这里,下载失败后广发消息给主窗口,返回这个reportId
                        showPrompt();
                      }
                   });
                },
                onComplete: _.bind(function(){
                   WaitManager.stopWaiting();
                   window.opener.postMessage(reportId,'*');  // 关键在这里,下载成功后广发消息给主窗口,返回这个reportId
                   downloadFinishedReport(fileId);
                   $('#loadMessage').html('Download successful!');
                }, this)
             });
          }else {
              WaitManager.stopWaiting();
              showPrompt();
            }
        });
    
         var downloadFinishedReport = function(fileId) {
             if (fileId.indexOf('FID=') !== -1) {
                window.location = '/sys/exported?' + fileId;
            }
         };
                          
    });

    主窗口是怎么接收这个消息的?

    看这里:

    initialize: function(){
               function receiveMessage(event){
                    console.log(event.data);
                    $('a.exportexcel[data-id='+event.data+']').removeAttr('disabled').css('color','#008cd2').addClass('exportfinish');  //改变那条reportId 的按钮状态
               }
               if (typeof window.addEventListener != 'undefined') {
                     window.addEventListener('message', receiveMessage, false);  //监听window的message事件,接收消息
                      } else if (typeof window.attachEvent != 'undefined') {  //这里做了一下兼容IE
                     //for ie
                     window.attachEvent('onmessage', receiveMessage);
               }
        },
  • 相关阅读:
    No mapping found for HTTP request with URI [/jiaoyu/student/add] in DispatcherServlet with name 'SpringMVC'
    Mybatis系列(四)映射文件
    SpringMVC 接收表单数据的方式
    Maven整合SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
    使用MyBatis Generator自动创建代码
    中颖电子AD操作
    搜索引擎排名不友好的五个地点-SEO
    与我一起extjs5(04--MVVM简要说明财产)
    AspNet MVC4 教育-28:Asp.Net MVC4 Ajax技术部门四舍五入余速Demo
    unix pwd使用命令
  • 原文地址:https://www.cnblogs.com/torri/p/10528709.html
Copyright © 2020-2023  润新知