《应用拆分与平台搭建最佳实践》- 跨应用平台资源
《应用拆分与平台搭建最佳实践》- 跨应用平台静态资源
什么是跨应用平台静态资源
静态资源可以横跨多个应用正常使用
为什么需要做成静态资源
1.任何使用的此资源的平台风格保证一致性。
2.不需要后段做太多渲染处理,降低接入平台成本。
效果图
怎么做
可以看出,top头部,和左侧的导航,基本样式保持一致。其中,top颜色不同,是提供给每个应用个喜欢定制需要的配置颜色的方式。导航没有改颜色,当然也是可以改的。
我们如何做成这个效果呢?
两套方案:
方案一 将静态资源打包成war包,需要的应用依赖来使用,缺点很明显,应用需要往页面注入值,需要对接一系列接口,复杂。
方案二 引入一段js,所有的事情都是js去完成。业务方不关心其他细节。
两种方案笔者都有做过,笔者这里只讲第二种方案,因为更加合理。
首先,我们引入一个空的js文件
<#-- 公用静态资源 --> <script type="text/javascript" src="http://login.xiaotian.shi/js/plat/plat.js" id="plat-resources" env="${env}" nav="true" userinfo="true" ></script>
使用的应用始终只调用线上的js文件,然后注入env,决定当前环境,找对应jsonp接口拿数据。(现在说复杂了点,慢慢来。)
我们引入了这段js,如下给出源码
// 此文件最好修改成纯js,在jquery之前体验更好,笔者js功底不行,不敢献丑 $(function (){ // 获取当前环境 var env = $("#plat-resources").attr("env"); // 是否需要导航 var needNav = $("#plat-resources").attr("nav"); // 是否显示个人信息 var needUserInfo = $("#plat-resources").attr("userinfo"); // 获取静态服务地址 var logginServerUrl = getSpileUrl(env); // 最前面插入标签 // 加载公共资源页面 // var publicDoc = "<style>" + "*{padding:0;margin:0;font-family:'微软雅黑';}" + "body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,th,td,p,pre,form,input,textarea,fieldset,blockquote{padding: 0;margin: 0;}" + ".body-top {width: 100%;height: 100px;color: white;background: black;}" + ".body-top-left {height: 100%;width: 270px; float: left;}" + ".body-top-left-top {height: 70px;width: 270px;font-size: 50px;padding-left: 10px;line-height: 70px;}" + ".body-top-left-bottom {height: 30px;width: 270px;font-size: 15px;line-height: 30px;text-align: right;}" + ".body-top-mid {float: left;}" + ".body-top-right {float: right;margin-right: 40px; width: 400px;margin-top: 10px;}" + ".body-top-right-count {text-align: right;margin: 5px;font-size: 20px;}" + ".hidden {display: none}" + "div{cursor:default}" + "</style>" + "<div class='body-top'>" + "<div class='body-top-left'>" + "<div class='body-top-left-top'>xiaotian.shi</div>" + "<div class='body-top-left-bottom'>欢迎来到石啸天的个人网站</div>" + "</div>" + "<div class='body-top-mid'></div>" + "<div class='body-top-right'>" + "<div class='body-top-right-count'></div>" + "<div class='body-top-right-user hidden'>登陆</div>" + "<div class='body-top-right-userinfo hidden'>" + "<div class='body-top-right-userinfo-username'></div>" + "<div class='body-top-right-userinfo-logout'>退出</div>" + "</div>" + "</div>" + "</div>" + "<style>" + ".body-nav {top: 100px;left: 0px;width: 200px;bottom:0; height:100%;position: absolute;color: white;background: #2e68aa;padding-top: 20px;}" + ".body-nav-item {height: 20px;font-size: 20px;padding-left: 40px;padding-top: 10px;padding-bottom: 10px;}" + ".body-nav-item:hover{background: #1e508a}" + ".current {background:#5387c3}" + "</style>" + "<div class='body-nav hidden'>" + "</div>" ; $("body").prepend(publicDoc); // 请求top头右边个人信息,和左边导航信息,进行渲染 $.ajax({ type : "get", async:false, url : logginServerUrl + "/cloudInfo", dataType : "jsonp",//数据类型为jsonp jsonp: "callback",//服务端用于接收callback调用的function名的参数 success : function(data){ var indexAccessCount = data.data.indexAccessCount; $(".body-top-right-count").html("访问量:" + indexAccessCount); if(data.code === 200 && "true" === needUserInfo) { $(".body-top-right-userinfo-username").html(data.data.username + " |"); $(".body-top-right-userinfo").removeClass("hidden"); $(".body-top-right-user").addClass("hidden"); $(".body-top-right-user").click(function() { location.href = loginHost; }); } if(data.code === 200 && "true" === needNav) { var navlist = data.data.nav; if(navlist.length > 0) { var navStr = ""; for(var i = 0 ; i < navlist.length ; i++) { var url =navlist[i].url; var nowUrl = window.location.href; var current = ""; if(nowUrl.indexOf(url) > -1) { current = "current"; } navStr = navStr + "<div class='body-nav-item "+ current +"' url='" + url + "'>" + navlist[i].name + "</div>"; } $(".body-nav").html(navStr); $(".body-nav").removeClass("hidden"); $(".body-nav-item").click(function(){ var url = $(this).attr("url"); location=url; }) } } mRealy(data); }, error:function(){ alert('fail'); } }); $(".body-top-right-userinfo-logout").click(function() { $.ajax({ type : "get", async:false, url : logginServerUrl + "/logout", dataType : "jsonp",//数据类型为jsonp jsonp: "callback",//服务端用于接收callback调用的function名的参数 success : function(data){ location.href = "/"; }, error:function(){ alert('fail'); } }); }); // 绑定高度 $(".body-nav").height(document.documentElement.clientHeight); }); // 默认http // 如何组装,需要根据自己应用的域名来决定 function getSpileUrl(env) { var p = "http"; var s = ":8081"; if(typeof(env) == "undefined" || env === "product") { env=""; // 暂时没有https环境 // p = "https"; s = ""; } return p + "://login.xiaotian" + env + ".shi" + s; }
js文件有点长,但是不复杂
1.获取了标签的一些配置
2.写了一些html样式
3.根据环境参数,组装了接口数据请求地址
4.读取了jsonp 个人会话的数据
其中html笔者有尝试写在另一个静态文件中,然后跨域调取。但是面临几个问题:
1.延迟高
2.跨域方式不友好
这些内容不长,所以写成字符串的形式,一次渲染进去,高效快捷。
其中,绿色的login系统右上角的样式,有特殊定制,可以通过复写的方式,将样式修改掉。
例如top头部的颜色修改
.body-top { width: 100%; height: 100px; /*border-bottom: 4px white solid;*/ color: white; background: black; }
或者使用plat.js渲染完成后的回掉函数进行设置。
function mRealy(publicData) { };
其中publicData是异步请求的个人信息数据,结构可以自行设定。
这样基本完成了资源静态化的工作,但是这里有一些小细节。
比如如何提速,plat最好使用cdn加速节点,并且,jquery也需要cdn加速。版本需要手动控制,不可以经常更新。
例如plat.js?v1.0.0
这样可以提升用户体验,不过最好的方式是使用纯原生的js方式去实现,笔者js功底不好,为了赶稿子就不献丑了。
这里可以跨域访问的前提是,您完成了应用跨域访问的配置,详情请看笔者单点登录相关的帖子,里面有详细描述,跨子域名会话共享的实现。
或者您可以下载系列源码,run demo来体验
项目地址 https://github.com/shixiaotian/xiaotian.shi-plat.git
demo http://www.miledao.top/
账户密码
admin admin
user1 user1
user2 user2
user3 user3
账户密码
admin admin
user1 user1
user2 user2
user3 user3