北極海冰縮減 加劇致命動物病毒擴散

摘錄自2019年11月08日中央通訊社北極報導

全球暖化引發的北極海冰縮減,正迫使北極熊等動物尋求適應,否則就會面臨死亡,但如今科學家進一步警告,北極海冰減少也可能導致動物暴露於新的致命疾病。

加州大學戴維斯分校(University of California, Davis)學者高德司坦(Tracey Goldstein)領導一項為期15年研究,研究報告今天(8日)在「科學報告」期刊(Scientific Reports)發表。研究發現,2002年導致數千隻北大西洋歐洲港海豹(Harbor seal)死亡的海豹瘟熱病毒(Phocine Distemper Virus, PDV),與2004年阿拉斯加沿岸外海的海獺體內存在的此種病毒有關連。

研究指出,自2003年起整個北太平洋出現廣泛海豹瘟熱病毒暴露與感染,於當年以及2009年達到最高峰。這些高峰發生在北極海冰減少之後。罪魁禍首似乎是不斷縮減的北極海冰,此現象會劇烈重塑該地區,影響到動物和人類。其中包括在俄羅斯北部和加拿大打開新通道,而動物和疾病都能通過那些新通道。

研究表示:「除了影響動物的營養及生理壓力以外,環境變化也可能導致暴露於新病原體。海冰流失改變動物行為,並移除物理障礙,可能創造出動物移動的新途徑,把感染性疾病引入北極。」

研究報告的結論指出:「打開穿越北極海冰的水域通路,與海豹瘟熱病毒暴露和感染升高有關連,顯示海豹瘟熱病毒及其他病原體,跨越北大西洋及北太平洋海洋哺乳動物族群間的機會,可能會更常見。」

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

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

增長率為76% 全球電動車市場達74萬輛車

德國Baden-Württemberg省的太陽能和氫能研究中心(ZSW)日前發佈的一份報告透露,全球電動汽車市場目前已達74萬輛車,其中幾乎有一半(32萬)註冊於2014年。基於電動車約為76%的增長率,去年汽車電池供應商的收益為20億歐元。   其中,美國市場增長69%,本土道路上的電動汽車數量增至29萬輛,占全球的三分之一。而中國是世界上第三最強大的電動車市場,2014年增加了約5萬4千輛,增長了120%,全國道路上接近有10萬輛電動車,僅次於擁有11萬電動車(2014年45%的速度增長)的日本。   該德國中心發現,這三個主要國家的扶持政策説明加速電動汽車的採用。在中國,例如,國產電動車是被補貼的,對終端消費者來講比較便宜。而德國相反,沒有市場激勵機制,從而只有11700新車註冊。   此外,該報告還發現,日產的Leaf是最流行的電動車品牌,創下了自2010年以來15萬的全球註冊記錄。第二是通用汽車公司的雪佛蘭Volt,全球註冊75000輛,第三為6萬註冊量的豐田Prius。而特斯拉S型已售出5萬輛,遙遙領先15000輛的寶馬的i3,事實上,i3才在市場上超過12個月,因此在這麼短時間內已具有這樣的市場份額,是令人印象深刻的。   2012年和2014年之間新車註冊數量每年增加兩倍。“如果近幾年的勢頭依然不減,在短短幾個月的時間裡,全球電動車的數量將超過百萬。”ZSW電化學能源技術事業部主任Werner Tillmetz表示。 

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

特斯拉有望 3 年後內在中國設廠

特斯拉(Tesla)執行長馬斯克(Elon Musk)在博鰲論壇期間表示,特斯拉希望 3 年內在中國大陸建立生產和設計基地,且馬斯克再度承諾,儘管目前所有在中國市場上銷售的特斯拉汽車都是從美國加州進口的,但特斯拉對發展中國市場有強烈的長期意向,盼能建立本土的生產和設計基地。   馬斯克表示,特斯拉將長期開拓中國市場,於 3 年內在中國設立工廠和研發中心,但得等到特斯拉在加州的工廠實現全能運轉,達到全部產能後,特斯拉才會考慮在海外市場建廠。因此,特斯拉還會持續進口到中國市場一段時間。   針對 2014 年特斯拉在中國的銷售不如預期,據馬斯克解釋,目前特斯拉處於「投機後遺症」的恢復期當中,「中國是特斯拉在全世界範圍內唯一有多餘庫存的市場。我們現在還在消化庫存中」。2014 年特斯拉剛剛進入中國市場時,投機者造成市場需求「極高」的假象。後來投機者取消訂單,導致庫存增加。   馬斯克並表示,在新戰略的引導下,特斯拉 3 月在中國市場的銷量較 2 月大幅成長,增幅達 130% 至 150%。  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

FreeSql 使用 ToTreeList/AsTreeCte 查詢無限級分類表

關於無限級分類

第一種方案:
使用遞歸算法,也是使用頻率最多的,大部分開源程序也是這麼處理,不過一般都只用到四級分類。 這種算法的數據庫結構設計最為簡單。category表中一個字段id,一個字段fid(父id)。這樣可以根據WHERE id = fid來判斷上一級內容,運用遞歸至最頂層。
分析:通過這種數據庫設計出的無限級,可以說讀取的時候相當費勁,所以大部分的程序最多3-4級分類,這就足以滿足需求,從而一次性讀出所有的數據,再對得到數組或者對象進行遞歸。本身負荷還是沒太大問題。但是如果分類到更多級,那是不可取的辦法。
這樣看來這種分類有個好處,就是增刪改的時候輕鬆了…然而就二級分類而言,採用這種算法就應該算最優先了。

第二種方案:
設置fid字段類型為varchar,將父類id都集中在這個字段里,用符號隔開,比如:1,3,6
這樣可以比較容易得到各上級分類的ID,而且在查詢分類下的信息的時候,
可以使用:SELECT * FROM category WHERE pid LIKE “1,3%”。

分 析:相比於遞歸算法,在讀取數據方面優勢非常大,但是若查找該分類的所有 父分類 或者 子分類 查詢的效率也不是很高,至少也要二次query,從某種意義看上,個人覺得不太符合數據庫範式的設計。倘若遞增到無限級,還需考慮字段是否達到要求,而且 在修改分類和轉移分類的時候操作將非常麻煩。
暫時,在自己項目中用的就是類似第二種方案的解決辦法。就該方案在我的項目中存在這樣的問題, 如果當所有數據記錄達到上萬甚至10W以上后,一次性將所以分類,有序分級的現實出來,效率很低。極有可能是項目處理數據代碼效率低帶來的。現在正在改良。

第三種方案:
  無限級分類—-改進前序遍歷樹
那 么理想中的樹型結構應具備哪些特點呢?數據存儲冗餘小、直觀性強;方便返回整個樹型結構數據;可以很輕鬆的返回某一子樹(方便分層加載);快整獲以某節點 的祖譜路徑;插入、刪除、移動節點效率高等等。帶着這些需求我查找了很多資料,發現了一種理想的樹型結構數據存儲及操作算法,改進的前序遍歷樹模型 (The Nested Set Model)。
原理:
我們先把樹按照水平方式擺開。從根節點開始(“Food”),然後他的左邊寫 上1。然後按照樹的順序(從上到下)給“Fruit”的左邊寫上2。這樣,你沿着樹的邊界走啊走(這就是“遍歷”),然後同時在每個節點的左邊和右邊寫上 数字。最後,我們回到了根節點“Food”在右邊寫上18。下面是標上了数字的樹,同時把遍歷的順序用箭頭標出來了。

我 們稱這些数字為左值和右值(如,“Food”的左值是1,右值是18)。正如你所見,這些数字按時了每個節點之間的關係。因為“Red”有3和6兩個值, 所以,它是有擁有1-18值的“Food”節點的後續。同樣的,我們可以推斷所有左值大於2並且右值小於11的節點,都是有2-11的“Fruit” 節點的後續。這樣,樹的結構就通過左值和右值儲存下來了。這種數遍整棵樹算節點的方法叫做“改進前序遍歷樹”算法。

表結構設計:

那 么我們怎樣才能通過一個SQL語句把所有的分類都查詢出來呢,而且要求如果是子類的話前面要打幾個空格以表現是子分類。要想查詢出所有分類很好 辦:SELECT * FROM category WHERE lft>1 AND lft<18 ORDER BY lft這樣的話所有的分類都出來了,但是誰是誰的子類卻分不清,那麼怎麼辦呢?我們仔細看圖不難發現如果相鄰的兩條記錄的右值第一條的右值比第二條的大那 么就是他的父類,比如food的右值是18而fruit的右值是11 那麼food是fruit的父類,但是又要考慮到多級目錄。於是有了這樣的設計,我們用一個數組來存儲上一條記錄的右值,再把它和本條記錄的右值比較,如 果前者比後者小,說明不是父子關係,就用array_pop彈出數組,否則就保留,之後根據數組的大小來打印空格。

以上內容引用出處:https://www.cnblogs.com/badboys/p/9945296.html

關於第三種設計的更多資料請點擊查看原文,因為過於複雜(過重)被使用的頻率不高。

引出痛點

無限級分類(父子)是一種比較常用的表設計,每種設計方式突出優勢的同時也帶來缺陷,如:

  • 第一種方案:表設計中只有 parent_id 字段,寫入數據方便,困擾:查詢麻煩,許多使用了 ORM 的項目被迫使用 SQL 解決該場景;
  • 第二種方案:表設計中冗餘子級id便於查詢,困擾:添加/更新/刪除的時候需要重新計算;
  • 第三種方案:表設計中存儲左右值編碼,困擾:同上;

第一種方案的設計最簡單,本文後面的內容是在該基礎上,使用 FreeSql 實現 ToTreeList(內存加工樹型)、AsTreeCte(實現遞歸向下/向上查詢),滿足大眾日常使用。

關於 FreeSql

FreeSql 是功能強大的對象關係映射技術(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.0+ 或 Xamarin,以 MIT 開源協議託管於 github,單元測試數量 4528個,nuget 下載量 151K,支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/達夢/人大金倉/神州通用/Access;

源碼地址:https://github.com/dotnetcore/FreeSql

作者說過:每一個功能代表他的一撮頭髮!

第一步:定義導航屬性

FreeSql 導航屬性之中,有針對父子關係的設置方式,ToTreeList/AsTreeCte 依賴該設置,如下:

public class Area
{
  [Column(IsPrimary = true)]
  public string Code { get; set; }

  public string Name { get; set; }
  public string ParentCode { get; set; }

  [Navigate(nameof(ParentCode)), JsonIgnore] //JsonIgnore 是 json.net 的特性
  public Area Parent { get; set; }
  [Navigate(nameof(ParentCode))]
  public List<Area> Childs { get; set; }
}

關於導航屬性

定義 Parent 屬性,在表達式中可以這樣:

fsql.Select<Area>()
  .Where(a => a.Parent.Parent.Parent.Name == "中國")
  .First();

定義 Childs 屬性,在表達式中可以這樣(子查詢):

fsql.Select<Area>()
  .Where(a => a.Childs.AsSelect().Any(c => c.Name == "北京"))
  .First();

定義 Childs 屬性,還可以使用【級聯保存】、【貪婪加載】 等等操作。

添加測試數據

fsql.Delete<Area>().Where("1=1").ExecuteAffrows();
var repo = fsql.GetRepository<Area>();
repo.DbContextOptions.EnableAddOrUpdateNavigateList = true;
repo.DbContextOptions.NoneParameter = true;
repo.Insert(new Area
{
  Code = "100000",
  Name = "中國",
  Childs = new List<Area>(new[] {
    new Area
    {
      Code = "110000",
      Name = "北京",
      Childs = new List<Area>(new[] {
        new Area{ Code="110100", Name = "北京市" },
        new Area{ Code="110101", Name = "東城區" },
      })
    }
  })
});

第二步:使用 ToTreeList 返回樹型數據

配置好父子屬性之後,就可以這樣用了:

var t1 = fsql.Select<Area>().ToTreeList();
Assert.Single(t1);
Assert.Equal("100000", t1[0].Code);
Assert.Single(t1[0].Childs);
Assert.Equal("110000", t1[0].Childs[0].Code);
Assert.Equal(2, t1[0].Childs[0].Childs.Count);
Assert.Equal("110100", t1[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t1[0].Childs[0].Childs[1].Code);

查詢數據本來是平面的,ToTreeList 方法將返回的平面數據在內存中加工為樹型 List 返回。

[
  {
    "ParentCode": null,
    "Childs": [
      {
        "ParentCode": "100000",
        "Childs": [
          {
            "ParentCode": "110000",
            "Childs": [],
            "Code": "110100",
            "Name": "北京市"
          },
          {
            "ParentCode": "110000",
            "Childs": [],
            "Code": "110101",
            "Name": "東城區"
          }
        ],
        "Code": "110000",
        "Name": "北京"
      }
    ],
    "Code": "100000",
    "Name": "中國"
  }
]

第三步:使用 AsTreeCte 遞歸查詢

若不做數據冗餘的無限級分類表設計,遞歸查詢少不了,AsTreeCte 正是解決遞歸查詢的封裝,方法參數說明:

參數 描述
(可選) pathSelector 路徑內容選擇,可以設置查詢返回:中國 -> 北京 -> 東城區
(可選) up false(默認):由父級向子級的遞歸查詢,true:由子級向父級的遞歸查詢
(可選) pathSeparator 設置 pathSelector 的連接符,默認:->
(可選) level 設置遞歸層級

通過測試的數據庫:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、達夢、人大金倉

姿勢一:AsTreeCte() + ToTreeList

var t2 = fsql.Select<Area>()
  .Where(a => a.Name == "中國")
  .AsTreeCte() //查詢 中國 下的所有記錄
  .OrderBy(a => a.Code)
  .ToTreeList(); //非必須,也可以使用 ToList(見姿勢二)
Assert.Single(t2);
Assert.Equal("100000", t2[0].Code);
Assert.Single(t2[0].Childs);
Assert.Equal("110000", t2[0].Childs[0].Code);
Assert.Equal(2, t2[0].Childs[0].Childs.Count);
Assert.Equal("110100", t2[0].Childs[0].Childs[0].Code);
Assert.Equal("110101", t2[0].Childs[0].Childs[1].Code);
// WITH "as_tree_cte"
// as
// (
// SELECT 0 as cte_level, a."Code", a."Name", a."ParentCode" 
// FROM "Area" a 
// WHERE (a."Name" = '中國')

// union all

// SELECT wct1.cte_level + 1 as cte_level, wct2."Code", wct2."Name", wct2."ParentCode" 
// FROM "as_tree_cte" wct1 
// INNER JOIN "Area" wct2 ON wct2."ParentCode" = wct1."Code"
// )
// SELECT a."Code", a."Name", a."ParentCode" 
// FROM "as_tree_cte" a 
// ORDER BY a."Code"

姿勢二:AsTreeCte() + ToList

var t3 = fsql.Select<Area>()
  .Where(a => a.Name == "中國")
  .AsTreeCte()
  .OrderBy(a => a.Code)
  .ToList();
Assert.Equal(4, t3.Count);
Assert.Equal("100000", t3[0].Code);
Assert.Equal("110000", t3[1].Code);
Assert.Equal("110100", t3[2].Code);
Assert.Equal("110101", t3[3].Code);
//執行的 SQL 與姿勢一相同

姿勢三:AsTreeCte(pathSelector) + ToList

設置 pathSelector 參數后,如何返回隱藏字段?

var t4 = fsql.Select<Area>()
  .Where(a => a.Name == "中國")
  .AsTreeCte(a => a.Name + "[" + a.Code + "]")
  .OrderBy(a => a.Code)
  .ToList(a => new { 
    item = a, 
    level = Convert.ToInt32("a.cte_level"), 
    path = "a.cte_path" 
  });
Assert.Equal(4, t4.Count);
Assert.Equal("100000", t4[0].item.Code);
Assert.Equal("110000", t4[1].item.Code);
Assert.Equal("110100", t4[2].item.Code);
Assert.Equal("110101", t4[3].item.Code);
Assert.Equal("中國[100000]", t4[0].path);
Assert.Equal("中國[100000] -> 北京[110000]", t4[1].path);
Assert.Equal("中國[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
Assert.Equal("中國[100000] -> 北京[110000] -> 東城區[110101]", t4[3].path);
// WITH "as_tree_cte"
// as
// (
// SELECT 0 as cte_level, a."Name" || '[' || a."Code" || ']' as cte_path, a."Code", a."Name", a."ParentCode" 
// FROM "Area" a 
// WHERE (a."Name" = '中國')

// union all

// SELECT wct1.cte_level + 1 as cte_level, wct1.cte_path || ' -> ' || wct2."Name" || '[' || wct2."Code" || ']' as cte_path, wct2."Code", wct2."Name", wct2."ParentCode" 
// FROM "as_tree_cte" wct1 
// INNER JOIN "Area" wct2 ON wct2."ParentCode" = wct1."Code"
// )
// SELECT a."Code" as1, a."Name" as2, a."ParentCode" as5, a.cte_level as6, a.cte_path as7 
// FROM "as_tree_cte" a 
// ORDER BY a."Code"

更多姿勢…請根據代碼註釋進行嘗試

源碼地址:https://github.com/dotnetcore/FreeSql

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

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

不再逼動物賺錢 吳哥窟園區2020年起禁止騎象

摘錄自2019年11月15日中央通訊社吳哥窟報導

柬埔寨的吳哥窟暨暹粒地區保護管理局(Apsara Authority)官員今天(15日)表示,明年初開始將禁止吳哥窟所在考古園區的大象騎乘活動。

吳哥考古園區位在柬埔寨北部,匯集柬國大多數外籍遊客,去年創下約600萬造訪人次新高紀錄。不少遊客選擇騎乘大象在園區內的古老寺廟遺址間漫遊。吳哥窟暨暹粒地區保護管理局發言人告訴法新社:「藉大象營利已不再恰當。」他還說,部分大象年事已高。

園區原本有14頭「在職」大象,其中5頭已被送到距離寺廟古蹟群大約40公里的樹林安置。管理局發言人指出:「牠們在那裡將以自然方式度過餘生。」他強調,擁有這些大象的企業將持續照護牠們。

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

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

Spring Boot 2.x基礎教程:MyBatis的多數據源配置

前两天,我們已經介紹了關於JdbcTemplate的多數據源配置以及Spring Data JPA的多數據源配置,接下來具體說說使用MyBatis時候的多數據源場景該如何配置。

添加多數據源的配置

先在Spring Boot的配置文件application.properties中設置兩個你要鏈接的數據庫配置,比如這樣:

spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver

說明與注意

  1. 多數據源配置的時候,與單數據源不同點在於spring.datasource之後多設置一個數據源名稱primary和secondary來區分不同的數據源配置,這個前綴將在後續初始化數據源的時候用到。
  2. 數據源連接配置2.x和1.x的配置項是有區別的:2.x使用spring.datasource.secondary.jdbc-url,而1.x版本使用spring.datasource.secondary.url。如果你在配置的時候發生了這個報錯java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.,那麼就是這個配置項的問題。
  3. 可以看到,不論使用哪一種數據訪問框架,對於數據源的配置都是一樣的。

初始化數據源與MyBatis配置

完成多數據源的配置信息之後,就來創建個配置類來加載這些配置信息,初始化數據源,以及初始化每個數據源要用的MyBatis配置。

這裏我們繼續將數據源與框架配置做拆分處理:

  1. 單獨建一個多數據源的配置類,比如下面這樣:
@Configuration
public class DataSourceConfiguration {

    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

}

可以看到內容跟JdbcTemplate、Spring Data JPA的時候是一模一樣的。通過@ConfigurationProperties可以知道這兩個數據源分別加載了spring.datasource.primary.*spring.datasource.secondary.*的配置。@Primary註解指定了主數據源,就是當我們不特別指定哪個數據源的時候,就會使用這個Bean真正差異部分在下面的JPA配置上。

  1. 分別創建兩個數據源的MyBatis配置。

Primary數據源的JPA配置:

@Configuration
@MapperScan(
        basePackages = "com.didispace.chapter39.p",
        sqlSessionFactoryRef = "sqlSessionFactoryPrimary",
        sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
public class PrimaryConfig {

    private DataSource primaryDataSource;

    public PrimaryConfig(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
        this.primaryDataSource = primaryDataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(primaryDataSource);
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactoryPrimary());
    }

}

Secondary數據源的JPA配置:

@Configuration
@MapperScan(
        basePackages = "com.didispace.chapter39.s",
        sqlSessionFactoryRef = "sqlSessionFactorySecondary",
        sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
public class SecondaryConfig {

    private DataSource secondaryDataSource;

    public SecondaryConfig(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        this.secondaryDataSource = secondaryDataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(secondaryDataSource);
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactorySecondary());
    }

}

說明與注意

  1. 配置類上使用@MapperScan註解來指定當前數據源下定義的Entity和Mapper的包路徑;另外需要指定sqlSessionFactory和sqlSessionTemplate,這兩個具體實現在該配置類中類中初始化。
  2. 配置類的構造函數中,通過@Qualifier註解來指定具體要用哪個數據源,其名字對應在DataSourceConfiguration配置類中的數據源定義的函數名。
  3. 配置類中定義SqlSessionFactory和SqlSessionTemplate的實現,注意具體使用的數據源正確(如果使用這裏的演示代碼,只要第二步沒問題就不需要修改)。

上一篇介紹JPA的時候,因為之前介紹JPA的使用時候,說過實體和Repository定義的方法,所以省略了 User 和 Repository的定義代碼,但是還是有讀者問怎麼沒有這個,其實都有說明,倉庫代碼里也都是有的。未避免再問這樣的問題,所以這裏就貼一下吧。

根據上面Primary數據源的定義,在com.didispace.chapter39.p包下,定義Primary數據源要用的實體和數據訪問對象,比如下面這樣:

@Data
@NoArgsConstructor
public class UserPrimary {

    private Long id;

    private String name;
    private Integer age;

    public UserPrimary(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

public interface UserMapperPrimary {

    @Select("SELECT * FROM USER WHERE NAME = #{name}")
    UserPrimary findByName(@Param("name") String name);

    @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
    int insert(@Param("name") String name, @Param("age") Integer age);

    @Delete("DELETE FROM USER")
    int deleteAll();

}

根據上面Secondary數據源的定義,在com.didispace.chapter39.s包下,定義Secondary數據源要用的實體和數據訪問對象,比如下面這樣:

@Data
@NoArgsConstructor
public class UserSecondary {

    private Long id;

    private String name;
    private Integer age;

    public UserSecondary(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

public interface UserMapperSecondary {

    @Select("SELECT * FROM USER WHERE NAME = #{name}")
    UserSecondary findByName(@Param("name") String name);

    @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
    int insert(@Param("name") String name, @Param("age") Integer age);

    @Delete("DELETE FROM USER")
    int deleteAll();
}

測試驗證

完成了上面之後,我們就可以寫個測試類來嘗試一下上面的多數據源配置是否正確了,先來設計一下驗證思路:

  1. 往Primary數據源插入一條數據
  2. 從Primary數據源查詢剛才插入的數據,配置正確就可以查詢到
  3. 從Secondary數據源查詢剛才插入的數據,配置正確應該是查詢不到的
  4. 往Secondary數據源插入一條數據
  5. 從Primary數據源查詢剛才插入的數據,配置正確應該是查詢不到的
  6. 從Secondary數據源查詢剛才插入的數據,配置正確就可以查詢到

具體實現如下:

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class Chapter39ApplicationTests {

    @Autowired
    private UserMapperPrimary userMapperPrimary;
    @Autowired
    private UserMapperSecondary userMapperSecondary;

    @Before
    public void setUp() {
        // 清空測試表,保證每次結果一樣
        userMapperPrimary.deleteAll();
        userMapperSecondary.deleteAll();
    }

    @Test
    public void test() throws Exception {
        // 往Primary數據源插入一條數據
        userMapperPrimary.insert("AAA", 20);

        // 從Primary數據源查詢剛才插入的數據,配置正確就可以查詢到
        UserPrimary userPrimary = userMapperPrimary.findByName("AAA");
        Assert.assertEquals(20, userPrimary.getAge().intValue());

        // 從Secondary數據源查詢剛才插入的數據,配置正確應該是查詢不到的
        UserSecondary userSecondary = userMapperSecondary.findByName("AAA");
        Assert.assertNull(userSecondary);

        // 往Secondary數據源插入一條數據
        userMapperSecondary.insert("BBB", 20);

        // 從Primary數據源查詢剛才插入的數據,配置正確應該是查詢不到的
        userPrimary = userMapperPrimary.findByName("BBB");
        Assert.assertNull(userPrimary);

        // 從Secondary數據源查詢剛才插入的數據,配置正確就可以查詢到
        userSecondary = userMapperSecondary.findByName("BBB");
        Assert.assertEquals(20, userSecondary.getAge().intValue());
    }

}

代碼示例

本文的相關例子可以查看下面倉庫中的chapter3-9目錄:

  • Github:https://github.com/dyc87112/SpringBoot-Learning/
  • Gitee:https://gitee.com/didispace/SpringBoot-Learning/

如果您覺得本文不錯,歡迎Star支持,您的關注是我堅持的動力!

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

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

電動車進駐大樓,ChargePoint 推出公寓大樓用電動車充電座

在美國,許多人都擁有寬敞的車庫,買了電動車就在車庫中設置充電座,然而若是市區中的大樓住戶,只能停在大樓地下室密密麻麻的停車格,買電動車可就麻煩了。電動車充電座製造商 ChargePoint 看見了這個問題,計劃推出公寓大樓用電動車充電座,解除大樓住戶購買電動車的障礙。    
  《富比世》報導,當特斯拉 Model S 電動車上市時,Gogoro 創辦人陸學森原本想要擁有一輛,但是第一個問題是在台灣沒有上市,就算進口一輛,台灣的住處大樓沒有獨立車庫,無法安裝幫 Model S 電動車充電的充電座,若非要開 Model S 電動車,只能在公司裝設充電座在公司充電,但這樣一來,週末就無法開出去兜風,豈不是大煞風景,最後陸學森在女友說服下,還是打退堂鼓。   這個困擾,其實也是各國所有大樓住戶的困擾,雖然以美國來說,如加州等地區路上設有充電站,不過電動車車主總是想要在家把電充飽飽才開出門,以免半路沒電,據美國能源部統計,80% 電動車都是在家充電,要是在家不能充電,購買電動車的意願就會降低,ChargePoint  執行長帕斯奎‧羅曼諾(Pasquale Romano)表示,除了少數例外,住大樓的人通常不買電動車,正是因為如此。   那要如何改善這個情況?羅曼諾認為,過去為了讓少數電動車主能在大樓停車場充電,大樓業主得全數自掏腰包在停車場設置充電座,投資風險很高,因此意願低落,但大樓業主如果並不用負擔充電座的設置費用,像大樓附設的投幣式自助洗衣機一樣,由業者來設置機器,這樣就成了。      
可吸引高收入使用者   2015 年 4 月,ChargePoint 宣布推出大樓專用的充電座系統,大樓業主不用負擔設置費用,這部分完全由 ChargePoint  吸收,大樓業主只需要為充電座連接電力即可,ChargePoint 會向用戶收取每月 39.99 美元的月費,電費部分則由住戶直接交給大樓業主,如果有電動車的住戶搬走了,ChargePoint 可以暫時關閉住戶所屬停車格的充電座,直到下一位有電動車的住戶入住才重新啟動,這樣一來,大樓業主的風險可說降到極低,勢必能提高安裝充電座的意願。   對大樓來說,提供停車場充電座設施,可吸引電動車車主,讓大樓更快租出,電動車車主又通常是高收入、高社經地位的良好住戶,對大樓有額外幫助;而對 ChargePoint 來說,能打進大樓這片處女地,是開拓新市場的絕佳機會,估計至 2020 年,美國將有 230 萬電動車主,其中有 10% 將會住在大樓內,這種合作方式對大樓與 ChargePoint 可說是雙贏局面。   想出免費贈送充電座商業模式的也不只 ChargePoint,曾經推出低價「開源碼」充電座的新創事業 EMotorWerks,2014 年推出特別活動,免費贈送原本售價 299 美元的 JuiceBox 充電座,條件是用戶要有可用的 Wi-Fi,讓充電座能將資訊傳給 EMotorWerks,以及用戶同意可由 EMotorWerks 來調整充電速度。    
 

    用戶只需要在行動裝置的專屬 App 上,告訴 EMotorWerks 何時要用車要充飽電力,EMotorWerks 會根據電力的離峰尖峰情況,自動調整充電速度,盡可能讓電力都在離峰時充電。在加州,尖峰電價可能高出平均電價 30 倍以上,避開尖峰時段充電可以為用戶節省大量電費;另一方面,也相當於為電網平衡離尖峰電力需求,如夜間風力發電過剩,可加速充電把多餘的電力用掉,尖峰時暫停充電,緩和尖峰負載。   EMotorWerks 未來的營收可望來自為用戶節省電費的服務、為電網調節平衡的服務,以及出售所收集的數據,為此,免費贈送充電座也划算。   EMotorWerks 的點子,也可能為 ChargePoint 採用,ChargePoint 充電座也可能成為大樓業主調節電力負載與電費支出的利器。無論如何,在充電座業者的推波助瀾下,電動車的充電障礙,將漸漸減輕。     本文全文授權轉載自《科技新報》─〈〉

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

一起玩轉微服務(14)——單元測試

作為一名java開發者,相信你或多或少的接觸過單元測試,對於測試來講它是一門能夠區分專業開發人員與業餘開發人員的重要學科,這篇文章將對java中最常見的一個單元測試框架junit進行一個梳理和講解。

為什麼需要單元測試

在平時的開發當中,一個項目往往包含了大量的方法,可能有成千上萬個。如何去保證這些方法產生的結果是我們想要的呢?當然了,最容易想到的一個方式,就是我們通過System.out來輸出我們的結果,看看是不是滿足我們的需求,但是項目中這些成千上萬個方法,我們總不能在每一個方法中都去輸出一遍嘛。這也太枯燥了。這時候用我們的單元測試框架junit就可以很好地解決這個問題。

junit如何解決這個問題的呢?答案在於內部提供了一個斷言機制,他能夠將我們預期的結果和實際的結果進行比對,判斷出是否滿足我們的期望。

預備工作

junit4是一個單元測試框架,既然是框架,這也就意味着jdk並沒有為我們提供api,因此在這裏我們就需要導入相關的依賴。

junit4是一個單元測試框架,既然是框架,這也就意味着jdk並沒有為我們提供api,因此在這裏我們就需要導入相關的依賴。

這裏的版本是4.12。當然還有最新的版本。你可以手動選擇。這裏選用的是4的版本。

案例

這裏我們要測試的功能超級簡單,就是加減乘除法的驗證。

然後我們看看如何使用junit去測試。

以上就是我們的單元測試,需要遵循一下規則:

  • •每一個測試方法上使用@Test進行修飾
  • •每一個測試方法必須使用public void 進行修飾
  • •每一個測試方法不能攜帶參數
  • •測試代碼和源代碼在兩個不同的項目路徑下
  • •測試類的包應該和被測試類保持一致
  • •測試單元中的每個方法必須可以獨立測試

以上的6條規則,是在使用單元測試的必須項,當然junit也建議我們在每一個測試方法名加上test前綴,表明這是一個測試方法。

assertEquals是一個斷言的規則,裏面有兩個參數,第一個參數表明我們預期的值,第二個參數表示實際運行的值。

我們運行一下測試類,就會運行每一個測試方法,我們也可以運行某一個,只需要在相應的測試方法上面右鍵運行即可。如果運行成功編輯器的控制台不會出現錯誤信息,如果有就會出現failure等信息。

運行流程

在上面的每一個測試方法中,代碼是相當簡單的,就一句話。現在我們分析一下這個測試的流程是什麼:

在上面的代碼中,我們使用了兩個測試方法,還有junit運行整個流程方法。我們可以運行一下,就會出現下面的運行結果:

從上面的結果我們來畫一張流程圖就知道了:

如果我們使用過SSM等其他的一些框架,經常會在before中添加打開數據庫等預處理的代碼,也會在after中添加關閉流等相關代碼。

註解

對於@Test,裏面有很多參數供我們去選擇。我們來認識一下

  • •@Test(expected=XX.class) 這個參數表示我們期望會出現什麼異常,比如說在除法中,我們1/0會出現ArithmeticException異常,那這裏@Test(expected=ArithmeticException.class)。在測試這個除法時候依然能夠通過。
  • •@Test(timeout=毫秒 ) 這個參數表示如果測試方法在指定的timeout內沒有完成,就會強制停止。
  • •@Ignore 這個註解其實基本上不用,他的意思是所修飾的測試方法會被測試運行器忽略。•@RunWith 更改測試運行器。

測試套件

如果我們的項目中如果有成千上萬個方法,那此時也要有成千上萬個測試方法嘛?如果這樣junit使用起來還不如System.out呢,現在我們認識一下測試嵌套的方法,他的作用是我們把測試類封裝起來,也就是把測試類嵌套起來,只需要運行測試套件,就能運行所有的測試類了。

下面我們使用測試套件,把這些測試類嵌套在一起。

 

 

 

參數化設置

什麼是參數化設置呢?在一開始的代碼中我們看到,測試加法的時候是1+1,不過我們如果要測試多組數據怎麼辦?總不能一個一個輸入,然後運行測試吧。這時候我們可以把我們需要測試的數據先配置好。

這時候再去測試,只需要去選擇相應的值即可,避免了我們一個一個手動輸入。

spring boot + junit

通過spring suite tools新建工程

 

 

1. Controller

@RestController
@RequestMapping
public class BookController {
    @RequestMapping("/books")
    public String book() {
        System.out.println("controller");
        return "book";
    }
}

Test1 引入Spring上下文,但不啟動tomcat

@RunWith(SpringRunner.class)
@SpringBootTest  //引入Spring上下文 -> 上下文中的 bean 可用,自動注入
public class BookControllerTest {
    
    @Autowired
    private BookController bookController;  //自動注入
    
    @Test
    public void testControllerExists() {
        Assert.assertNotNull(bookController);
    }
    
}

Test2 引入Spring上下文,且啟動Tomcat 模擬生產環境,接收Http請求

package com.cloud.skyme;

import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;

/** * @author zhangfeng * web單元測試 * */
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class Chapter0302junitApplicationTests {
	
	@LocalServerPort
    private int port;
	
	@Autowired
	private TestRestTemplate restTemplate;
    
    @Test
    public void testControllerExists() {
    	Assert.assertEquals(this.restTemplate.getForObject("http://localhost:" + port + "/books", String.class), "book");
    }

}

@RunWith(SpringRunner.class),讓測試運行於Spring測試環境,此註釋在org.springframework.test.annotation包中提供。
@SpringBootTest指定Sspring Bboot程序的測試引導入口。
TestRestTemplate是用於測試rest接口的模板類。
運行單元測試,測試上面邊構建的Wweb地址,可以看到輸出的測試結果與期望的結果相同.

運行單元測試,得到與期望相同的結果。

    
javascript    44行

13:31:03.722 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate] 13:31:03.739 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)] 13:31:03.801 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [com.cloud.skyme.Chapter0302junitApplicationTests] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper] 13:31:03.830 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [com.cloud.skyme.Chapter0302junitApplicationTests], using SpringBootContextLoader 13:31:03.837 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.cloud.skyme.Chapter0302junitApplicationTests]: class path resource [com/cloud/skyme/Chapter0302junitApplicationTests-context.xml] does not exist 13:31:03.838 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.cloud.skyme.Chapter0302junitApplicationTests]: class path resource [com/cloud/skyme/Chapter0302junitApplicationTestsContext.groovy] does not exist 13:31:03.838 [main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [com.cloud.skyme.Chapter0302junitApplicationTests]: no resource found for suffixes {-context.xml, Context.groovy}.
13:31:03.839 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [com.cloud.skyme.Chapter0302junitApplicationTests]: Chapter0302junitApplicationTests does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 13:31:03.918 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [com.cloud.skyme.Chapter0302junitApplicationTests] 13:31:04.070 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [C:\java\workspace\microservice\chapter0302junit\target\classes\com\cloud\skyme\Chapter0302junitApplication.class] 13:31:04.073 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration com.cloud.skyme.Chapter0302junitApplication for test class com.cloud.skyme.Chapter0302junitApplicationTests 13:31:04.225 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [com.cloud.skyme.Chapter0302junitApplicationTests]: using defaults. 13:31:04.226 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener] 13:31:04.243 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource] 13:31:04.244 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute] 13:31:04.244 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@7133da86, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@3232a28a, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@73e22a3d, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@47faa49c, org.springframework.test.context.support.DirtiesContextTestExecutionListener@28f2a10f, org.springframework.test.context.event.EventPublishingTestExecutionListener@f736069, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@6da21078, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@7fee8714, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@4229bb3f, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@56cdfb3b, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@2b91004a, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener@20ccf40b] 13:31:04.250 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@6cd28fa7 testClass = Chapter0302junitApplicationTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@614ca7df testClass = Chapter0302junitApplicationTests, locations = '{}', classes = '{class com.cloud.skyme.Chapter0302junitApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@3b07a0d6, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@14d3bc22, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@45b9a632, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5e316c74, org.springframework.boot.test.context.SpringBootTestArgs@1], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false]], class annotated with @DirtiesContext [false] with mode [null]. 13:31:04.267 [main] DEBUG org.springframework.test.context.support.DependencyInjectionTestExecutionListener - Performing dependency injection for test context [[DefaultTestContext@6cd28fa7 testClass = Chapter0302junitApplicationTests, testInstance = com.cloud.skyme.Chapter0302junitApplicationTests@31fa1761, testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@614ca7df testClass = Chapter0302junitApplicationTests, locations = '{}', classes = '{class com.cloud.skyme.Chapter0302junitApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@3b07a0d6, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@14d3bc22, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@45b9a632, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5e316c74, org.springframework.boot.test.context.SpringBootTestArgs@1], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false]]].
13:31:04.306 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.1.RELEASE) 2020-06-28 13:31:04.940 INFO 8376 --- [ main] c.c.s.Chapter0302junitApplicationTests : Starting Chapter0302junitApplicationTests on WIN-55FHBQI56BD with PID 8376 (started by Administrator in C:\java\workspace\microservice\chapter0302junit) 2020-06-28 13:31:04.942 INFO 8376 --- [ main] c.c.s.Chapter0302junitApplicationTests : No active profile set, falling back to default profiles: default 2020-06-28 13:31:09.134 INFO 8376 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 0 (http) 2020-06-28 13:31:09.160 INFO 8376 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2020-06-28 13:31:09.161 INFO 8376 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.36] 2020-06-28 13:31:09.372 INFO 8376 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2020-06-28 13:31:09.372 INFO 8376 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 4316 ms 2020-06-28 13:31:10.029 INFO 8376 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-06-28 13:31:10.655 INFO 8376 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 59724 (http) with context path '' 2020-06-28 13:31:10.673 INFO 8376 --- [ main] c.c.s.Chapter0302junitApplicationTests : Started Chapter0302junitApplicationTests in 6.362 seconds (JVM running for 8.218) 2020-06-28 13:31:11.423 INFO 8376 --- [o-auto-1-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2020-06-28 13:31:11.423 INFO 8376 --- [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2020-06-28 13:31:11.461 INFO 8376 --- [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 37 ms controller 2020-06-28 13:31:13.497 INFO 8376 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'

 

 這樣,一個web應用從構建到單元測試就都已經完成了,可見,構建一個Spring Web MVC的應用就是如此簡單。

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

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

報名即將截止——第五屆中國國際新能源汽車論壇2015餘票有限

2015上海車展已圓滿落下帷幕。本屆上海車展吸引了18個國家和地區2000家中外汽車展商參展,新能源汽車無疑是此次車展最大的亮點之一。本次車展共展出新能源車103輛,其中51輛國內自主車型,52輛合資或進口車型。新能源汽車將成車市主流,也將成車市中有力的競爭者。在剛剛結束的2015上海車展上,幾乎國內的每個車企都有新能源汽車展出,比亞迪更是以“清一色”的新能源汽車參展,由此可見,新能源汽車的重要性。現階段,基礎設施和電池續航里程是影響其發展的重要因素,如何破解這些難題是中國政府和車企急需考慮的問題。

在新能源汽車發展的大形勢下,距離第五屆中國國際新能源汽車論壇2015舉辦還有一周,中國國際新能源汽車論壇組委會邀請到了100+企業, 200位左右行業高層領導,其中包括世界知名混合動力汽車生產廠商、純電動汽車生產廠商、純電動高檔跑車生產廠商、零部件一百強企業、鋰電池供應商、變速器供應商、生產設備供應商、充電樁服務商、運營商等。共同商討新能源汽車行業發展新變化、新趨勢、新契機。包括以下議題:

  • 新能源汽車產業發展規劃和節能減排計畫
  • 政府激勵政策和補貼
  • 新能源汽車市場資料分析及市場展望
  • 如何讓電動汽車更容易被消費者接受
  • 高性能電動車-清潔交通的革新
  • 新能源汽車的節能減排技術
  • 打造安全高性能的新能源汽車電子控制器
  • 未來制動系統的核心: 結合最新技術的基礎制動架構
  • 新能源汽車零部件開發測試
  • 力帆新能源汽車產業模式與創新技術
  • 圓桌論壇:零部件的技術創新與整合廠商設計融入
  • 充換電標準的發展與統一
  • 飛兆車載充電器及DC-DC轉換器解決方案
  • 全球充電基礎設施與行業標杆
  • 樂視生態與智慧互聯汽車的未來
  • 電動汽車動力和能源管理研究進展
  • 動力汽車在電動車及動力電池發展的前景探討
  • 新能源客車機動力電池發展的前景探討
  • 純電動客車運營策略分析
  • 車網互聯打造智能新能源汽車
  • 2015年中國車用動力電池產業經濟運行情況及展望
  • 圓桌討論:充電設施的落地途徑及商業模式
  • 整車廠商-零部件企業對接洽談會

欲瞭解詳情,請登錄論壇唯一官方網址,或聯繫Hill ZENG(曾先生) 電話:+86 21-6045 1760諮詢。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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

易到用車APP上線數千輛新能源車 最低5元人民幣即可搭乘

日前,易到用車啟動了「E-Car計畫」,將陸續在北京、上海、廣州、深圳上線數千輛新能源車型,打造新能源出行平台;與此同時易到用車還宣佈將與普天新能源、龐大集團、騰勢等品牌展開深度合作,共同打造新能源出行聯盟,共建新能源城市。   屆時,易到用車App將上線開通「新能源」車型選項。此次加入易到「E-Car計畫」的車型包括混合動力的雙擎普銳斯、沃爾沃S60L、北汽EV系列以及特斯拉,用戶可通過易到用車App,在「新能源」車型中按需選擇,價格最低5元人民幣(下同)起步,0元/分鐘,0.99元/公里。   易到方面介紹,作為聯盟計畫的一部分,易到用車將與普天合作,在未來共同建設1000個充電樁設施,也同時尋找更多合作夥伴,提供場地共同建樁,而且充電樁建好後,將面向社會全面開放使用。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

新北清潔公司,居家、辦公、裝潢細清專業服務

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