分類: 3C資訊

  • Azure AD(四)知識補充-服務主體

    Azure AD(四)知識補充-服務主體

    一,引言

      又到了新的一周了,也到了我新的分享的時間了,還記得上一周立得Flag,其中 “保證每周輸出一篇文章” ,讓我特別“在意”(這裏用詞不太恰當)。主要是我的一個大學舍友,他突然問了我一個關於寫博的事情,自己也在上周開通了賬號,也想着堅持寫博客。在我看來,這確實是一件好事,寫博不僅僅是分享的過程;也是自己提煉寫博的一個過程,以及文章組織的能力,對自己還是很有好處的。這不僅僅要寫內容要精鍊,同時也要讓別人能看的懂。加油,默默的在這裏給他打氣。(ง •_•)ง

    好了,開始今天的分析

    ————————————我是分割線————————————

      上一周有介紹到Azure AD資源託管標識的內容,其實就包括如何去操作開啟系統分配的託管標識,以及通過開啟託管標識,VM如何去訪問Azure 中的一些資源,如 “Key Vault” 等。今天去分析一波關於“Service Principal”(服務主體)。

    二,正文

    1,服務主體對象

      若要訪問受 Azure AD 租戶保護的資源,需要訪問的實體必須由安全主體來表示。 這同時適用於用戶(用戶主體)和應用程序(服務主體)。安全主體定義 Azure AD 租戶中用戶/應用程序的訪問策略和權限。 這樣便可實現核心功能,如在登錄時對用戶/應用程序進行身份驗證,在訪問資源時進行授權。當應用程序被授予了對租戶中資源的訪問權限時(根據註冊或許可),將創建一個服務主體對象。 Microsoft Graph ServicePrincipal 實體定義服務主體對象屬性的架構。

    2,應用程序和服務主體的關係

    可以將應用程序對象視為應用程序的全局表示形式(供所有租戶使用),將服務主體視為本地表示形式(在特定租戶中使用)。

    應用程序對象用作模板,常見屬性和默認屬性從其中派生,以便在創建相應服務主體對象時使用。 因此,應用程序對象與軟件應用程序存在 1 對 1 關係,而與其對應的服務主體對象存在 1 對多關係。

    必須在將使用應用程序的每個租戶中創建服務主體,讓它能夠建立用於登錄和/或訪問受租戶保護的資源的標識。 單租戶應用程序只有一個服務主體(在其宿主租戶中),在應用程序註冊期間創建並被允許使用。 多租戶 Web 應用程序/API 還會在租戶中的某個用戶已同意使用它的每個租戶中創建服務主體。

    下圖演示了應用程序的應用程序對象和對應的服務主體對象之間的關係,其上下文是在名為 HR 應用的示例多租戶應用程序中。 此示例方案中有三個 Azure AD 租戶:

    • Adatum -開發HR 應用的公司使用的租戶
    • Contoso -contoso 組織使用的租戶,即HR 應用的使用者
    • Fabrikam -fabrikam 組織使用的租戶,它也使用HR 應用

    在此示例方案中:

    表 1

    步驟 說明
    1 是在應用程序的宿主租戶中創建應用程序對象和服務主體對象的過程。
    2 當 Contoso 和 Fabrikam 的管理員完成同意並嚮應用程序授予訪問權限時,會在其公司的 Azure AD 租戶中創建服務主體對象,並向其分配管理員所授予的權限。 另請注意,HR 應用可能配置/設計為允許由用戶同意以供個人使用。
    3 HR 應用程序的使用者租戶(例如 Contoso 和 Fabrikam)各有自己的服務主體對象。 每個對象代表其在運行時使用的應用程序實例,該實例受相關管理員同意的權限控制。

    3,使用Azure CLI創建Azure服務主體(示例)

    使用 az ad sp create-for-rbac 命令創建服務主體創建服務主體時,請選擇其使用的登錄身份驗證的類型。

     注意

    如果您的帳戶無權創建服務主體,將返回一條錯誤消息,其中包含“權限不足,無法完成操作”。請與您的Azure Active Directory管理員聯繫以創建服務主體。

    3.1,在 “azure portal” 中驗證當前的Azure訂閱

    az account show
    

    3.2,显示訂閱名稱ID值的列表

    az account list --query "[].{name:name, subscriptionId:id}"
    

     

    3.3,使用 az ad sp create-for-rbac 命令,將其替換<subscription_id>為要使用的訂閱帳戶的ID

    az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/<subscription_id>"

    注意:我們將創建一個具有 “Contributor” (貢獻者角色:默認角色)的服務主體。該 “Contributor” 角色具有完全的權限讀取和寫入到Azure的賬戶,

    成功完成后,該命令將显示幾個值,包括自動生成的密碼  

     

    同時,我們可以在 “azure portal” 中可以找到對應的設置 選擇=》Azure Active Directory

     

    點擊 “App registrations”

     

     同時,我們可以在當前訂閱下的 “IAM”中找到對應的角色訪問權限信息。當然了,上面我創建服務主體的時候給的 scope 是整個訂閱,也就是我們可以通過這個服務主體去訪問azure的任何資源。

    例如 “azure devops Pipeline” 在CD的過程,需要配置 “Service Principal”

     

     例如使用Terraform 構建基礎架構資源的時候,需要配置 Service Principal

    三,總結

      使用Azure服務的自動化工具應始終具有受限權限。Azure提供服務主體,而不是讓應用程序以完全特權用戶身份登錄。Azure服務主體是為與應用程序,託管服務和自動化工具一起使用而創建的身份,以訪問Azure資源。這種訪問受到分配給服務主體的角色的限制,使您可以控制可以訪問哪些資源以及可以訪問哪個級別。出於安全原因,始終建議將服務主體與自動化工具一起使用,而不是允許他們使用用戶身份登錄。

    服務主體的默認角色是Contributor該角色具有讀取和寫入Azure帳戶的完整權限

    參考資料:RBAC內置角色:https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles

    作者:Allen 

    版權:轉載請在文章明顯位置註明作者及出處。如發現錯誤,歡迎批評指正。

     

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※別再煩惱如何寫文案,掌握八大原則!

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    ※回頭車貨運收費標準

    台中搬家公司費用怎麼算?

  • 將「生態滅絕」行為入罪化 法國公民會議促辦公投

    摘錄自2020年6月22日自由時報報導

    法國參與推動解決環境問題的「公民氣候公約」(Citizen’s Convention on Climate)理事會昨(21日)提出「生態滅絕」(Ecocide)提案,呼籲法國政府舉行公投,將破壞自然生態環境的行為入罪化。

    「公民氣候公約」是法國總統馬克宏(Emmanuel Macron)在2018到2019年黃背心運動(Yellow vests movement)後,回應「直接民主」的訴求下成立的理事會,以隨機的150位公民組成,旨在達成2030年的溫室氣體排放量和1990年相比減量40%。

    馬克宏上週建議理事會就各項提案舉行獨立公投,提案包括改善房屋隔熱、將高速公路限速從時速130公里調整至110公里等措施,與會人士則在會議中投票否決馬克宏的提議。馬克宏表示,將在29日於愛麗舍宮(Elysee Palace)和理事會150名成員進行會談,並針對議題做出回應。

    全球變遷
    氣候變遷
    國際新聞
    法國
    公投
    大滅絕
    氣候變遷
    全球暖化

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※別再煩惱如何寫文案,掌握八大原則!

    ※教你寫出一流的銷售文案?

    ※超省錢租車方案

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    ※回頭車貨運收費標準

  • 美國早產率隨高溫與空污攀升 非裔孕婦風險更高

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※別再煩惱如何寫文案,掌握八大原則!

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※超省錢租車方案

    ※教你寫出一流的銷售文案?

    網頁設計最專業,超強功能平台可客製化

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

  • 星巴克美國分店 首度推出人造肉餐點

    摘錄自2020年6月23日中央社報導

    為降低環境衝擊盡一分心力,星巴克的美國和世界各地分店早就開始以豆漿和燕麥奶來替代牛奶,不過美國連鎖咖啡品牌星巴克(Starbucks)今(23日)表示,將首度把植物肉列入旗下美國分店的菜單中。

    美聯社報導,總部位於西雅圖的星巴克表示,一款巧巴達三明治中使用模仿肉品口感的素香腸,來自加州紅木城(Redwood City)人造肉公司Impossible Foods,配料還有雞蛋、起司,現在多數旗下美國分店都有供應。

    星巴克4月在中國市場攜手另一家人造肉公司Beyond Meat,推出起司千層麵、香蒜醬義大利麵以及酸辣玉米餅捲等人造肉餐點。星巴克2月時,也在加拿大使用Beyond Meat的人造肉提供三明治作為早餐。

    國際新聞
    美國
    星巴克
    人造肉
    生物科技

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※教你寫出一流的銷售文案?

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※回頭車貨運收費標準

    ※別再煩惱如何寫文案,掌握八大原則!

    ※超省錢租車方案

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    ※推薦台中搬家公司優質服務,可到府估價

  • 越野旅遊收益因疫情銳減 保育經費無以為繼

    摘錄自2020年6月24日公視報導

    非洲國家受到疫情衝擊,各國野生動物保育專案計畫的經費也被迫裁減。保育團體就擔心,盜獵象牙和犀牛角的惡習,將和疫情一起蔓延。

    根據非洲的旅行業同業公會估計,從肯亞、烏干達一路往南,到波札那和南非,這類搭車跟著野生動物觀察遷徙路線的行程,每年可以帶來總計約新台幣3670多億元的收益。但因疫情國際航空幾乎停擺,經調查顯示,超過300家大小旅行社,有9成以上業者的業績只剩原來的1/4。除了相關的產業收入銳減,有關各國的野生動物保育專案計畫也被迫裁減編制與經費。

    由於中國在2018年以維護文化傳統、充實中醫藥材為由,取消買賣犀牛角的禁令,保育團體擔心盜獵者將利用巡邏人力的缺口,把非法取得的犀牛角拿去賺黑心錢。路透社的報導指出,南非有三個頗受歡迎、又可合法狩獵的野生動物公園,採取防範措施。工作人員在讓犀牛得以存活的條件下,切除部份的犀牛角,希望減少盜獵者對這些犀牛的興趣。

    生物多樣性
    國際新聞
    非洲
    武漢肺炎
    象牙
    犀牛角
    動物與大環境變遷

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※超省錢租車方案

    ※別再煩惱如何寫文案,掌握八大原則!

    ※回頭車貨運收費標準

    ※教你寫出一流的銷售文案?

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    網頁設計最專業,超強功能平台可客製化

  • 墨西哥地震規模7.4釀5死 震央附近交通中斷傷亡恐增

    摘錄自2020年6月24日中央社報導

    墨西哥南部太平洋岸今(23日)發生規模7.4強震,造成至少5人喪生,偏遠村落交通中斷,地震威力之強,連遠在震央數百公里外的首都墨西哥市(Mexico City)都有建築物受損。

    這起強震震央在瓦哈卡州(Oaxaca)附近,死傷也是在這裡傳出。由於州首府瓦哈卡市(Oaxaca)與海岸間的蜿蜒山路因落石中斷,搜救人員尚未抵達受災村落,傷亡可能更進一步攀升。

    社群媒體影像顯示,震央附近山村的診所與老舊教堂也都嚴重受損。

    美國地質調查所(USGS)表示,這起地震震源深度僅26公里,屬淺層地震。美國地質調查所初步測得規模達7.7,稍後下修為7.4。

    土地水文
    土地利用
    國際新聞
    墨西哥
    地震
    災害

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計最專業,超強功能平台可客製化

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※回頭車貨運收費標準

    ※推薦評價好的iphone維修中心

    ※教你寫出一流的銷售文案?

    台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

    台中搬家公司費用怎麼算?

  • 委內瑞拉燃油短缺 單車通勤成生活新常態

    摘錄自2020年6月19日公視報導

    全球儲油量第一的委內瑞拉,卻因為美國加強禁運和經濟制裁,國內陷入石油危機,民眾排隊加油竟然要等上三天三夜,也促使許多人開始改以自行車代步。

    在委內瑞拉,石油長年比水還便宜,民眾大多開車上班,現在因為沒油可買,許多民眾轉而騎單車通勤。自行車技師塞古拉表示:「修理自行車的量變多了,我計算至少多出20至30倍」

    該地煉油設備老舊到不堪使用,過去以原油和俄羅斯交換燃油,如今交易也因為受到美國制裁而停擺,面臨歷年來最嚴重的汽油短缺,更有民眾說,沒油可用比新冠病毒更讓人苦惱。

    現在委內瑞拉最低月薪3塊美金左右,台幣不到100塊,等於只夠買六公升左右的汽油,無疑是生活一大負擔,也難怪騎單車通勤,成了越來越多委內瑞拉民眾生活的新常態。

    生活環境
    能源議題
    能源轉型
    國際新聞
    委內瑞拉
    單車
    自行車
    石油危機
    石油
    交通運輸

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※回頭車貨運收費標準

    ※推薦評價好的iphone維修中心

    ※超省錢租車方案

    台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

    ※推薦台中搬家公司優質服務,可到府估價

  • 為綠能發電犧牲演化寶庫 水壩工程威脅印尼古老波索湖

    環境資訊中心綜合外電;黃鈺婷 翻譯;林大利 審校;稿源:Mongabay

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※回頭車貨運收費標準

    ※產品缺大量曝光嗎?你需要的是一流包裝設計!

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※推薦評價好的iphone維修中心

    ※教你寫出一流的銷售文案?

    台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

    台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

  • 微前端與項目實施方案研究

    微前端與項目實施方案研究

    一、前言

    微前端(micro-frontends)是近幾年在前端領域出現的一個新概念,主要內容是將前端應用分解成一些更小、更簡單的能夠獨立開發、測試、部署的小塊,而在用戶看來仍然是內聚的單個產品。微前端的理念源於微服務,是將龐大的整體拆成可控的小塊,並明確它們之間的依賴關係,而它的價值在於能將低耦合的代碼與組件進行組合,基座+基礎協議模式能接入大量應用,進行統一的管理和輸出,許多公司與團隊也都在不斷嘗試和優化相關解決技術與設計方案,為這一概念的落地和推廣添磚加瓦。結合自身遇到的問題,適時引用微前端架構能起到明顯的提效賦能作用。
    

    二、背景

    目前我司擁有大量的內部系統,這些系統採用相同的技術棧,在實際開發和使用過程中,逐漸暴露出如下幾個問題:
    

    1.有大量可復用的部分,雖然有組件庫,但是依賴版本難統一;
    2.靜態資源體積過大,影響頁面加載和渲染速度;
    3.應用切換目前是通過鏈接跳轉的方式實現,會有白屏和等待時長的問題,對用戶體驗不夠友好;
    針對上述幾個問題,決定採用微前端架構對內部系統進行統一的管理,本文也是圍繞微前端落地的技術預研方案。

    三、方案調研

    目前業界有多種解決方案,有各自的優缺點,具體如下:

    • 路由轉發:路由轉發嚴格意義上不屬於微前端,多個子模塊之間共享一個導航即可 簡單,易實現 體驗不好,切換應用整個頁面刷新;

    • 嵌套 iframe:每個子應用一個 iframe 嵌套 應用之間自帶沙箱隔離 重複加載腳本和樣式;

    • 構建時組合:獨立倉儲,獨立開發,構建時整體打包,合併應用 方便依賴管理,抽取公共模塊 無法獨立部署,技術棧,依賴版本必須統一;

    • 運行時組合:每個子應用獨立構建,運行時由主應用負責應用管理,加載,啟動,卸載,通信機制 良好的體驗,真正的獨立開發,獨立部署 複雜,需要設計加載,通信機制,無法做到徹底隔離,需要解決依賴衝突,樣式衝突問題;

      開源微前端框架也有多種,例如阿里出品的qiankun,icestark,還有針對angular提出的mooa等,都能快速接入項目,但結合公司內部系統的特點,直接採用會有有些限制,例如要實現定製界面,無刷新加載應用,且不能對現有項目的開發和部署造成影響,因此決定自研相關技術。

    四、架構設計

    4.1 應用層

    應用層包括所有接入微服務工作台的內部系統,他們各自開發與部署,接入前後沒有多大影響,只是需要針對微服務層單獨輸出打包一份靜態資源;

    4.2 微服務層

    微服務層作為核心模塊,擁有資源加載、路由管理、狀態管理和用戶認證管理幾大功能,具體內容將在後面詳細闡述,架構整體工作流程如下:

    4.3 基礎支撐層

    基礎支撐層作為基座,提供微服務運行的環境和容器,同時接入其他後端服務,豐富實用場景和業務功能;

    五、技術重難點

    要實現自定義微前端架構,難點在於需要管理和整合多個應用,確保應用之間獨立運行,彼此不受影響,需要解決如下幾個問題:

    5.1 資源管理

    5.1.1資源加載

    每個應用有一個應用資源管理和註冊的文件(app.regiser.js),其中包含路由信息,應用配置信息(configs.js)和靜態資源清單,當首次切換到某應用時,首先加載app.register.js文件,完成路由和應用信息的註冊,然後根據當前瀏覽器路由地址加載對應的靜態文件,完成頁面渲染,從而將各應用的靜態資源串聯起來,其中註冊入口文件通過webpack插件來實現,具體實現如下:
    
    FuluAppRegisterPlugin.prototype.apply = function(compiler) {
       appId = extraAppId();
       var entry = compiler.options.entry;
       if (isArray(entry)) {
                for (var i = 0; i &lt; entry.length; i++) {
                    if (isIndexFile(entry[i])) { // 入口文件
                        indexFileEdit(entry[i]);
                        entry[i] = entry[i].replace(indexEntryRegx, indeEntryTemp); // 替換入口文件
                        i = entry.length;
                    }
                }
        } else {
                if (isIndexFile(entry)) { // 入口文件
                    indexFileEdit(entry); // 重新生成和編輯入口文件
                    compiler.options.entry = compiler.options.entry.replace(indexEntryRegx, indeEntryTemp); // 替換入口文件
                }
        }
        compiler.hooks.done.tap('fulu-app-register-done', function(compilation) {
                fs.unlinkSync(tempFilePath); // 刪除臨時文件
                return compilation;
        });
        compiler.hooks.emit.tap('fulu-app-register', function(compilation) {
            var contentStr = 'window.register("'+ appId + '", {\nrouter: [ \n ' + extraRouters() + ' \n],\nentry: {\n'; // 全局註冊方法
            var entryCssArr = [];
            var entryJsArr = [];
            for (var filename in compilation.assets) {
                if (filename.match(mainCssRegx)) { // 提取css文件
                    entryCssArr.push('\"' + filename + '\"');
                } else if (filename.match(mainJsRegx) || filename.match(manifestJsRegx) || filename.match(vendorsJsRegx)) { // 提取js文件
                    entryJsArr.push('\"' + filename + '\"');
                }
            }
            contentStr += ('css: ['+ entryCssArr.join(', ') +'],\n'); // css資源清單
            contentStr += ('js: ['+ entryJsArr.join(', ') +'],\n }\n});\n'); // js資源清單
            compilation.assets['resources/js/' + appId + '-app-register.js'] = { // 生成appid-app-register.js入口文件
                source: function() {
                    return contentStr;
                },
                size: function() {
                    return contentStr.length;
                }
            };
            return compilation;
        });
    };
    
    5.1.2資源文件名
    微服務輸出打包模式下,靜態資源統一打包形式以項目id開頭,形如10000092-main.js, 文件名稱的修改通過webpack的插件實現;
    

    核心實現代碼如下:

    FuluAppRegisterPlugin.prototype.apply = function(compiler) {
        ......
        compiler.options.output.filename = addIdToFileName(compiler.options.output.filename, appId);
        compiler.options.output.chunkFilename = addIdToFileName(compiler.options.output.chunkFilename, appId);
        compiler.options.plugins.forEach((c) =&gt; {
            if (c.options) {
                if (c.options.filename) {
                    c.options.filename = addIdToFileName(c.options.filename, appId);
                }
                if (c.options.chunkFilename) {
                    c.options.chunkFilename = addIdToFileName(c.options.chunkFilename, appId);
                }
            }
        });
       ......
    };
    

    5.2 路由管理

    路由分為應用級和菜單級兩大類,應用類以應用id為前綴,將各應用區分開,避免路由地址重名的情況,菜單級的路由由各應用的路由系統自行管理,結構如下:
    

    5.3 狀態分隔

    前端項目通過狀態管理庫來進行數據的管理,為了保證各應用彼此間獨立,因此需要修改狀態庫的映射關係,這一部分需要藉助於webpack插件來進行統一的代碼層面調整,包括model和view兩部分代碼,model定義了狀態對象,view藉助工具完成狀態對象的映射,調整規則為【應用id+舊狀態對象名稱】,下面來講解一下插件的實現;
    

    插件的實現原理是藉助AST的搜索語法匹配源代碼中的狀態編寫和綁定的相關代碼,然後加上應用編號前綴,變成符合預期的AST,最後輸出成目標代碼:
    
    module.exports = function(source) {
          var options = loaderUtils.getOptions(this);
    	stuff = 'app' + options.appId;
    	isView = !!~source.indexOf('React.createElement'); // 是否是視圖層
    	allFunc = [];
    	var connectFn = "function connect(state) {return Object.keys(state).reduce(function (obj, k) { var nk = k.startsWith('"+stuff+"') ? k.replace('"+stuff+"', '') : k; obj[nk] = state[k]; return obj;}, {});}";
    	connctFnAst = parser.parse(connectFn);
    	const ast = parser.parse(source, { sourceType: "module", plugins: ['dynamicImport'] });
    	traverse(ast, {
    		CallExpression: function(path) {
    			if (path.node.callee && path.node.callee.name === 'connect') { // export default connext(...)
    				if (isArray(path.node.arguments)) {
    					var argNode = path.node.arguments[0];
    					if (argNode.type === 'FunctionExpression') { // connect(() => {...})
    						traverseMatchFunc(argNode);
    					} else if (argNode.type === 'Identifier' && argNode.name !== 'mapStateToProps') { // connect(zk)
    						var temp_node = allFunc.find((fnNode) => {
    							return fnNode.id.name === argNode.name;
    						});
    						if (temp_node) {
    							traverseMatchFunc(temp_node);
    						}
    					}
    				}
    			} else if (path.node.callee && path.node.callee.type === 'SequenceExpression') {
    				if (isArray(path.node.callee.expressions)) {
    					for (var i = 0; i < path.node.callee.expressions.length; i++) {
    						if (path.node.callee.expressions[i].type === 'MemberExpression'
    							&& path.node.callee.expressions[i].object.name === '_dva'
    							&& path.node.callee.expressions[i].property.name === 'connect') {
    								traverseMatchFunc(path.node.arguments[0]);
    								i = path.node.callee.expressions.length;
    						}
    					}
    				}
    			}
    		},
    		FunctionDeclaration: function(path) {
    			if (path.node.id.name === 'mapStateToProps' && path.node.body.type === 'BlockStatement') {
    				traverseMatchFunc(path.node);
    			}
    			allFunc.push(path.node);
    		},
    		ObjectExpression: function(path) {
    			if (isView) {
    				return;
    			}
    			if (isArray(path.node.properties)) {
    				var temp = path.node.properties;
    				for (var i = 0; i < temp.length; i++) {
    					if (temp[i].type === 'ObjectProperty' && temp[i].key.name === 'namespace') {
    						temp[i].value.value = stuff + temp[i].value.value;
    						i = temp.length;
    					}
    				}
    			}
    		}
    	});
    	return core.transformFromAstSync(ast).code;
    };
    

    5.4 框架容器渲染

    完成以上步驟的改造,就可以實現容器中的頁面渲染,這一部分涉及到組件庫框架層面的調整,大流程如下圖:

    六、構建流程

    6.1 使用插件

    構建過程中涉及到兩款自開發的插件,分別是fulu-app-register-plugin和fulu-app-loader;

    6.1.1 安裝
    npm i fulu-app-register-plugin fulu-app-loader -D;
    
    6.1.2 配置

    webpack配置修改:

    const FuluAppRegisterPlugin = require('fulu-app-register-plugin');
    module: {
       rules: [{
             test: /\.jsx?$/,
             loader: 'fulu-app-loader',
          }
       ]
    }
    plugins: [
        new FuluAppRegisterPlugin(),
        ......
    ]
    

    6.2.編譯

    編譯過程與目前項目保持一致,相比以前,多輸出了一份微前端項目編譯代碼,流程如下:

    七、遺留問題

    7.1 js環境隔離

    由於各應用都加載到同一個運行環境,因此如果修改了公共的部分,則會對其他系統產生不可預知的影響,目前沒有比較好的辦法來解決,後續將持續關注這方面的內容,逐漸優化達到風險可制的效果。
    

    7.2.獲取token

    目前應用切換使用重定向來完成token獲取,要實現如上所述的微前端效果,需要放棄這種方式,改用接口調用異步獲取,或者其他解決方案。
    

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

    ※別再煩惱如何寫文案,掌握八大原則!

  • 用隊列實現棧,用棧實現隊列,聽起來有點繞,都搞懂了就掌握了精髓!

    用隊列實現棧,用棧實現隊列,聽起來有點繞,都搞懂了就掌握了精髓!

    目錄

    • 一、背景
    • 二、概念
      • 2.1 棧
      • 2.2 隊列
    • 三、棧和隊列的相互實現
      • 3.1 用隊列實現棧
      • 3.2 用棧實現隊列
    • 四、總結

    一、背景

    棧和隊列是數據結構中最常用到的兩種結構,有非常廣泛的運用,該篇文章將通過動畫的手段,展示棧和隊列相互實現的底層原理,讓我們真正搞懂棧和隊列的特性。

    二、概念

    2.1 棧

    棧[Stack]:是一種限定僅在表尾進行插入和刪除操作的線性表;即後進先出(LIFO-last in first out),最後插入的元素最先出來

    • 入棧(push)
    • 出棧 (pop)
    2.2 隊列

     隊列[Queue]:是一種限定僅在表頭進行刪除操作,僅在表尾進行插入操作的線性表;即先進先出(FIFO-first in first out):最先插入的元素最先出來。

    • 入隊(enqueue)
    • 出隊(dequeue)

    三、棧和隊列的相互實現

    3.1 用隊列實現棧
    • 模擬入棧的實現原理
      — 棧的特性是新加入的元素出現在棧頂,保證後進先出。
      — 隊列的特性為新加入的元素出現在隊尾,隊列的隊尾元素最後出隊。
      按以上兩個前提,我們可以讓隊頭至隊尾前的其它所有元素依次出隊再入隊,直至在隊尾新加入的元素被移到隊頭,也即實現了讓新壓入的元素保留在棧頂

    • 模擬出棧的實現原理
      — 由於在入棧時保證隊列中新加入隊尾的元素被移到了隊頭,出棧只需彈出隊頭元素即可。

    • 完整代碼實現

    /**
     * 用隊列模擬實現棧
     *
     * @author zhuhuix
     * @date 2020-06-09
     */
    public class QueueImplStack {
    
        // 定義隊列
        private Queue<Integer> queue;
    
        public QueueImplStack() {
            queue = new LinkedList();
        }
    
        // 入棧--在隊尾加入元素后,讓其他元素按順序出隊再入隊,保持新加入的元素永遠在隊頭
        public void push(Integer e) {
            queue.offer(e);
            int size = queue.size();
            int i = 0;
            while (i < size - 1) {
                queue.offer(queue.poll());
                i++;
            }
        }
    
        // 出棧--將隊尾前的其它所有元素出隊再入隊,直至隊尾元素移到隊頭
        public Integer pop() {
            return queue.poll();
        }
    
        // 查看棧頂元素--即隊頭元素
        public Integer peek() {
            return queue.peek();
        }
    
        // 是否為空
        public boolean isEmpty() {
            return queue.isEmpty();
        }
    
        public static void main(String[] args) {
            QueueImplStack stack = new QueueImplStack();
            stack.push(1);
            System.out.println(stack.peek());
            stack.push(2);
            System.out.println(stack.peek());
            stack.push(3);
            System.out.println(stack.peek());
            System.out.println("=============");
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            System.out.println(stack.isEmpty());
    
        }
    }
    
    
    3.2 用棧實現隊列
    • 模擬入隊的實現原理
      — 隊列的特性最新入隊的元素需排在隊尾,最先入隊的元素排在隊頭,按隊頭到隊尾的順序依次出隊。
      — 對應到棧的數據結構上,也即需將新加入的元素保留在棧頂,保證先進先出。
      按以上兩個前提,需在存放數據的棧的基礎上再增加一個輔助棧,在每次入隊時,先將存放數據的棧彈入輔助棧,再把需加入的新元素壓入數據棧底,最後把輔助棧中的元素彈出依次壓入數據棧,這樣保證了新加入的元素,沉在棧底。

      模擬出隊的實現原理
      — 由於在入隊時,通過數據棧與輔助棧的交換,實現了后加入的元素沉在棧底,先進入的元素保留在棧頂,直接通過出棧彈出即可。

      • 完整代碼實現
    /**
     * 用棧模擬實現隊列
     *
     * @author zhuhuix
     * @date 2020-06-09
     */
    public class StackImplQueue {
        // 數據棧
        private Stack<Integer> stack;
        // 輔助棧
        private Stack<Integer> aux;
    
        StackImplQueue() {
            stack = new Stack<>();
            aux = new Stack<>();
        }
    
        // 入隊--通過數據棧與輔助棧相互交換,保證新加入的元素沉在數據棧底
        public void enqueue(Integer e) {
            while (!stack.isEmpty()) {
                aux.push(stack.pop());
            }
            stack.push(e);
            while(!aux.isEmpty()){
                stack.push(aux.pop());
            }
    
        }
    
        // 出隊--彈出數據棧元素
        public Integer dequeue(){
            return stack.pop();
        }
    
        // 查看隊頭元素
        public Integer peek(){
            return stack.peek();
        }
    
        // 是否為空
        public boolean isEmpty(){
            return stack.isEmpty();
        }
    
        public static void main(String[] args) {
            StackImplQueue queue = new StackImplQueue();
            queue.enqueue(1);
            System.out.println(queue.peek());
            queue.enqueue(2);
            System.out.println(queue.peek());
            queue.enqueue(3);
            System.out.println(queue.peek());
            System.out.println("=============");
            System.out.println(queue.dequeue());
            System.out.println(queue.dequeue());
            System.out.println(queue.dequeue());
    
        }
    }
    
    

    四、總結

    通過以上棧和隊列相互交叉的實踐,我們對棧和隊列的重大特性有了深入了解:

    • 棧和隊列都是線性連續結構,增加和刪除元素不會影響破此連續性
    • 棧通過棧頂的操作實現元素的增加與刪除,也即只能在一端進行操作
    • 隊列通過隊尾增加元素,隊頭刪除元素,也即可以在兩端操作

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※台北網頁設計公司全省服務真心推薦

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※推薦評價好的iphone維修中心

    網頁設計最專業,超強功能平台可客製化

    ※別再煩惱如何寫文案,掌握八大原則!