python基本操作-文件、目錄及路徑_包裝設計

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

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

目錄

  • 1 前言
  • 2 文件夾操作
    • 2.1 查詢操作
    • 2.2 創建操作
    • 2.3 刪除操作
    • 2.4 修改操作
  • 3 文件操作
    • 3.1 查詢操作
    • 3.2 創建操作
    • 3.3 修改操作
    • 3.4 刪除
  • 4 路徑操作
  • 5 示例應用
    • 5.1 批量修改文件名
    • 5.2 遍歷目錄及子目錄下所有指定擴展名的文件
    • 5.3 按修改時間排序指定目錄下的文件
  • 6 總結
  • 參考資料
  • 往期文章

使用python的os模塊,簡單方便完成對文件夾、文件及路徑的管理與訪問操作。

1 前言

在最近開發中,經常需要對文件進行讀取、遍歷、修改等操作,想要快速、簡單的完成這些操作,我選擇用 python 。通過 python 的標準內置 os 模塊,只需要幾行代碼,即可完成想要的操作。經過對 os 的使用,本文把 os 模塊的常用的操作進行總結,主要分為以下幾個劃分:

  • 文件夾操作:即文件夾的創建、修改(改名/移動),查詢(查看、遍歷)、刪除等。
  • 文件操作:即文件的創建、修改、讀取、刪除等。
  • (文件夾/文件)路徑操作:即文件夾或文件的路徑操作,如絕對路徑,文件名與路徑分割,擴展名分割等

本文涉及常用 的 os 函數的使用展示,主要使用 python 交互模式下進行代碼說明。後續操作默認已經引入 os 模塊,如下:

import os

2 文件夾操作

以本地 E://pythontest 目錄作為演示目錄,此目錄下當前文件如下:

test
 │ test.txt
 └─test-1
     test-1.txt

testtest-1 是文件夾,test.txttest-1.txt 是文件。

2.1 查詢操作

熟悉 linux 同學應該對 ls / pwd / cd 等操作不陌生,對應的 python 也有對應的方法,主要包括:

  • listdir : 文件及目錄列表
  • getcwd :獲取當前目錄
  • chdir :更換目錄
  • stat :文件及目錄基本信息
  • walk :遞歸遍歷目錄
>>> os.chdir("E://pythontest")  # 更改目錄
>>> os.getcwd()                 # 獲取當前目錄
'E:\\pythontest'
>>> os.listdir("test")          # 文件及目錄列表,相對路徑
['test-1', 'test.txt']          
>>> os.listdir("E://pythontest/test")  # 文件及目錄列表,絕對路徑
['test-1', 'test.txt']
>>> os.stat("test")             # 獲取目錄信息
os.stat_result(st_mode=16895, st_ino=4503599627377599, st_dev=266147611, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1590833033, st_mtime=1590832647, st_ctime=1590832207)
>>> os.stat("test/test.txt")    # 獲取文件信息
os.stat_result(st_mode=33206, st_ino=2251799813692354, st_dev=266147611, st_nlink=1, st_uid=0, st_gid=0, st_size=4, st_atime=1590832653, st_mtime=1590832609, st_ctime=1590832598)

其中 stat 函數返回的是文件或者目錄的基本信息,具體如下:

  • st_mode: inode 保護模式
  • st_ino: inode 節點號。
  • st_dev: inode 駐留的設備。
  • st_nlink: inode 的鏈接數。
  • st_uid: 所有者的用戶ID。
  • st_gid: 所有者的組ID。
  • st_size: 普通文件以字節為單位的大小
  • st_atime: 上次訪問的時間。
  • st_mtime: 最後一次修改的時間。
  • st_ctime: 創建時間。

日常使用中,我們一般使用 st_size 、st_ctime 及 st_mtime 獲取文件大小,創建時間,修改時間。另外,我們看到輸出的時間是秒數,在這裏提一下,關於日期的轉換處理。

(1)秒數轉日期時間格式字符串

>>> import time                              # 引入time模塊
>>> timestruct = time.localtime(1590803070)  # 轉換為時間結構體
>>> print(timestruct)
time.struct_time(tm_year=2020, tm_mon=5, tm_mday=30, tm_hour=9, tm_min=44, tm_sec=30, tm_wday=5, tm_yday=151, tm_isdst=0)
>>> time.strftime("%Y-%m-%d %H:%M:%S",timestruct)   # 格式化時間
'2020-05-30 09:44:30'

(2)格式日期時間字符串轉秒數

>>> import datetime               # 引入datetime模塊
>>> timeobject = datetime.datetime.strptime("2020-05-23 10:00:00","%Y-%m-%d %H:%M:%S") #解析時間字符串為時間對象
>>> timeseconds=time.mktime(timeobject.timetuple())  # 獲取時間秒數
>>> print(int(timeseconds))       # 轉為int显示
1590199200
  • 遍歷操作

    walk 函數對目錄進行遞歸遍歷,返回 root,dirs,files,分別對應當前的遍歷的目錄,此目錄中的子目錄及文件。

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

    網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

>>> data = os.walk("test")               # 遍歷test目錄
>>> for root,dirs,files in data:         # 遞歸遍歷及輸出
...    print("root:%s" % root)
...    for dir in dirs:
...       print(os.path.join(root,dir))
...    for file in files:
...       print(os.path.join(root,file))
...
root:test
test\test-1
test\test-2
test\test.txt
root:test\test-1
test\test-1\test-1.txt
root:test\test-2
test\test-2\test-2.txt

2.2 創建操作

  • mkdir :新建單個目錄,若目錄路徑中父目錄不存在,則創建失敗

  • makedirs :新建多個目錄,若目錄路徑中父目錄不存在,則自動創建

>>> os.mkdir("test")
>>> os.mkdir("test1/test1-1")          # 父目錄不存在,報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'test1/test1-1'
>>> os.makedirs("test1/test1-1")       # 父目錄不存在,自動創建
>>> os.listdir("test1")
['test1-1']

2.3 刪除操作

  • rmdir :刪除單個空目錄,目錄不為空則報錯
  • removedirs : 按路徑刪除遞歸多級空目錄,目錄不為空則報錯
>>> os.rmdir("test1")                         # 若目錄不為空,報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [WinError 145] 目錄不是空的。: 'test1'
>>> os.rmdir("test1/test1-1")
>>> os.removedirs("test1/test1-1")            # 刪除多級空目錄
>>> os.listdir(".")
['test']

由於刪除空目錄的限制,更多的是使用 shutil 模塊中的 rmtree 函數,可以刪除不為空的目錄及其文件。

2.4 修改操作

  • rename :重命名目錄或文件,可修改文件或目錄的路徑(即移動操作),若目標文件目錄不存在,則報錯。
  • renames :重命名目錄或文件,若目標文件目錄不存在,則自動創建
>>> os.makedirs("test1/test1-1")
>>> os.rename("test1/test1-1","test1/test1-2")     # test1-1 修改為test1-2
>>> os.listdir("test1")
['test1-2']
>>> os.rename("test1/test1-2","test2/test2-2")     # 由於test2目錄不存在,報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'test1/test1-2' -> 'test2/test2-2'
>>> os.renames("test1/test1-2","test2/test2-2")    # renames可自動創建不存在的目錄
>>> os.listdir("test2")
['test2-2']

如果目標路徑文件已經存在,那麼os.rename()和os.renames()都會報錯:FileExistsError: [WinError 183] 當文件已存在時,無法創建該文件。

3 文件操作

3.1 查詢操作

  • open/read/close :文件讀取
  • stat :文件信息,詳細見前面文件夾中的 stat 說明
>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT)  # 打開文件
>>> str_bytes = os.read(f,100)                          # 讀100字節
>>> str = bytes.decode(str_bytes)                       # 字節轉字符串
>>> print(str)
test write data
>>> os.close(f)                                         # 關閉文件

注意 open/read/close 需要一起操作,其中 open 操作需要指定模式,上述是以讀寫模式打開文件,若文件不存在則創建文件。各模式具體如下:

flags — 該參數可以是以下選項,多個使用 “|” 隔開:

  • os.O_RDONLY: 以只讀的方式打開
  • os.O_WRONLY: 以只寫的方式打開
  • os.O_RDWR : 以讀寫的方式打開
  • os.O_NONBLOCK: 打開時不阻塞
  • os.O_APPEND: 以追加的方式打開
  • os.O_CREAT: 創建並打開一個新文件
  • os.O_TRUNC: 打開一個文件並截斷它的長度為零(必須有寫權限)
  • os.O_EXCL: 如果指定的文件存在,返回錯誤
  • os.O_SHLOCK: 自動獲取共享鎖
  • os.O_EXLOCK: 自動獲取獨立鎖
  • os.O_DIRECT: 消除或減少緩存效果
  • os.O_FSYNC : 同步寫入
  • os.O_NOFOLLOW: 不追蹤軟鏈接

3.2 創建操作

前面已提到,使用 open ,指定模式, 若文件不存在,則創建。有點類似 linux 操作中的 touch。

>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT)   # 若文件不存在,則創建
>>> os.close(f)

3.3 修改操作

  • open/write/close :寫入文件內容
  • rename ,renames : 與前面介紹的修改名稱、移動操作一致。
>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT)     # 打開文件
>>> os.write(f,b"test write data")                         # 寫入內容
15
>>> os.close(f)                                   # 關閉文件

3.4 刪除

  • remove :刪除文件,注意不能刪除目錄(使用 rmdir/removedirs)
>>> os.remove("test/test-1")       # 刪除目錄報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 2] 系統找不到指定的文件。: 'test/test1'
>>> os.remove("test/test.txt")     # 刪除文件
>>> os.listdir("test")
['test-1']

4 路徑操作

在使用文件或目錄過程中,經常需要對文件及目錄路徑進行處理,因此,os 中有一個子模塊 path,專門就是處理路徑操作的。主要有以下操作:

  • abspath :返回絕對路徑
>>> os.path.abspath("test")
'E:\\pythontest\\test'
  • exists :判斷文件或目錄是否存在
>>> os.path.exists("test")
True
>>> os.path.exists("test/test.txt")
False
>>> os.path.exists("test/test-1/test-1.txt")
True
  • isfile/isdir :判斷是否為文件/目錄
>>> os.path.isdir("test")
True
>>> os.path.isfile("test/test-1/test-1.txt")
True
  • basename/dirname:獲取路徑尾部和路徑頭部。其實就是以路徑中最後一個 / 為分割符,分為頭(head) 和尾(tail)兩部分,tail 是 basename 返回的內容,head 是 dirname 返回的內容。經常用於獲取文件名,目錄名等操作
>>> os.path.basename("test/test-1/test-1.txt")   # 文件名
'test-1.txt'
>>> os.path.basename("test/test-1/")     # 空內容
''
>>> os.path.basename("test/test-1")      # 目錄名
'test-1'
>>> os.path.dirname("test/test-1/test-1.txt")   # 文件所在目錄路徑
'test/test-1'
>>> os.path.dirname("test/test-1/")   # 目錄路徑
'test/test-1'
>>> os.path.dirname("test/test-1")   # 父目錄路徑
'test'
  • join :合成路徑,即把兩個參數使用系統路徑分割符進行連接,形成完整路徑。
>>> os.path.join("test","test-1")   # 連接兩個目錄
'test\\test-1'
>>> os.path.join("test\\test-1","test-1.txt")   # 連接目錄與文件名
'test\\test-1\\test-1.txt'
  • split :分割文件名和文件夾,即把 path 以最後一個斜線”/”為分隔符,切割為 head 和 tail ,以 (head, tail) 元組的形勢返回。
>>> os.path.split("test/test-1")     # 分割目錄
('test', 'test-1')
>>> os.path.split("test/test-1/")    # 以/結尾的目錄分割
('test/test-1', '')
>>> os.path.split("test/test-1/test-1.txt")  # 分割文件
('test/test-1', 'test-1.txt')
  • splitext :分割路徑名和文件擴展名,把path 以最後一個擴展名分隔符“.”分割,切割為 head 和 tail ,以 (head, tail) 元組的形勢返回。注意與 split 的區別是分隔符的不同。
>>> os.path.splitext("test/test-1")  
('test/test-1', '')
>>> os.path.splitext("test/test-1/") 
('test/test-1/', '')
>>> os.path.splitext("test/test-1/test-1.txt")  # 區分文件名及擴展名
('test/test-1/test-1', '.txt')
>>> os.path.splitext("test/test-1/test-1.txt.tmp") # 以最後的"."為分割點
('test/test-1/test-1.txt', '.tmp')

5 示例應用

下面以一些平時使用到的場景,對前面的操作函數進行綜合使用。

5.1 批量修改文件名

def batch_rename(dir_path):
    itemlist = os.listdir(dir_path)
    # 獲取目錄文件列表
    for item in itemlist:
        # 連接成完整路徑
        item_path = os.path.join(dir_path, item)
        print(item_path)
        # 修改文件名
        if os.path.isfile(item_path):
            splitext = os.path.splitext(item_path)
            os.rename(item_path, splitext[0] + "-副本" + splitext[1])

5.2 遍歷目錄及子目錄下所有指定擴展名的文件


def walk_ext_file(dir_path,ext):
    # 遍歷
    for root, dirs, files in os.walk(dir_path):
        # 獲取文件名稱及路徑
        for file in files:
            file_path = os.path.join(root, file)
            file_item = os.path.splitext(file_path)
            # 輸出指定擴展名的文件路徑
            if ext == file_item[1]:
                print(file_path)

5.3 按修改時間排序指定目錄下的文件

def sort_file(dir_path):
    # 排序前
    itemlist = os.listdir(dir_path)
    print(itemlist)
    # 正向排序
    itemlist.sort(key=lambda filename: os.path.getmtime(os.path.join(dir_path, filename)))
    print(itemlist)
    # 反向排序
    itemlist.sort(key=lambda filename: os.path.getmtime(os.path.join(dir_path, filename)), reverse=True)
    print(itemlist)
    # 獲取最新修改的文件
    print(itemlist[0])

6 總結

在需要對文件或者目錄進行操作時,python 是一個簡單快速選擇。本文通過 python 的標準內置 os 模塊及子模塊 os.path 的常用方法進行介紹,最後結合使用場景進行綜合使用。相信已經滿足大家對文件及目錄操作的大部分需求。

參考資料

  • python之os模塊:https://www.cnblogs.com/yufeihlf/p/6179547.html
  • Python OS 文件/目錄方法: https://www.runoob.com/python/os-file-methods.html
  • Python os.path() 模塊: https://www.runoob.com/python/python-os-path.html

往期文章

  • MinIO 的分佈式部署
  • 利用MinIO輕鬆搭建靜態資源服務
  • 搞定SpringBoot多數據源(3):參數化變更源
  • 搞定SpringBoot多數據源(2):動態數據源
  • 搞定SpringBoot多數據源(1):多套源策略
  • java開發必學知識:動態代理
  • 2019 讀過的好書推薦

我的公眾號(搜索Mason技術記錄),獲取更多技術記錄:

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

【JVM】垃圾回收的四大算法_貨運

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

GC垃圾回收

JVM大部分時候回收的都是新生代(伊甸區+倖存0區+倖存1區)。按照回收的區域可以分成兩種類型:Minor GC和Full GC(MajorGC)。

  • Minor GC:只針對新生代區域的GC,大多數Java對象的存活率都不高,Minor GC非常頻繁,回收速度快。
  • Full GC:發生在老年代的GC,經常會伴隨至少一次的Minor GC(但不一定會),Full GC掃描的範圍更廣泛,Full GC的速度比Minor GC慢10倍以上。

 

 

GC四大算法

引用計數法

對於單個對象來說,當有引用發生,引用計數器就+1;當丟失引用,引用計數器就-1。當引用數減到0的時候,說明對象不再有用,被垃圾回收。引用計數法缺點是每次對對象賦值都要維護引用計數器,且計數器本身也有一定的消耗,難以處理引用循環(例如:對象雙方互相引用,但實際上二者為空,此時雙方引用都不為空)。JVM的實現一般不採用這種方式。

複製算法

年輕代中使用的是Minor GC,這種Minor GC採用的是複製算法。複製的思想是將內存分為2快,每次只用其中一塊,當這一塊內存用完,就將或者的對象複製到另一塊上面,複製算法不會產生內存碎片

HotSpot JVM中年輕代可以分成三個部分:Eden區、Survivor0區,Survivor1區,默認比例為8:1:1。Survivor的兩個區在邏輯上可以視為from區和to區,每次GC後會交換from區和to區,在Eden區和from區滿之前,to區始終是為空的區。如果to區也被填滿了,所有對象移動到老年代。

新創建的對象一般會被分配到伊甸區,經過一次Minor GC后,如果對象還存活,就會被移到Survivor區。from區的對象如果繼續存活,且能夠被另一塊倖存區to區容納,則使用複製算法將這些仍然存活的的對象複製到另一塊倖存區to區中,然後清理使用過的Eden和from區(下一次分配就從to區開始,to區成為下一次GC的from區),且這些對象的年齡設置為1,以後對象在倖存區每經歷一次Minor GC,對象的年齡就會+1,當對象的年齡到達某個閾值的時候,這些對象就會進入老年代。(閾值默認是15,可以通過-XX:MaxTenuringThreshhold來設定對象在新生代在存活的次數)。

這種算法的優點了不會產生內存碎片,缺點是浪費內存空間,在HotSpot虛擬機中8:1:1的比例下,可用內存為80%+10%,有10%的內存會被浪費掉。如果對象存活率很高,就需要將所有對象都複製一邊,並重置引用地址。

標記清除(Mark-Sweep)

老年代一般是由標記清除 或者 標記清除和標記整理的混合實現的。

標記清除算法分為兩個步驟,先標記出要回收的對象,然後統一回收這些對象。

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

優點是節約內存空間,不需要額外空間。缺點是兩次掃描,標記和清除的效率都不高,耗時嚴重。標記清除後會產生大量不連續的內存碎片。內存碎片會導致以後程序需要分配大對象的時候,找不到足夠的連續內存,導致提前觸發GC。

 標記整理(Mark-Compact)

和標記清除一樣,先標記出要回收的對象,然後讓存活對象都向一端移動,直接清理掉端邊界 以外的內存。

優點是沒有內存碎片,缺點是效率不高,需要標記存活對象還要整理存活對象的引用地址,從效率上來說是不如複製算法的。

還有一種折衷的方案,將標記清除和標記整理算法相結合,一般直接標記清除,當GC達到一定次數的時候,進行一次標記整理,從而減少了移動對象的成本,又有處理內存碎片的步驟。

總結

效率排名:複製算法>標記清除>標記整理

內存整齊度:複製算法=標記整理>標記清理

內存利用率:標記整理=標記清理>複製算法

四種算法各有優劣,一般的JVM實現會採用分代收集算法,根據不同代所具有的不同特點使用不同的算法。

年輕代的特點是區域較小,對象存活率低,適合使用複製算法。複製算法的效率只和當前存活對象的大小有關,適用於年輕代的回收,內存利用率不高的問題HotSopt通過兩個survivor的設計進行和緩解,新生代可用容量為80%+10%,只有10%的內存被浪費掉。

老年代的特點是區域較大,對象存活率高,適合使用標記清除/標記整理算法。

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

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

基於RBAC的權限控制淺析(結合Spring Security)_網頁設計公司

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

 

嗯,昨天面試讓講我的項目,讓我講講項目里權限控制那一塊的,講的很爛。所以整理一下。

按照面試官的提問流程來講:

一、RBAC是個啥東西了?

RBACRole-Based Access Control ),即基於角色的訪問控制模型,我的項目是基於RBAC0模型.由於之相對應的數據實體構成.由用戶表,角色映射表,角色表,權限表,權限映射表構成.

 

 

1 RBAC0模型圖

二、你可以講講權限控制大概執行流程嗎?

 用戶登錄之後首先進行身份驗證,成功之後獲取當前用戶的所有角色,之後根據角色加載對應的權限菜單,這裏默認不加載沒有權限的菜單,當存在直接輸入URL路徑的情況時,對於登錄用戶的每一個請求,都會通過鑒權處理,分析角色.最後通過權限的判斷分析是否可以訪問菜單資源.

在 spring Security,對用登錄的請先通過FilterInvocationSecurityMetadataSource的實現類獲取當前請求,分析需要的角色,該類的主要功能就是通過當前的請求地址,獲取該地址需要的用戶角色。

1、獲取當前訪問路徑的URL路徑

2、獲取所有資源URL,即所有的菜單URL路徑

3、當前的訪問URL和返回的每個URL基於Ant風格比較,如果相等,獲取當前訪問URL的所有角色。如果沒有相等的,定義資源為公告資源,並且給予一個公告資源的角色。

4、當為公共資源時,判斷用戶是否登錄。登錄放行。返回資源

5、當為角色資源時,登錄用戶的角色列表和該資源的角色列表進行比較,如果有相同角色,放行,返回資源

6、當即不是公共資源也沒有相匹配的角色的時候。拋異常,沒有權限

圖2 系統訪問控制流程圖

 代碼:

鑒權:

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

@Component
public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    @Autowired
    MenuService menuService;
    //路徑比較工具
    AntPathMatcher antPathMatcher = new AntPathMatcher();
    Logger logger = Logger.getLogger("com.liruilong.hros.config.ustomFilterInvocationSecurityMetadataSource");
    /**
     * @return java.util.Collection<org.springframework.security.access.ConfigAttribute> * 返回值是 Collection<ConfigAttribute>,表示當前請求 URL 所需的角色。
     * @Author Liruilong
     * @Description 當前請求需要的角色,該方法的參數是一個 FilterInvocation, 開發者可以從 Filterlnvocation 中提取出當前請求的 URL,
     * @Date 18:13 2019/12/24
     * @Param [object]
     **/
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        //獲取當前請求路徑
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        logger.warning(requestUrl);
        //獲取所有的菜單url路徑
        List<Menu> menus = menuService.getAllMenusWithRole();
        // AntPathMatcher,主要用來實現 ant 風格的 URL 匹配。
         for (Menu menu : menus) {
            if (antPathMatcher.match(menu.getUrl(), requestUrl)) {
                //擁有當前菜單權限的角色
                List<Role> roles = menu.getRoles();
                String[] strings = new String[roles.size()];
                for (int i = 0; i < roles.size(); i++) {
                    strings[i] = roles.get(i).getName();
                }
                return SecurityConfig.createList(strings);
            }
        }
        // 沒匹配上的資源都是登錄,或者為公共資源
        return SecurityConfig.createList("ROLE_LOGIN");
    }

 

 @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        for (ConfigAttribute configAttribute : configAttributes) {
            String needRole = configAttribute.getAttribute();
            if ("ROLE_LOGIN".equals(needRole)) {
                if (authentication instanceof AnonymousAuthenticationToken) {
                    throw new AccessDeniedException("尚未登錄,請登錄!");
                } else {
                    return;
                }
            }
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            for (GrantedAuthority authority : authorities) {
                if (authority.getAuthority().equals(needRole)) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("權限不足,請聯繫管理員!");
    }

 

 

 

三、你可以把對應的SQL和表結構寫一下嗎?

 

加載所有的菜單資源;返回所有的菜單資源和對應的角色集合,Service端和訪問的URL的比較,存在判斷角色。(鑒權)


select m.*,r.`id` as rid,r.`name` as rname,r.`namezh` as rnamezh
from menu m,menu_role mr,role r
where m.`id`=mr.`mid` and mr.`rid`=r.`id` order by m.`id`
根據用戶ID返回當前用戶的全部菜單資源(授權)
   select m1.`id`,m1.url,m1.`path`,m1.`component`,m1.`iconCls`,m1.`name`,m1.`requireAuth`,m1.keepAlive,m1.enabled,
       m2.id as id2,m2.url as url2,m2.name as name2,m2.`component` as component2,m2.`iconCls` as iconCls2,m2.`keepAlive` as keepAlive2,m2.`path` as path2,m2.`requireAuth` as requireAuth2,m2.enabled as enabled2,m2.parentId as parentId2
       from menu m1,menu m2
       where m1.`id`=m2.`parentId` and m1.`id`!=1 and m2.`id`
       in(select mr.`mid` from hr_role h_r,menu_role mr where h_r.`rid`=mr.`rid` and h_r.`hrid`=#{hrId})
       and m2.`enabled`=true order by m1.`id`,m2.`id`

 

2 ERBAC數據實體關係圖

用戶登錄之後首先進行身份驗證,成功之後獲取當前用戶的所有角色,之後根據角色加載對應的權限菜單,這裏默認不加載沒有權限的菜單,當存在直接輸入URL路徑的情況時,對於登錄用戶的每一個請求,都會通過鑒權處理,分析角色.最後通過權限的判斷分析是否可以訪問菜單資源.

用戶表:

 

 角色表:

 

用戶角色映射表:

 

權資源表:

 

 

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

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

15萬買合資SUV必看!這款車居然是歐洲最暢銷車型之一!_貨運

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

而且作為一款SUV它的離地間隙達到了將近20cm這也保證了它具備一定實力的通過性,可以適合歐洲主要以丘陵為主的道路,以及中國多路況的局面,這也是為什麼逍客的銷量在中國銷量也不差的原因。逍客配備的是一款2。0L自然吸氣發動機,最大馬力達到150ps,以及一台模擬七速的CVT變速箱,動力總成的賬面參數並不突出,但是對於家用來說,動力輸出已經完全可以滿足日常的用車需求。



歐洲,世界汽車工業誕生的搖籃,孕育出了寶馬、奔馳、大眾等等世界知名的汽車品牌,但是來自日產的逍客,居然成為了歐洲最暢銷的SUV車型之一,而且逍客在國內的銷量也不低,平均月銷量都過萬台,這車究竟為什麼會如此受歡迎?

外觀:其貌不揚卻迎合觀眾

熟悉歐洲車的朋友都知道,除了法系車以外,以德系車為代表的汽車外觀設計都是普遍偏向保守,這其實也跟歐洲人普遍的審美還是偏向保守嚴謹有關。

逍客的外觀其實沒有什麼突出的亮點,日產家族式的前臉,用整體性更強的幾何板塊營造出一個不過不失,中庸圓潤的車輛外形,這也十分符合一台家用SUV應有的定位。

逍客的車主年齡層次涵蓋十分廣泛,從65后的中年人到85后的年輕人,購買逍客的不在少數,正式這種其貌不揚但是老少通殺的外觀設計才能做到真正迎合消費者的普遍審美。

操控:駕控靈活,可適應路況眾多

作為一台緊湊型SUV,逍客的軸距並不算短,達到了2645mm,但是車身的前後懸較短,營造出了一個較為短小精悍的外觀,

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

而且由於逍客的操控特性建立得十分靈敏,導致逍客的操控感受十分靈敏輕便。談不上什麼運動感和駕駛樂趣,但是逍客卻可以成為一家人所有會開車的人士都比較好上手的一台SUV。

而且作為一款SUV它的離地間隙達到了將近20cm這也保證了它具備一定實力的通過性,可以適合歐洲主要以丘陵為主的道路,以及中國多路況的局面,這也是為什麼逍客的銷量在中國銷量也不差的原因。

逍客配備的是一款2.0L自然吸氣發動機,最大馬力達到150ps,以及一台模擬七速的CVT變速箱,動力總成的賬面參數並不突出,但是對於家用來說,動力輸出已經完全可以滿足日常的用車需求。

內飾:樸實無華,舒適至上

日產的汽車在內飾層面不會體現過多的設計感,走量的車型普遍都是以很樸素的樣式進行設計,中控功能區的按鍵布局合理簡潔,內飾的溝通感做得不錯,但是方向盤尺寸偏大而且握感很細,在駕駛的時候或許需要駕駛員做更多的適應。

逍客的乘坐空間布局不算很大,後排空間顯得比較局促,但是勝在座椅的貼合程度很高,所以乘坐起來很舒適,各種布局都體現了逍客是一款適合家用的SUV。

全文總結:什麼車是一台好車,相信不少人眼裡都會有不同的答案。有些人注重的是品牌情懷,有人注重的是各種突出的性能,而更多人可能選擇是一款足夠實用,簡單,而且不過不失的車型,SUV作為國人家庭接受度程度比較高的車型,日產的逍客或許沒有什麼吸引的品牌效應,甚至有不少排斥日系的朋友會對其不屑一顧,但就事論事的說,逍客作為15萬級的合資家用SUV來說,可以作為一款不錯的選擇。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

專家學者聚焦古民居保護傳承:像對老人一樣善待古民居_包裝設計

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

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

城市化進程加快,使得自然村落加速消散。如何保護傳統古民居,促進建築遺產良性有序傳承,成為文化收藏界深思的話題。

在彙集了眾多徽派古民居的聞道園,業界專家、收藏者11日舉行了一個小型沙龍,共同聚焦古民居的文化傳承及活態保護。

同濟大學國家歷史文化名城研究中心特約研究員居平表示,古民居是中國人的傳統住宅,體現了獨特的中華文化,其中蘊含的文化藝術可謂國粹。古民居體現了中國人的生活方式、人際交往,以獨特的方式呈現中國之美。由此,留住古民居也是留住了“中國文化的根”。

知名建築保護專家阮儀三在接受採訪時認為,注重真實性、整體性、可讀性、永續性、獨特性是老房子收藏保護的最高境界。他亦坦言,實在非拆不可,只能異地保護,花功夫拆,給每一片瓦、每一塊磚都編上號。收藏學專家祝君波也認為,異地收藏和保護並非上策,但比之於“毀”,是一種妥協的辦法。

坐落在上海寶山羅店鎮的聞道園,規劃面積600餘畝,被業界譽為“古建築異地保護的典範”。沙龍採訪之餘,記者探訪了這座洋溢着古典之美的園林。行走其間,記者看到,園內錯落有致地佇立了數十座古色古香的徽州老宅、古橋、古亭、戲台……庭院里、房間里懸挂、擺放着匾額、傢具等“老物件”。清代咸豐九年的永濟橋、道光八年的狀元樓、乾隆年間的雕花樓……在這裏靜靜地佇立着,散發著厚重的歷史氣息,青石砌成的門牆洋溢着濃濃的古意,石磨盤連成的小路蜿蜒神相遠處,置身寧靜古樸的飛檐古宅群之間,在垂柳、碧波映襯下,彷彿時空倒轉,現代人與崇尚自然的古人有了神交。

聞道園創始人王衛告訴記者,目前園中仍有包括明代大夫第、明代金絲楠木翰林院、清代大祠堂等在內的百餘棟古民居原材料還靜待搭建。

談及收藏這些古民居的初衷,王衛十分感慨:收藏古宅的初衷不僅源於對徽式古建築的喜愛,更出於對老宅飄零凋敝現狀的痛心。20多年前,他與朋友在安徽鄉間遊歷,黛瓦、粉壁、馬頭牆的徽派古民居建築之美深深吸引着他們。承載着數百年歷史滄桑的飛檐、雕花韻味雋永,讓人回味無窮。可是當時在安徽的一些農村,修復一幢稍有規模的古宅所需費用,憑當地人的年收入,根本無力承受。日久天長,一些古宅或受潮霉爛,或坍塌廢棄。不少精美木雕被住戶丟棄。

王衛說,眼睜睜看着不少古宅被用作豬圈、養蠶場,心中不僅是痛楚,還有對傳統文化失落的擔憂。於是,他將早年做生意所得積蓄投入古民居的收藏。為了盡可能多地保留下這些古民居,王衛曾一度賣掉房產,來收藏別人眼中的“爛木頭”。

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

王衛告訴記者,很多古民居在被收藏的時候已然破敗不堪,甚至已經倒塌。不少古民居或被白蟻蛀蝕、或被風雨侵蝕,毀損嚴重,脆弱飄搖地存在於世間,如同風燭殘年的老者。有些古民居只剩下主要構件。在王衛看來,每一棟古民居都是不可再生的財富,不僅記載着歷史變遷,更飽含文化傳承的價值。王衛將這些當地人眼中的“廢物”,當做寶貝,一件不落地運回上海。或者按原貌維修重建,或者進行防腐、防蛀處理后暫時保存起來,等待日後逐一恢復原貌。

在收集古民居的20餘年裡,一百多棟古民居建材被王衛用卡車分300多次運到上海。王衛說,遇到特別粗大的冬瓜梁,因為鄉村道路設施限制,無法用吊機搬動,所以只能靠人力靠人力搬運。一根冬瓜梁常需要20多個壯漢共同搬動。

據了解,一些古民居的部件,因為年代久遠,經多年風霜侵蝕,無法再使用,所以在建設過程中,王衛和工作人員按照原部件的材質和形態,四處尋覓最為相似的部件。他說,這是一個艱辛的而糾結的過程。

如今,20多棟徽派古民居已經建好,成為上海“水泥鋼筋”森林中,別具特色的徽派古民居觀賞地。王衛賦予每一棟重煥新生的古民居不同的“職責”。有的成為傳播傳統文化的文創中心,有的作為人們修心的禪修堂,還有的變身書院、畫院和大師工作室。聞道園也成為書畫家、文人墨客青睞的創作、展示作品場所。王衛說,重生的古民居只有在現代人的使用中才能得到最好的保護。

談及未來,王衛期待一棟棟古民居逐漸恢復修建,古建築藝術重煥光彩。他希望這些古民居成為傳統文化的彰顯之地。

不過,如今,待建的百餘棟古民居原材料暴露在自然環境中,這令王衛十分着急。古民居全部重建需要時間,而原本就已經十分破敗凋敝的老木料雖經修復,但已經不起風霜烈日的摧殘。王衛說,如果在自然環境中再次霉爛,這些古民居終將難逃毀滅的厄運。

作為文化研究學者,居平坦言,在現實中,古民居的保護與當地居民實際需求,以及與相關機構、個人利益產生衝突。這對古民居保護確實不利。她呼籲,要像善待老人一樣善待、愛護古民居。

談及還未恢復建造的古民居原材料,阮儀三指出,應給這些寶貴的原材料提供相對穩定的存儲環境。對古民居的保護不僅要動用高科技手段,還要進行活態保護。(陳靜)

本站聲明:網站內容來http://www.societynews.cn/html/wh/fq/,如有侵權,請聯繫我們,我們將及時處理

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

Python裝飾器的一點解讀_貨運

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

  版權申明:本文為博主窗戶(Colin Cai)原創,歡迎轉帖。如要轉貼,必須註明原文網址

  http://www.cnblogs.com/Colin-Cai/p/12977127.html 

  作者:窗戶

  QQ/微信:6679072

  E-mail:6679072@qq.com

  理論上,函數是一等公民(first class function)的語言都可以使用函數式編程,從而利用算子(高階函數)來做裝飾器。

  裝飾器一般是這樣一個算子,它接受一個函數作為參數,返回另外一個函數。裝飾器,顧名思義,就是把一個函數“裝飾”一下,得到另外一個函數。為何要裝飾一下呢?目的一般是可能設計上需要對函數做一些改裝,比如原函數輸出結果需要再加工加工,或者原函數的輸入參數傳入不一樣,或者兩者兼有之,等等。

 

  迭代是編程中常用的手段,它的計算方式表現為狀態的不斷變換,且狀態的變換具有唯一性。

  比如我們使用Scheme來表示迭代。

;stat代表當前狀態,next代表狀態改變函數,final?代表判斷狀態是否終止
(define (iterate-orgin stat next final?)
  (if (final? stat)
      stat
      (iterate-orgin (next stat) next final?)))

;將next函數和final?函數封成一個函數
(define (iterate stat f-stat)
  (iterate-orgin stat (f-stat 'next) (f-stat 'final)))

;最終我們需要的迭代函數
(define (it f-stat)
  (lambda (stat) (iterate stat f-stat)))

  

  以上構造出一個算子it,就是用來“裝飾”迭代的函數。

  我們構造一個對list求和的迭代:

  可以每次把list的前面兩個相加,比如對(1 2 3 4 5)求和,經過以下狀態:

  (1 2 3 4 5)

  (3 3 4 5)

  (6 4 5)

  (10 5)

  (15)

  15

  得到最後結果15。

  代碼可以如下:

(define (make-sum-func sym)
 (if (eq? sym 'next);next函數
  (lambda (lst)
   (if (pair? lst)
    (if (null? (cdr lst))
     (car lst)
     (cons (+ (car lst) (cadr lst)) (cddr lst)))
    lst))
  (if (eq? sym 'final?);final?函數
   (lambda (lst) (not (pair? lst)))
   '())))

 

  然後測試一下((it make-sum-func) ‘(1 2 3 4 5)),得到最後結果15。

  上面兩個函數寫在一起,我們還可以再分離一下。

  

;定義一個打包函數
(define (wrap-next-final next final?)
 (lambda (sym)
  (if (eq? sym 'next)
   next
   (if (eq? sym 'final?)
    final?
    '()))))

;下面next和final?兩個函數可以分開寫
(define make-sum-next
 (lambda (lst)
  (if (pair? lst)
   (if (null? (cdr lst))
    (car lst)
    (cons (+ (car lst) (cadr lst)) (cddr lst)))
   lst)))

(define make-sum-final?
 (lambda (lst) (not (pair? lst))))

;於是函數就可以下面這樣表示
(define make-sum-func (wrap-next-final make-sum-next make-sum-final?))

 

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

  總而言之,裝飾器就是這樣一類算子。

 

  Python也是這樣,只是Python提供了@這樣的語法,實際上是個語法糖,與其說是簡寫,倒是更像是個語法提醒這是一個裝飾器。

  我們這次希望來显示一下mysym,還是用求和。

  先寫一個簡單的mysum函數用於求和: 

def mysum(*args):
    ret = 0
    for i in args:
        ret += i
    return ret

 

  做一個算子,來擴充它的輸入參數:

  這裏需要用來判斷一個對象是否是可迭代對象,

  from collections import Iterable

  然後,如果判斷對象x是否是可迭代對象,只需要:

  isinstance(x, Iterable)

  算子如下:

from collections import Iterable
def args_expan(f):
    def f2(*args):
        lst = []
        for i in args:
            if isinstance(i, Iterable):
                lst.append(f(*i))
            else:
                lst.append(i)
        return f(*lst)
    return f2

 

  然後在mysum前添加裝飾器標誌

@args_expan
def mysum(*args):
    ret = 0
    for i in args:
        ret += i
    return ret

 

  測試如下:

print(mysum(1,2,3,4,5))
print(mysum((1,2,3,4,5)))
print(mysum([1,2,3,4,5]))
print(mysum(range(1,6)))
print(mysum(map(lambda x:x+1, range(5))))
print(mysum(filter(lambda x:x<6, range(10))))

#構造了一個生成器
def gen_range(a, b):
    while a < b:
        yield a
        a += 1

print(mysum(\
    filter(lambda x:x<6, range(10)), \
    6, \
    [7,8], \
    (9, 10), \
    map(lambda x:x+11, range(10)), \
    gen_range(21,101)))

 

  運行得到:

15
15
15
15
15
15
5050

  終於看到,函數功能已被擴充。

  這個裝飾器還可以裝飾別的函數,比如乘積、統計等。

 

  從而,裝飾器就是這樣一個算子,一般用來改造函數的輸入或輸出,避免重複寫代碼。

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

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

Java動態代理與靜態代理以及它能為我們做什麼_網頁設計公司

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

  相信我們在網上和平時學習和工作中或多或少都接觸過Java的代理模式,經常聽到什麼靜態代理、動態代理的一些名詞。但我們是否真的很清楚這些呢?至少我在面試時,發現很多人並不很清楚。

  首先代理比較好理解,就是幫一個人,或者一類人做一些事情。遷移到面向對象的程序設計中,代理就是幫一個類去做一些事情,而這個代理的工具我們就稱為代理類。

  通過代理的方式去做事有什麼好處呢?這就好比工廠和分銷商做的事情一樣,工廠可以直賣一些自己的產品,分銷商同樣也可以賣工廠生產的產品,那麼為什麼還有分銷商的存在呢?因為分銷商可以提供一些額外的服務,或者在銷售的過程中能夠完成一些其他的事情,比如組合銷售、根據本地情況做活動等,而這些可能是工廠不想關心或者也管不過來的。這樣的功能和角色承包給代理商就會使得分工比較明晰,並且又能夠提供一些額外或者定製的服務。

 

靜態代理

  Java中的代理方式可以分為靜態代理和動態代理。靜態代理的含義是代理類/對象在我們關心的程序運行前就已經確定或存在。靜態代理比較好理解,我們在日常工作中也是經常用到,比如一個已經存在的接口,我們不期望去更改它,但是現在要在原邏輯上新加一些邏輯或功能,比如原接口方法調用完成后發送一個消息之類的。於是我們可以創建一個類,同樣實現原接口,並且把之前存在的接口當做成員變量注入進來,調用其中的方法,並添加我們需要的功能。

  靜態代理的類圖如下所示,需要被代理的實現類和代理類都實現了抽象接口AbstractInterface,而InterfaceProxy和InterfaceImpl間是聚合關係。

  

 

 

 

   來看一段示例代碼,ProductAuditCallbackService 是我們已有的一個接口,出於某些原因,這個接口不能繼續對外使用,我們需要定義一個新的接口並且名稱還要一樣(主要是方便客戶理解和對應原接口),但是我們需要添加一點“新邏輯”。因此我們可以同樣實現 ProductAuditCallbackService,ProductAuditCallbackServiceProxy 就是我們的代理類,之後外部調用就可以實例化我們的代理類,調用同名方法就好了。

 

 1 public class ProductAuditCallbackServiceProxy implements ProductAuditCallbackService {
 2 
 3     @Resource
 4     private ProductAuditCallbackService productAuditCallbackService;
 5 
 6     @Override
 7     public Result<Void> auditProduct(ProductAuditRequest request, String auditStatus) {
 8         if (auditStatus == "DELETED") {
 9             return new Result<>();
10         }
11         return productAuditCallbackService.auditProduct(request, auditStatus);
12     }
13 
14 
15 ...
16 }

 

 

 

 

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

動態代理

  動態代理的作用和靜態代理一樣,主要的區別就在於需要在運行時生成代理類。在使用動態代理時,我們還需要定義一個在代理類和委託類之間的中介類,並且中介類需要實現 java.lang.reflect.InvocationHandler 接口。

 1 package java.lang.reflect;
 2 
 3 /**
 4  * {@code InvocationHandler} is the interface implemented by
 5  * the <i>invocation handler</i> of a proxy instance.
 6  *
 7  * <p>Each proxy instance has an associated invocation handler.
 8  * When a method is invoked on a proxy instance, the method
 9  * invocation is encoded and dispatched to the {@code invoke}
10  * method of its invocation handler.
11  *
12  * @author      Peter Jones
13  * @see         Proxy
14  * @since       1.3
15  */
16 public interface InvocationHandler {
17 
18     public Object invoke(Object proxy, Method method, Object[] args)
19         throws Throwable;
20 }

  

  動態代理在框架類的代碼中用到的頻率並不低,而且能夠使我們的代碼看起來更高級一些,所以何樂而不為呢? 讓我們來看一些實際的例子。

  MethodInvocationHandler是一个中介類,實現了InvocationHandler接口,MethodMonitor 這個類的功能就是要統計我們的委託類的對象business中的方法被調用的次數和耗時,由於其主要功能不是我們關注的主要內容,所以忽略其實現。

 1 public class MethodInvocationHandler implements InvocationHandler {
 2 
 3     //被代理對象
 4     private Object business;
 5 
 6     private final MethodMonitor methodMonitor;
 7 
 8     public MethodInvocationHandler(MethodMonitor methodMonitor) {
 9         this.methodMonitor = methodMonitor;
10     }
11 
12     /**
13      * 代理方法
14      */
15     @Override
16     public Object invoke(Object proxy, Method method, Object[] args)
17             throws Throwable {
18 
19         long startTime = System.currentTimeMillis();
20 
21         Object result = method.invoke(this.business, args);
22 
23         //方法調用統計
24         this.methodMonitor.methodCount(this.business.getClass().getSimpleName() + POINT + method.getName(), startTime);
25         return result;
26     }
27 
28 }

  其餘示例代碼及外部調用示例如下,我們的Business類裏面擁有三個方法。MethodSampleClient 則是一個封裝起來的客戶端。我們不想讓外部客戶端感知我們的實現以及和Business的關係,於是我們在MethodSampleClient中定義了一個成員變量proxy,當外部需要Business提供的一些功能時,我們通過proxy為其提供。Proxy.newProxyInstance() 則是我們實例化一個代理類的方式,喲,這還是個工廠模式,可以閱讀一些這個方法的說明,需要傳入的三個參數依次是:需要被代理的類的ClassLoader,被代理類需要被代理的接口的集合,中介處理類的實例。

  這裏Business我寫的是一個確定的類,其實真正在實際開發工作中,我們往往定義的抽象的接口或抽象類,知道運行時才會確定到底是哪個實現類的實例,這樣可能更容易理解一些:運行時確定委託類的實現類,運行時生成代理類,並調用對應的委託類的方法。

 

 1 public class Business {
 2 
 3     public void createJob() {
 4         System.out.println("test createJob");
 5     }
 6 
 7 
 8     public void processJob() {
 9         System.out.println("test processJob");
10     }
11 
12     public void closeJob() {
13         System.out.println("test closeJob");
14     }
15 
16 }
17 
18 
19 
20 public class MethodSampleClient {
21 
22     private Business business;
23 
24     @Getter
25     private Object proxy;
26 
27     private InvocationHandler invocationHandler;
28 
29 
30     public void init() {
31         this.business = new Business();
32         this.invocationHandler = new MethodInvocationHandler(new MethodMonitor());
33         this.proxy = bind(this.business, invocationHandler);
34     }
35 
36     /**
37      * 綁定對象, 直接初始化並返回代理類供客戶端使用
38      */
39     public Object bind(Object business, InvocationHandler invocationHandler) {
40         return Proxy.newProxyInstance(
41                 //被代理類的ClassLoader
42                 business.getClass().getClassLoader(),
43                 //要被代理的接口,本方法返回對象會自動聲稱實現了這些接口
44                 business.getClass().getInterfaces(),
45                 //代理處理器對象
46                 invocationHandler);
47     }
48     
49 }    
50 
51 
52 /**
53 *  A simple client test class
54 */
55 public class Test {
56 
57     public void main(String[] args) {
58         MethodSampleClient methodSampleClient = new MethodSampleClient();
59         methodSampleClient.init();
60 
61         methodSampleClient.getProxy().createJob();
62         methodSampleClient.getProxy().processJob();
63         methodSampleClient.getProxy().closeJob();
64     }
65 
66 }

   

  為了說清楚這個過程,竟然還真的寫了不少代碼,看起來比較繁瑣。總結一下,動態代理無非按照下面的步驟來編寫代碼:

  • 首先明確需要被代理的委託類。
  • 實現 InvocationHandler 接口,定義一个中介類。
  • 用 Proxy.newProxyInstance() 實例化代理類,並在客戶端代碼中直接使用。

  好了,大概差不多了,最重要的是能夠在實際工作中有意識地去使用並體會其作用 —— 軟件開發是經驗驅動不是知識驅動。

 

 

 

 

  

 

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

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

這款15萬級的國產SUV氣場竟然完爆路虎?_包裝設計

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

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

車身側面和尾部的設計風格則可以看出相當高的原創度,沒有採用溜背式的“極光”造型,而是用了較為方正的懸浮式車頂設計,這樣會使得車身側面顯得更加剛毅,整車的力量感與肌肉感也顯現出來。內飾層面同樣也是向成熟車型借鑒的意圖比較明顯,黑紅色的雙拼搭配是營造一台車內飾運動氛圍屢試不爽的設計風格,並且採用了一定量的鍍鉻裝飾進行點綴,中控造型十分前衛也比較符合當下設計潮流。

路虎,SUV車型中絕對的明星品牌,如果我告訴你十五萬不到就可以買到“路虎”,你還是會想到陸風X7?還是想到眾泰又準備複製哪一款成熟車型?不,今天的主角是一款可以比肩路虎的SUV——來自廣汽吉奧的GX6。

廣汽吉奧GX6

指導價格:10.98-14.68萬

我們可以看到吉奧GX6的外形讓人感到十分熟悉,很多路虎極光的設計元素在其身上,但是不得不說也融入了當下非常流行的運動化設計,讓GX6看上去十分年輕時尚。車身尺寸為4640*1815*1800,而且軸距達到了2745,而路虎攬勝極光的尺寸為4370*1900*1635,軸距為2660,尺寸上吉奧GX6不可謂不大。

車身側面和尾部的設計風格則可以看出相當高的原創度,

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

沒有採用溜背式的“極光”造型,而是用了較為方正的懸浮式車頂設計,這樣會使得車身側面顯得更加剛毅,整車的力量感與肌肉感也顯現出來。

內飾層面同樣也是向成熟車型借鑒的意圖比較明顯,黑紅色的雙拼搭配是營造一台車內飾運動氛圍屢試不爽的設計風格,並且採用了一定量的鍍鉻裝飾進行點綴,中控造型十分前衛也比較符合當下設計潮流。而且做工的細緻程度也是比較精細,不會有過於明顯的粗糙感。只是用料偏廉價,硬質塑料比較多。

動力總成方面廣汽吉奧GX6所使用的是來自三菱的4G69S4N汽油發動機,排量為2.4L,並且搭載的是手動變速箱,三菱的自然吸氣發動機可靠性毋庸置疑,但是全系沒有自動變速箱的配置着實有點對不起觀眾;而且這款發動機技術比較過時,以目前的汽車發展來說,吉奧GX6的油耗並不低。

編輯總結:採用借鑒的方式進行汽車的設計和生產是國內很多車企都在進行或者曾經做過的方式,好壞與否暫且不論,但這也說明這種外觀的設計是比較討好消費者的設計。

GX6的整車配置不低,像是目前自主品牌SUV車型普遍搭載的中控大屏、倒車影像、一鍵啟動、無鑰匙進入等等配置較為齊全,比較可惜的是這款車目前搭載的是全手動變速箱,據悉裝配了自動變速箱的新款吉奧GX6會在今年年底上市,屆時或許可以對於它的新車做一下期待。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

小米推出小米便攜鼠標 2,內建雙模式可操作兩台電腦、4 段可調 DPI、一顆 5 號電池可用一年_貨運

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

小米便攜鼠標第一代推出至今也有超過二年的時間,依據其他產品的經驗,這款可說更新的相當慢,終於在稍早小米官方正式宣布二代「小米便攜鼠標 2」登場,除了延續上一代的雙模式特色外,還加入了 4 段可調 DPI 與更強悍的待機續航力,更重要是,價格還只需要 79 人民幣(約台幣 340 元),真的超值阿。

小米推出小米便攜鼠標 2

這次小米便攜鼠標 2 跟很多小米產品一樣,採用眾籌的方式開賣,眾籌價為 79 人民幣,預計 12/30 早上 10 開售,一直到 1/6 早上 10 點結束,隨後價格也會調整回零售的 99 人民幣(約台幣 425 元)。

就外型來看,小米便攜鼠標 2 跟上一代沒有太大差異,不過側面線條更佳時尚,也沒那麼厚,我覺得變得更好看,表面也採用細膩噴砂金屬處理,擁有耐磨耐腐蝕特性。另外雙模式(藍牙4.2 + USB 接收器)的按鍵也移到正面,使用上更容易:

搭載消耗功率低 Telink 藍牙晶片,並內建自動休眠技術,來降低待機功耗,實現更好的省電節能。根據官方測試數據,裝一顆 5 號電池,就能正常使用一整年的時間,用到後面你搞不好會以為它不需要裝電池。電量低於 10% 時,正面上方的 LED 紅燈也會亮起,來提醒使用者:

上一代 DPI 為固定的 1200,小米便攜鼠標 2 全新加入 4 段靈敏度調整,分別為 1200、1800、2400 與 4000,滿足使用者各種需求。DPI 功能鍵位於底部,切換時也會透過 LED 燈來提示你目前是什麼 DPI:

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

體積一樣相當輕巧,含電池僅 86 公克,攜帶上非常容易:

有白銀與黑灰兩種顏色。至於會不會進台灣,我是覺得有點難,畢竟第一代都沒有了。無論如何,有興趣入手的人還是可以透過集運之類方式,眾籌部分預計 1/13 起開始出貨:

多款小米筆電 Pro 現身 Geekbench,單核效能大幅提升

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

國外玩家反應 Epic Games 啟動器會導致 AMD 與 Intel CPU 溫度提升,還會發送數據到某個網址_網頁設計公司

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

EPIC Games Store 正推出連續 15 天都送免費遊戲的活動(雖然有點沒誠意),相信很多人每天都準時收藏起來,不過如果你平常沒用 EPIC Games 啟動器的話,最好把它整個關閉,也就是不要縮小在右下角,因為最近有玩家發現,Epic Games 啟動器會導致 AMD 與 Intel CPU 溫度提升,不僅差了十幾度,還有外媒實測揭露,Epic Games 啟動器會持續在背景發送數據到某個網址。

國外玩家反應 Epic Games 啟動器會導致 AMD 與 Intel CPU 溫度提升

最近在國外 Reddit 論壇上,一名網友指出他發現把 EPIC Games 啟動器關掉之後,自己的 AMD Ryzen 5800X 處理器從 50 度降到 37 度,少了 13 度,他甚至用不要再打開這惡意軟體來形容,如果想玩 EPIC 遊戲,請使用另一套 Legendary,免費遊戲則透過網頁版領取就好:

隨後下方陸續有其他網友表示,他也碰到相同狀況,不過處理器是 AMD Ryzen 5900X。另外還有 Ryzen 5 2600,這位網友說他看 YouTube 時溫度是 46,原本以為還可以,但把 EPIC Games 啟動器整個關掉後,立刻降到 38 度:

Intel 處理器也有案例,不過他碰到的是 EPIC Games 啟動器的使用率達 15~20%,沒特別提溫度,不過既然使用率提升,溫度基本上也會上升:

關於這點,外媒 Hot Hardware 也進行了實測,結果發現不只是處理器溫度變高,還悄悄在背後持續發送數據到一個指定網址。

下方是尚未開啟 EPIC Games 啟動器的截圖,AMD Ryzen 9 5950X 的 CPU 溫度為 34.28:

EPIC Games 啟動器打開之後,溫度立刻提升到 56.78,差了 20 度,比 Reddit 網友反應的還多:

雖然很多遊戲啟動器打開時(如:Steam、GOG),CPU 使用率與溫度都會提升,但基本上過一陣子後就會降低,不像 EPIC Games 啟動器是一直保持這種狀態。

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

因此,他們還透過一款 Glasswire 網路流量監控工具來檢測 EPIC Games 啟動器,結果發現,它會持續將數據傳送到 22 台不同伺服器上,無論是打開還是最小隱藏啟動器都會:

EpicWebHelper 還會發送一些數據到這個網址:

  • tracking-website-prod07-epic-961842049.us-east-1.elb.amazonaws.com

相較於 Steam 與 NVIDIA GeForce Experience,EPIC 發送的數量是 14 倍以上。不過不確定這跟 CPU 使用率和溫度提升是否有關連。

所以說,如果你平常沒在使用 EPIC Games 啟動器,建議就整個關掉,不要最小化隱藏在右小角中。對於擔心個人隱私的人,也能嘗試看看 Legendary。

資料來源:Reddit、Hot Hardware

EPIC、Spotify 等公司成立應用程式公平聯盟,對抗 Apple 的 30% 抽成

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單