環境資訊中心綜合外電;姜唯 編譯;林大利 審校
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線
※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益
※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象
※台灣寄大陸海運貨物規則及重量限制?
※大陸寄台灣海運費用試算一覽表
北部有線電視-提供穩定的寬頻光纖上網、高畫質HD數位頻道、第四台電視、數位電視,現在申辦免費體驗3個月"HD99高畫質套餐"
摘錄自2018年10月4日中央社報導
路透社報導,緬甸當局4日銷毀查獲的數以百計象牙、穿山甲鱗片和其他動物部位,總重量超過1.4公噸,黑市價格達到130萬美元(約新台幣4000萬元),作為政府打擊非法走私野生生物的一環。
緬甸位於全球非法野生生物交易的心臟地帶,大部分走私品銷往中國。緬甸、寮國和泰國的交界地區,就是惡名昭彰的「金三角」(Golden Triangle)。
保育團體「拯救大象」(Save the Elephants)本週提出的報告指出,中國近來推出的象牙交易禁令,幾乎無法阻止緬甸與中國邊界城鎮勐拉(Mong La)的交易「大量成長」。過去3年來,勐拉鎮出售新的象牙產品增加60%。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!
※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!
※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!
※大陸寄台灣空運注意事項
※大陸海運台灣交貨時間多久?
※避免吃悶虧無故遭抬價!台中搬家公司免費估價,有契約讓您安心有保障!
摘錄自2018年10月3日科技新報報導
近日,潮汐能公司 SIMEC Atlantis Energy(SAE) 打造出世界最大、裝置量高達 2MW 的單轉子潮汐能設備 AR2000,該系統使用壽命長達 25 年,每六年進行一次檢查即可。該設備也採用濕式配對(wet-mate)系統,可快速且安全地裝設在重力結構或獨立基座上,一天最多可部署 8 座潮汐能渦輪機,開發商也可將多個渦輪機串起連接,進一步降低海底作業的成本與生態影響。
SAE 的 AR1500 潮汐能設備先前也在英國大放異彩,其中蘇格蘭全球最大的潮汐能發電計畫「MeyGen」便是出自 SAE 之手,目前 AR1500 已於 2017 年第三季末開始運行,未來 AR2000 也會在 MeyGen 發電廠服役。計畫總監 David Taaffe 更預計 2018 年該潮汐發電廠將可生產約 1.9GWh 電力。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※專營大陸空運台灣貨物推薦
※台灣空運大陸一條龍服務
Python多線程與Queue隊列多線程在感官上類似於同時執行多個程序,雖然由於GIL的存在,在Python中無法實現線程的真正并行,但是對於某些場景,多線程仍不失為一個有效的處理方法:
1,不緊急的,無需阻塞主線程的任務,此時可以利用多線程在後台慢慢處理;
2,IO密集型操作,比如文件讀寫、用戶輸入和網絡請求等,此時多線程可以近似達到甚至優於多進程的表現;
多線程的基本使用不再贅述,以下語法便可輕鬆實現:
1 def task(args1, args2): 2 pass 3 4 Thread( 5 target=task, 6 args=(args1, args2) 7 ).start()
這裏我們重點關注線程通信。
假設有這麼一種場景:有一批源數據,指定一個操作係數N,需要分別對其進行與N的加減乘除操作,並將結果匯總。
當然這裏的加減乘除只是一種簡單處理,在實際的生產環境中,它其實代表了一步較為複雜的業務操作,並包含了較多的IO處理。
自然我們想到可以開啟多線程處理,那麼緊接着的問題便是:如何劃分線程,是根據處理步驟劃分,還是根據源數據劃分?
對於前者,我們把涉及的業務操作單獨劃分位一個線程,即有4個線程分別進行加減乘除的操作,顯然上一個線程的結果是下一個線程的輸入,這類似於流水線操作;
而後者則是把源數據分為若干份,每份啟動一個線程進行處理,最終把結果匯總。一般來說,我們推薦第一種方式。因為在一個線程中完成所有的操作不如每步一個線程清晰明了,
尤其是在一些複雜的場景下,會加大單個線程的出錯概率和測試難度。
那麼我們將開闢4個線程,分別執行加減乘除操作。最後一個除法線程結束則任務完成:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 from Queue import Queue 5 from threading import Thread 6 7 8 class NumberHandler(object): 9 def __init__(self, n): 10 self.n = n 11 12 def add(self, num): 13 return num + self.n 14 15 def subtract(self, num): 16 return num - self.n 17 18 def multiply(self, num): 19 return num * self.n * self.n 20 21 def divide(self, num): 22 return num / self.n 23 24 25 class ClosableQueue(Queue): 26 SENTINEL = object() 27 28 def close(self): 29 self.put(self.SENTINEL) 30 31 def __iter__(self): 32 while True: 33 item = self.get() 34 try: 35 if item is self.SENTINEL: 36 return 37 yield item 38 finally: 39 self.task_done() 40 41 42 class StoppableWorker(Thread): 43 def __init__(self, func, in_queue, out_queue): 44 super(StoppableWorker, self).__init__() 45 self.in_queue = in_queue 46 self.out_queue = out_queue 47 self.func = func 48 49 def run(self): 50 for item in self.in_queue: 51 result = self.func(item) 52 self.out_queue.put(result) 53 print self.func 54 55 56 if __name__ == '__main__': 57 source_queue = ClosableQueue() 58 add_queue = ClosableQueue() 59 subtract_queue = ClosableQueue() 60 multiply_queue = ClosableQueue() 61 divide_queue = ClosableQueue() 62 result_queue = ClosableQueue() 63 64 number_handler = NumberHandler(5) 65 66 threads = [ 67 StoppableWorker(number_handler.add, add_queue, subtract_queue), 68 StoppableWorker(number_handler.subtract, subtract_queue, multiply_queue), 69 StoppableWorker(number_handler.multiply, multiply_queue, divide_queue), 70 StoppableWorker(number_handler.divide, divide_queue, result_queue), 71 ] 72 73 for _thread in threads: 74 _thread.start() 75 76 for i in range(10): 77 add_queue.put(i) 78 79 add_queue.close() 80 add_queue.join() 81 print 'add job done...' 82 subtract_queue.close() 83 subtract_queue.join() 84 print 'subtract job done...' 85 multiply_queue.close() 86 multiply_queue.join() 87 print 'multiply job done...' 88 divide_queue.close() 89 divide_queue.join() 90 print 'divide job done...' 91 result_queue.close() 92 93 print "%s items finished, result: %s" % (result_queue.qsize(), result_queue) 94 95 for i in result_queue: 96 print i
運行結果:
線程執行日誌:
總的結果:
可見線程交叉運行,但是任務卻是順序結束,這符合我們的預期。
值得注意的是,我們在ClosableQueue定義了一個close()方法,通過放入一個特殊的類變量SENTINEL告訴隊列應該關閉。此外,由於直接加減乘除結果不變,因此我特意乘了兩次來便於我們判斷結果。
總結:
1. Queue是一種高效的任務處理方式,它可以把任務處理流程劃分為若干階段,並使用多條python線程來同時執行這些子任務;
2. Queue類具備阻塞式的隊列操作、能夠指定緩衝區尺寸,而且還支 持join方法,這使得開發者可以構建出健壯的流水線。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※帶您來了解什麼是 USB CONNECTOR ?
※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象
※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!
※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化
※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益
※試算大陸海運運費!
兩種運動檢測算法的介紹:
幀差法:
幀差法是目前運動目標檢測中最常用的算法。幀差法依據的原則是:當視頻中存在移動物體的時候,相鄰幀(或相鄰三幀)之間在灰度上會有差別,求取兩幀圖像灰度差的絕對值,則靜止的物體在差值圖像上表現出來全是0,而移動物體特別是移動物體的輪廓處由於存在灰度變化為非0,當絕對值超過一定閾值時,即可判斷為運動目標,從而實現目標的檢測功能。
二維頻域運動目標檢測:
通過對動態圖像的行列分解, 將三維頻域內的運動檢測問題轉化到兩組二維頻域內進行, 從而降低了濾波器設計的難度。給出了一種提取主運動能量的自適應濾波算法, 通過剔除背景和噪聲的頻率成分, 有效地檢測出運動目標。
複雜度分析:
針對幀差法進行分析,代碼複雜度主要集中在absdiff與findContours部分,其中absdiff的迭代次數為2*500*500=50000次,時間為88.46ms(取兩百幀計算平均的時間)
針對二維頻域運動目標檢測算法,這裡有兩個代碼版本:
針對py-new-fuliye.py,代碼的複雜度主要集中在兩個部分:傅里恭弘=叶 恭弘變換以及遍歷,在py-new-fuliye.py中,共使用了兩次傅里恭弘=叶 恭弘變換與兩次遍歷,遍歷的迭代次數次數為2*50*30=300次,時間為:54.175ms
針對pepoplefft.py(改進版)進行分析,使用了兩次傅里恭弘=叶 恭弘變換(一次正一次逆),進行了一次嵌套遍歷,遍歷次數為:50*10=500次,時間為: ms
針對pepoplefft.py進行優化調參:
搜尋噪點:
要找到噪點,就要知道經傅里恭弘=叶 恭弘高通濾波變換后,剩餘的邊緣部分在數組中的表現規律,採用numpy繪圖表示出來:
經過閾值去噪后,效果如圖:
在隨後的視頻測試中發現其面對複雜環境表現仍不理想,此時考慮選擇繪製多個矩形來框選標記多個候選目標,暫時不考慮使用其他的濾波進行去噪,原因為1、會佔用原本就不多的處理時間,2、不認為在經過高通濾波后還未被濾掉的噪點會被其他濾波函數濾掉,目標被濾掉的可能性反而更大。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!
※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光
※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!
※專營大陸快遞台灣服務
※台灣快遞大陸的貨運公司有哪些呢?
以前寫過一篇《》的文章,文章的地址是:https://www.cnblogs.com/tosser/p/9022187.html,我當時使用 OCX 來實現,可是 OCX 只支持 IE 瀏覽器,後來在往上找了一個 Chrome 的擴展,也解決了該問題。不過,總覺得無論使用 OCX 還是使用 Chrome 的擴展,都是瀏覽器相關的,並不通用。後來,使用 Socket 寫了一個簡單的 DEMO,用來模擬 HTTP 服務器,然後使用 Ajax 進行通信,問題解決了。也不再是瀏覽器相關了。
Web 頁面獲取 MAC 地址的設計思路
Web 頁面獲取 MAC 地址的設計思路是比較簡單的,只需要在本地模擬一個 HTTP 服務器,然後讓 Web 頁面通過 Ajax 來請求 HTTP 服務器,HTTP 服務器直接返回本機的 MAC 地址就可以了。
具體流程如下圖:
流程圖非常的清楚,主要就是 HostServer 和 Ajax 的通信,這樣就可以得到 MAC 地址,然後通過 DOM 操作,即可把 MAC 地址寫入到 input 框中。這樣,就可以和用戶名、密碼一起提交給服務器進行驗證了。
除了獲取 MAC 地址還能幹啥
之前做過一個物流提貨的項目,涉及到一些硬件設備,包括:小票打印機、刷卡器(身份證、銀聯卡)、進幣器、密碼数字鍵盤等。這些設備、電腦主機和显示器在一個類似 ATM 機那樣的機櫃中(其實就是 ATM 機的設備,本身這套東西就是銀行提供的)。
操作這些硬件的接口廠家提供了一個 OCX,而整個項目是 B/S 架構的。那麼,在客戶端想要操作這些硬件,就要調用 OCX,而 OCX 只能在 IE 瀏覽器下使用(Chrome、FireFox 是不支持 OCX 的)。眾所周知,IE 對 Web 並不友好,但是如何又能在不使用 IE 的情況下,又去調用 OCX 來完成操作硬件的功能呢?那麼就是我們上面的方法了。
簡單的描述一下,就不貼圖了。
在終端上放一個 HostServer 用來接受頁面中 Ajax 的請求,並根據請求去調用 OCX 中相應的功能,把 OCX 的返回信息,再以 Json 的格式返回給 Ajax 即可。
這樣,把 瀏覽器 和 OCX 文件進行了分離,中間加入了一個 HostServer,頁面 和 OCX 的通信通過了 HostServer,那麼以後如果接口是 DLL 文件,也可以通過 HostServer 來進行完成,當然,還可以完成更多的功能。
總結
其實整個獲取 MAC 地址的功能,對於登錄頁面而言是一個服務端,它在本地是一個可執行的程序,那麼它和普通的 EXE 文件是沒有區別的,那麼它能完成的功能其實遠遠不是獲取一個 MAC 地址的功能,對於上面的例子來說,把服務的提供者和使用者進行了分離,而且針對於本機的擴展也十分的方便了。當然,如果你願意的話,可以讓 HostServer 充當客戶端直接和後端的服務器進行通信而不通過瀏覽器,這樣是不是還能做一些讓用戶沒有感知的事情?
我的微信公眾號:“碼農UP2U”
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※台灣海運大陸貨務運送流程
※兩岸物流進出口一站式服務
接着上一篇文章中的代碼,修改下service中的代碼,這次我不通過構造器注入Dao,在方法中new一個StudentDao,創建一個名為StudentNewService的類。
具體示例代碼如下:
package com.rongrong.powermock.service; import com.rongrong.powermock.dao.StudentDao; /** * @author rongrong * @version 1.0 * @date 2019/11/17 21:13 */ public class StudentNewService { /** * 獲取學生個數 * @return返回學生總數 */ public int getTotal() { StudentDao studentDao = new StudentDao(); return studentDao.getTotal(); } /** * 創建學生 * @param student */ public void createStudent(Student student) { StudentDao studentDao = new StudentDao(); studentDao.createStudent(student); } }
針對上面修改部分代碼,進行單元測試,以下代碼有採用傳統方式測試和採用powermock方式進行測試,具體代碼如下:
package com.rongrong.powermock.service; import com.rongrong.powermock.dao.StudentDao; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; /** * @author rongrong * @version 1.0 * @date 2019/11/20 21:42 */ @RunWith(PowerMockRunner.class) @PrepareForTest(StudentNewService.class) public class TestNewStudentService { /** * 傳統方式測試 */ @Test public void testGetStudentTotal() { StudentNewService studentNewService = new StudentNewService(); int total = studentNewService.getTotal(); assertEquals(total, 10); } /** * @desc測試有返回值類型 採用powermock進行測試獲取學生個數 */ @Test public void testGetStudentTotalWithPowerMock() { //先模擬一個假對象即studentdao方法中的局部變量 StudentDao studentDao = PowerMockito.mock(StudentDao.class); try { //這句話我按照英文理解就是,我用無參的方式new了一個StudentDao對象 PowerMockito.whenNew(StudentDao.class).withNoArguments().thenReturn(studentDao); //再模擬這個對象被調用時,我們默認假定返回10個證明調用成功 PowerMockito.when(studentDao.getTotal()).thenReturn(10); //這裏就是service就不用再說了 StudentNewService studentNewService = new StudentNewService(); int total = studentNewService.getTotal(); assertEquals(total, 10); } catch (Exception e) { fail("測試失敗了!!!"); e.printStackTrace(); } } /** * @desc測試的無返回值類型 採用powermock進行測試創建學生 */ @Test public void testCreateStudentWithPowerMock() { //先模擬一個假對象即studentdao方法中的局部變量 StudentDao studentDao = PowerMockito.mock(StudentDao.class); try { //這句話我按照英文理解就是,我用無參的方式new了一個StudentDao對象 PowerMockito.whenNew(StudentDao.class).withNoArguments().thenReturn(studentDao); Student student = new Student(); //這句話註釋與否都能運行通過,也就是我只能判斷他是否被調用 //PowerMockito.doNothing().when(studentDao).createStudent(student); //這裏就是service就不用再說了 StudentNewService studentNewService = new StudentNewService(); studentNewService.createStudent(student); Mockito.verify(studentDao).createStudent(student); } catch (Exception e) { fail("測試失敗了!!!"); e.printStackTrace(); } } }
運行上面的測試用例,會發現第一個失敗,後面兩個都運行成功,即有返回值和無返回值類型的測試(void類型)。
注意:對於無返回值類型的測試,只能驗證其是否被調用,這裏還請注意。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包”嚨底家”
※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線
※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整
※小三通海運與一般國際貿易有何不同?
※小三通快遞通關作業有哪些?
是 java 實現的 property 框架。
優雅地進行屬性文件的讀取和更新
寫入屬性文件后屬性不亂序
靈活定義編碼信息
使用 OO 的方式操作 property 文件
支持多級對象引用
Maven 3.x
Jdk 1.7+
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>property</artifactId>
<version>0.0.4</version>
</dependency>
PropertyBs.getInstance("read.properties").get("hello");
read.properties 為文件路徑,hello 為存在的屬性值名稱。
final String value = PropertyBs.getInstance("read.properties")
.getOrDefault("hello2", "default");
read.properties 為文件路徑,hello2 為不存在的屬性值名稱,default 為屬性不存在時返回的默認值。
PropertyBs.getInstance("writeAndFlush.properties").setAndFlush("hello", "world-set");
writeAndFlush.properties 為文件路徑,hello 為需要設置的屬性信息。
| 序號 | 方法 | 說明 |
|---|---|---|
| 1 | getInstance(propertyPath) | 獲取指定屬性文件路徑的引導類實例 |
| 2 | charset(charset) | 指定文件編碼,默認為 UTF-8 |
| 3 | get(key) | 獲取 key 對應的屬性值 |
| 4 | getOrDefault(key, defaultValue) | 獲取 key 對應的屬性值,不存在則返回 defaultValue |
| 5 | set(key, value) | 設置值(內存) |
| 6 | remove(key) | 移除值(內存) |
| 7 | flush() | 刷新內存變更到當前文件磁盤 |
| 9 | flush(path) | 刷新內存變更到指定文件磁盤 |
| 10 | set(map) | 設置 map 信息到內存 |
| 11 | set(bean) | 設置 bean 對象信息到內存 |
| 12 | asMap() | 返回內存中屬性信息,作為 Map 返回 |
| 13 | asBean(bean) | 返回內存中屬性信息到 bean 對象中 |
我們希望操作 property 可以想操作對象一樣符合 OO 的思想。
User user = new User();
user.setName("hello");
user.setHobby("hobby");
final long time = 1574147668411L;
user.setBirthday(new Date(time));
PropertyBs propertyBs = PropertyBs.getInstance("setBean.properties")
.set(user);
Assert.assertEquals("hobby", propertyBs.get("myHobby"));
Assert.assertEquals("1574147668411", propertyBs.get("birthday"));
PropertyBs propertyBs = PropertyBs.getInstance("setBean.properties"
.set("myHobby", "play")
.set("birthday", "1574147668411");
User user = new User();
propertyBs.asBean(user);
Assert.assertEquals("play", user.getHobby());
Assert.assertEquals(1574147668411L, user.getBirthday().getTime());
public class User {
private String name;
@PropertyField("myHobby")
private String hobby;
@PropertyField(converter = DateValueConverter.class)
private Date birthday;
}
| 序號 | 屬性 | 默認值 | 說明 |
|---|---|---|---|
| 1 | value | 當前字段名稱 | 對應的 property 屬性名稱 |
| 2 | converter | 默認轉換實現 DefaultValueConverter |
對當前字段進行屬性的轉換處理 |
這個就是我們針對 Date 類型,自己實現的處理類型。
實現如下:
public class DateValueConverter implements IValueConverter {
@Override
public Object fieldValue(String value, IFieldValueContext context) {
return new Date(Long.parseLong(value));
}
@Override
public String propertyValue(Object value, IPropertyValueContext context) {
Date date = (Date)value;
return date.getTime()+"";
}
}
有時候一個屬性可能是集合或者數組,這裏暫時給出比較簡單的實現。
將字段值直接根據逗號分隔,作為屬性值。
UserArrayCollection userArrayCollection = buildUser();
PropertyBs propertyBs = PropertyBs.getInstance("setBeanArrayCollection.properties")
.set(userArrayCollection);
Assert.assertEquals("array,collection", propertyBs.get("alias"));
Assert.assertEquals("array,collection", propertyBs.get("hobbies"));
public class UserArrayCollection {
private List<String> alias;
private String[] hobbies;
}
暫時只支持 String 類型,不想做的過於複雜。
後期將考慮添加各種類型的支持。
有時候我們在一個對象中會引用其他對象,比如 對象 a 中包含對象 b。
這裏採用 a.b.c 這種方式作為屬性的 key, 更加符合使用的習慣。
Book book = new Book();
book.name("《海底兩萬里》").price("12.34");
UserEntry user = new UserEntry();
user.name("海倫").book(book).age("10");
PropertyBs propertyBs = PropertyBs.getInstance("setBeanEntry.properties")
.set(user);
Assert.assertEquals("海倫", propertyBs.get("name"));
Assert.assertEquals("10", propertyBs.get("age"));
Assert.assertEquals("《海底兩萬里》", propertyBs.get("book.name"));
Assert.assertEquals("12.34", propertyBs.get("book.price"));
Map<String, String> map = new HashMap<>();
map.put("name", "海倫");
map.put("age", "10");
map.put("book.name", "《海底兩萬里》");
map.put("book.price", "12.34");
UserEntry userEntry = new UserEntry();
PropertyBs.getInstance("setBeanEntry.properties")
.set(map)
.asBean(userEntry);
Assert.assertEquals("UserEntry{name='海倫', age=10, book=Book{name='《海底兩萬里》', price=12.34}}",
userEntry.toString());
public class UserEntry {
private String name;
private String age;
@PropertyEntry
private Book book;
}
public class Book {
private String name;
private String price;
}
@PropertyEntry 註解用來標識一個字段是否採用多級對象的方式表示。
這個註解只有一個屬性,就是 value(),可以用來給當前字段指定一個別稱,和 @PropertyField 別稱類似。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※帶您來了解什麼是 USB CONNECTOR ?
※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象
※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!
※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化
※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益
※試算大陸海運運費!
邏輯備份用於備份數據庫的結構(CREAET DATABASE、CREATE TABLE)和數據(INSERT),這種備份類型適合數據量小、跨SQL服務器、需要修改數據等場景。如mysqldump命令就是產生一個邏輯備份工具,使用mysqldump輸出的文件包含CREATE TABLE和INSERT語句,能夠直接重建表內容和表結構。
使用邏輯備份有以下優勢和劣勢:
- 可移植性高,SQL語句可直接適用於其他SQL服務器;
- 在數據恢復之前可增加、修改數據;
- 數據恢復粒度小可以是服務器、數據庫、表級別;
- 使用文本格式,可讀性高;
- 備份時需要訪問mysql服務器,影響其他客戶端;
- 需要將數據轉換成邏輯格式(SQL,CSV);
- 如果命令運行在客戶端,mysql服務器還需要將數據發送給客戶端;
- 因為輸出格式為文本文件,佔用空間較大;
物理備份是包括存儲數據庫內容的目錄和文件的副本,這種類型的備份適用於需要在出現問題時快速恢復的大型重要數據庫。
- 完整的Mysql文件和目錄備份,只需要複製文件不需要轉換,速度比邏輯備份更快;
- 除了備份數據,還能備份配置文件和日誌文件;
- 不需要運行Mysql服務器就可以完成備份;
- 備份工具簡單使用cp、scp、tar命令即可完成備份;
- 可移植性不高,恢複數據只適用於相同或類似的機器上;
- 為了保持數據庫文件的一致性,需要停機備份;
- 恢復粒度不能按表或用戶恢復;
在線備份需要mysql服務器處理運行狀態,以便備份工具從mysql服務器中獲取數據。離線備份表示mysql服務器處理停止狀態。兩種備份形式也可以稱為“熱備份”和“冷備份“。
- 備份不需要停機,對其他客戶端影響較小其他連接能夠正常訪問mysql服務器(依賴操作類型,如讀操作);
- 備份需要加鎖,以免在備份期間對數據做出修改;
- 備份期間服務器不可用;
- 備份過程更簡單,不會受到客戶端的干擾;
mysqldump屬於邏輯備份命令,使用mysqldump備份的優勢是它非常方便和靈活,可以直接編輯輸出文件或者使用導入到其他的SQL服務器中去,但是它不能用作備份大量數據的快速解決方案,對於大數據量,即使備份花費的時候可以接受,但是恢複數據也可能會非常緩慢,因為執執行SQL語句會涉及磁盤I/O進行插入,創建索引等。mysqldump的使用方式非常簡單:
shell> mysqldump [options] db_name [tbl_name ...]
shell> mysqldump [options] --databases db_name ...
shell> mysqldump [options] --all-databases
使用mysqldump備份時要注意:數據庫的一致狀態,在執行mysqldump命令時要保證數據不會再發生變更,保持數據的一致性有二種方法:
REPEATABLE READ使用REPEATABLE READ事務隔離級別執行mysqldump命令(使用事務保持數據庫的一致狀態):
mysqldump --master-data=2 \
--flush-logs \
--single-transaction \
--all-databases > /backup/`date +%F-%H`-mysql-all.sql
備份參數說明:
- –master-data: 將二進制日誌文件的名稱和位置備份
- –flush-logs: 開始備份之前刷新mysql服務器日誌文件
- –single-transaction:開始備份之前設置事務隔離級別為REPEATABLE READ然後發送一個START TRANSACTION命令。
- –all-databases:備份所有數據庫
為了保證複製文件的完整性,備份原始文件最好是停止mysql服務器,複製原始文件備份由以下步驟完成:
- 停止mysql服務器
$ mysqladmin shutdown- 使用合適的工具複製原始數據文件
$ tar cf /tmp/dbbackup.tar ./data- 備份完成后,運行mysql服務器
$ mysqld_safe
使用mysqldump和tar備份或多或少都會對業務產生影響,使用mysqldump備份需要對數據加鎖,加鎖就意味着其他客戶端操作受到限制。使用tar命令需要停止服務器直接導致數據庫服務器不可用,有沒有辦法能解決這兩種問題呢?答案是有的,就是使用主從備份模式。
在單機的基礎上增加一台Slave機器對Master機器的數據進行同步:
開始備份時對Slave進行備份,這樣即使Slave停機或對數據加鎖也不會影響業務的正常使用,如果公司有條件或業務非常重要可以選擇這種方案來備份數據。
歡迎關注微信公眾號《架構文摘》,高質量技術文章第一時間推送。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※為什麼 USB CONNECTOR 是電子產業重要的元件?
※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!
※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光
※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!
※專營大陸快遞台灣服務
※台灣快遞大陸的貨運公司有哪些呢?
最近對我們的服務進行了改造,原本內部服務在內部可以匿名調用,現在增加了限制,通過 identity server 來管理 api 和 client,網關和需要訪問api的客戶端或api服務相互調用通過 client_credencial 的方式來調用,這樣一來我們可以清晰知道哪些 api 服務會被哪些 api/client 所調用,而且安全性來說更好。
為了保持後端服務的代碼更好的兼容性,希望能夠實現相同的代碼通過在 Startup 里不同的配置實現不同的 Authorization 邏輯,原來我們的服務的 Authorize 都是以 Authorize("policyName") 的形式來寫的,這樣一來我們只需要修改這個 Policy 的授權配置就可以了。對於 AllowAnonymous 就希望可以通過一種類似的方式來實現,通過自定義一個 Policy 來實現自己的邏輯
將 action 上的 AllowAnonymous 替換為 Authorize("policyName"),在沒有設置 Authorize 的 controller 上增加 Authorize("policyName")
public class AllowAnonymousPolicyTransformer : IApplicationModelConvention
{
private readonly string _policyName;
public AllowAnonymousPolicyTransformer() : this("anonymous")
{
}
public AllowAnonymousPolicyTransformer(string policyName) => _policyName = policyName;
public void Apply(ApplicationModel application)
{
foreach (var controllerModel in application.Controllers)
{
if (controllerModel.Filters.Any(_ => _.GetType() == typeof(AuthorizeFilter)))
{
foreach (var actionModel in controllerModel.Actions)
{
if (actionModel.Filters.Any(_ => _.GetType() == typeof(AllowAnonymousFilter)))
{
var allowAnonymousFilter = actionModel.Filters.First(_ => _.GetType() == typeof(AllowAnonymousFilter));
actionModel.Filters.Remove(allowAnonymousFilter);
actionModel.Filters.Add(new AuthorizeFilter(_policyName));
}
}
}
else
{
if (controllerModel.Filters.Any(_ => _.GetType() == typeof(AllowAnonymousFilter)))
{
var allowAnonymousFilter = controllerModel.Filters.First(_ => _.GetType() == typeof(AllowAnonymousFilter));
controllerModel.Filters.Remove(allowAnonymousFilter);
}
controllerModel.Filters.Add(new AuthorizeFilter(_policyName));
}
}
}
}
public static class MvcBuilderExtensions
{
public static IMvcBuilder AddAnonymousPolicyTransformer(this IMvcBuilder builder)
{
builder.Services.Configure<MvcOptions>(options =>
{
options.Conventions.Insert(0, new AllowAnonymousPolicyTransformer());
});
return builder;
}
public static IMvcBuilder AddAnonymousPolicyTransformer(this IMvcBuilder builder, string policyName)
{
builder.Services.Configure<MvcOptions>(options =>
{
options.Conventions.Insert(0, new AllowAnonymousPolicyTransformer(policyName));
});
return builder;
}
}
controller 中的代碼:
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly ILogger _logger;
public ValuesController(ILogger<ValuesController> logger)
{
_logger = logger;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
var msg = $"IsAuthenticated: {User.Identity.IsAuthenticated} ,UserName: {User.Identity.Name}";
_logger.LogInformation(msg);
return new string[] { msg };
}
// GET api/values/5
[Authorize]
[HttpGet("{id:int}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// ...
}
Startup 中 ConfigureServices 配置:
var anonymousPolicyName = "anonymous";
services.AddAuthorization(options =>
{
options.AddPolicy(anonymousPolicyName, builder => builder.RequireAssertion(context => context.User.Identity.IsAuthenticated));
options.DefaultPolicy = new AuthorizationPolicyBuilder(HeaderAuthenticationDefaults.AuthenticationSchema)
.RequireAuthenticatedUser()
.RequireAssertion(context => context.User.GetUserId<int>() > 0)
.Build();
});
services.AddMvc(options =>
{
options.Conventions.Add(new ApiControllerVersionConvention());
})
.AddAnonymousPolicyTransformer(anonymousPolicyName)
;
訪問原來的匿名接口
userId 為0訪問原來的匿名接口
userId 大於0訪問原來的匿名接口
userId 為0訪問需要登錄的接口
userId 大於0訪問需要登錄的接口
注:按照上面的做法已經可以做到自定義 policy 代替 AllowAnonymous 的行為,但是原來返回的401,現在可能返回到就是 403 了
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※台灣海運大陸貨務運送流程
※兩岸物流進出口一站式服務