發表文章

目前顯示的是 2019的文章

Java Lambda Map篇

目的 主要介紹Map中的新方法,包含如下 forEach() getOrDefault() putIfAbsent() remove() replace() replaceAll() merge() 有些是Lambda有些則是我覺得比以前使用Map更方便而介紹 forEach Map的forEach方法與List不大依樣,因為Map主要的迭代方法是以Entry為主,所以需要Key-Value Pair去迭代 原始碼解說 可以看到forEach的傳入參數BiConsumer介面,必須傳入Key與Val,裡面的實作就如同我們使用Java8版本以前的寫法,需要使用for迴圈去迭代抓出每個Value 原始碼 default void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); for (Map.Entry<K, V> entry : entrySet()) { K k; V v; try { k = entry.getKey(); v = entry.getValue(); } catch(IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } action.accept(k, v); } } 範例 private void forEachExample() { Map<Integer, String> map = new HashMap<>(); map.put(1, "test1"); map.put(2, "test2"); m

JWT(JSON Web Token) 和 Session 的差別

圖片
目的 透過這篇文章理解JWT(JSON Web Token)與Session的差異,以及為何現在大家都用JWT而不是用傳統的Session儲存使用者的資訊,本篇文章的案例都透過登入行為做解說。 緣由 這篇文章主要針對兩者的差異,其實我一直以來只用過session做過使用者狀態傳輸,但是因為工作使用到了Jhisper框架開始嘗試JWT,不過因為這套框架已經將JWT都完整包好直接使用就好,所以不是非常了解,直到有天需要自己寫Spring Security後才發現JWT的奧妙,但是在嘗試的過程中一直不知道為啥不使用Session就好,就開始展開兩者VS的冒險,也有了這篇文章。 Cookie & Session 如果要討論Session的話首先我們必須先理解Cookie是甚麼。 Cookie 我們可以從Wiki上得知 因為HTTP協定是無狀態的,即伺服器不知道用戶上一次做了什麼,這嚴重阻礙了互動式Web應用程式的實現。在典型的網路購物場景中,用戶瀏覽了幾個頁面,買了一盒餅乾和兩瓶飲料。最後結帳時,由於HTTP的無狀態性,不通過額外的手段,伺服器並不知道用戶到底買了什麼,所以Cookie就是用來繞開HTTP的無狀態性的「額外手段」之一。伺服器可以設定或讀取Cookies中包含資訊,藉此維護用戶跟伺服器對談中的狀態。 但是使用Cookie會有以下的缺陷 辨識不精確 如果在同一台機器上使用多個瀏覽器,每個瀏覽器在不同的儲存位置儲存 Cookie,因此,Cookie 並不能定位到一個具體的人,而是用戶,電腦和瀏覽器的組合。 不準確的狀態 如果用戶在取得了一個 Cookie 之後,點擊了瀏覽器的"回退"按鍵,則瀏覽器的狀態和取得Cookie 的狀態就出現了不一致.例如, 如果網站基於 Cookie 技術實現了購物車的應用,當用戶添加了物品後點擊了"回退"按鍵, 購物車的物品狀態可能並沒有發生變化. 隱私、安全和廣告 Cookie 是沒有加密的 案例 Cookies在某種程度上說已經嚴重危及用戶的隱私和安全。其中的一種方法是:一些公司的高層人員為了某種目的(譬如市場調研)而存取了從未去過的網站(通過搜尋引擎查到的),而這些網站包含了一種叫做網頁臭蟲的圖片,該圖片透明,且只有一個像素大小(以便隱藏),

Clean Code - 為什麼要看Clean Code?

Total Productive Maintenance, TPM (全面生產維護) 在過往日本泡沫前就是依照了TPM的概念讓工廠的產能大幅領先美國,而為什麼我們要提到TPM呢? 在過往的工廠都是有訂單就趕快用土法煉鋼的方式改裝目前的產線與機器為了能產出客戶需要的產品。在這樣的情況下,整個工廠的運作機制其實已經變成渾沌狀態,因為頻繁改變的情形下當產線掛掉停擺時要花許多時間去找到原因,而日本提出了TPM的概念後將工廠變得井然有序進而超越了美國,所以才有豐田生產管理等等專們以日本企業命名的工廠管理方法出現。 而現在的軟體設計其實也是一樣的道理,軟體迭代速度越來越快,如果開發人員只顧著往前衝刺不斷地改變,如果缺乏了有效的管理以及人員的紀律,那就可能像是滾雪球一般造成雪崩也說不定。相同類型的故事也可以透過鳳凰專案這本書一窺究竟。 回歸正題,Clean Code裡面提到的概念與方法其實就是TPM中的5S原則 5S (日語) Seiri (整理) - 好好地整理每個方法和class的命名,這樣才能讓每個團隊成員明確的知道問題在哪 Seiton (整頓) - 一段程式碼他應該出現在你所期待他出現的地方,如果不是那就是要重構了 Seiso (清掃) - 刪除那些根本沒意義的註解還有程式碼吧,讓程式碼們更好閱讀 Seiketsu (清潔) - 每天都要讓自己的工作環境標準化更清潔,讓每個成員的程式碼都用上check style吧 Shutsuke (身美) - 這也是最重要的一點,其實就是自律與反省,好好誠實的面對以前自己寫的程式碼吧 若是每次工作時都有好好遵從這5S原則,那未來產品業務大爆發或是要開發更前衛的功能時,你偷偷藏起來的雪球才不會造成雪崩讓產品一夕崩潰。 那接下來就會是我一系列的Clean Code文章(讀書心得),其實這本書我已經看過兩次,一次是碩士還在讀書時一次是工作第一年的時候,第一次看的時候其實可以說是完全看不懂(哈哈),內心想的都是為什麼要搞那麼麻煩?而第二次看的時候開始有感覺了,因為自己寫的程式碼也開始要接受挑戰已經被其他同事的程式碼挑戰,但是還是有些不得要領的地方,而這一次我決定要改變讀書行為,每到一個段落就記錄與分享,希望自己可以到另一個境界。

什麼是Database的ACID與一致性問題

目的 介紹ACID,並且針對其中的C(Consisitency)一致性提出常見的問題與解決問題的Lock用法 ACID 資料庫的ACID基本上就是四個字首的縮寫分別是 ATOMICITY CONSISTENCY ISOLATION DURABILITY 在開始進入文章前需要先講解一個概念Transaction(交易/事務),Transaction代表著你的程式在這個過程中對資料庫做的操作 舉例: 今天會員購買了這個產品,則程式會對資料庫做一系列的操作包含 新增訂單資料 新增會員與訂單的關聯資料 更新商品銷售資料 則這系列的操作可稱為一個Transaction 若是以Java Spring中的Annotation來講解的話,若在method上標記Transaction則Spring會幫助你判斷此method中對資料庫的操作都為一個Transaction。 ATOMICITY (原子性) 一個Transaction中的全部操作被視為不可分割,代表要就全部完成或是全部取消。若是其中一個環節失敗則會全部回滾(Rollback)到此資料庫Transaction前的狀態。 原子性確保了資料庫的可使用性,當然當資料不再準確時資料庫基本上也不可以使用了 CONSISTENCY (一致性) 其實目前我對於網路上一致性的解釋上有些許混亂,網路上有兩種說法可能是與CAP理論的C一起解釋了,如何選擇就由客官們判斷了 資料庫在Transaction執行後資料都必須符合schema的規範,例如要執行Trigger或是constraint(Not null/Unique) 資料庫每個Transaction讀取一個數據的解果都是一樣的 第二個說法的補充 當資料滿足了原子性與隔離性,那在同步進行Transaction時,就算其中一個Transaction 提前完成,那資料也是可以滿足一致性的 ISOLATION (隔離性) Transaction在確定提交以前,是看不到其他Transaction對這個資料的操作。 DURABILITY (持久性) 一但Transaction提交後,其作的修改將會永遠存在Database之中不能遺失 常見的一致性問題 現在各語言框架通常都已經將資料庫操作包裝好都符合ACID原則,開發者只要呼叫API即可使用,

Java Lambda Collection/List篇

Java Lambda Collection/List篇 前言 這篇文章主要接續Lambda基礎篇,主要介紹與自我複習常用的Collection家族中的Lambda方法 Collection forEach forEach 是Iterable介面中的default Method原始碼如下 default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } 敲黑板 畫重點 Collection透過FunctionalInterface "Consumer"讓此介面可以透過lambda實踐。 Collection家族都有實作Iterable介面因此都可以使用此forEach方法。 實踐 private void forExample(List<String> example) { example.forEach(System.out::println); } 透過ArrayList實踐 System.out::println省列了不帶任何參數的method ()->,讓Lambda自動對物件使用此method removeIf removeIf是Collection介面本身的方法,原始碼如下 default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove();

Java interface "Default Methods"

前言 因為近期再深入研究Java Lambda,在研究Cosumer介面實發現了一件有趣的事情,以前看Java8以前的書籍都說介面不能包含實做,而現在Java8推出了Default Methods,讓開發人員可以在介面寫上有邏輯的方法了! Default Methods 主要是透過前綴字"default",像JVM告知這一個是介面中的Default Method,範例如下 public class DefaultMethodExample { public static void main(String[] args) { DefaultInterface exampleA = new ExampleA(); DefaultInterface exampleB = new ExampleB(); exampleA.methodA(); exampleB.methodA(); } public static class ExampleA implements DefaultInterface { @Override public void methodA() { System.out.println("Hi! I am methodA in ExampleA"); basicMethod(); } } public static class ExampleB implements DefaultInterface { @Override public void methodA() { System.out.println("Hi! I am methodA in ExampleB"); basicMethod(); } } public interface DefaultInterface { void methodA(); default void ba

Java Lambda 基礎

前言 Lambda語法對我而言較像是coding風格上的改變,讓程式碼風格更加地簡潔,如果程式碼更加簡潔那就代表 更容易被管理 容易管理代表容易擴張與除錯 容易擴張除錯也代表的迭代速度加快 速度加快代表產品更容易修改去符合使用者需求 產引更容易符合使用者需求代表公司賺大錢 我真心認為許多工程師常常覺得自己只是在寫Code,其實不然他們在幫助公司創造更多的機會養活更多的家庭與製造更多生產。 當然除了上述的優點之外,現在Java社群與官方也已經環繞著Lambda進行多種開發,這也代表使用Lambda可以讓工程師們減少重複的工作(而這些重複的工作Lambda提供的效能可能還比自己寫到好…汗顏) 內容中的原始碼可以參考我的GitHub! 點我! 甚麼是Lambda 先讓我們看一下使用Lambda前後的範例 無參數 使用執行續Print出字串 private void withoutLambda() { new Thread(new Runnable() { @Override public void run() { System.out.println("Hi! This function isn't using lambda"); } }).start(); } private void withLambda() { new Thread(() -> System.out.println("Hi! This function is using lambda") ).start(); } 有參數 將較長的字串往後移動 private void hasParameter() { List<String> list = Arrays.asList("Hi", "my", "name", "is", "Charlie");

名詞解釋 FTP/sFTP(SSH)

FTP File Transfer Protocol 簡單來說就是檔案傳輸的協定,我其實常常思考甚麼是協定,直到深入理解Java interface概念後,其實協定就跟interface一樣他沒有太多的功能,他是訂出一個標準只要大家都符合這個標準那大家都可以進行傳輸。 FTP原理與應用 原理 主要透過軟體FTP client與server進行協定上的連線(可以透過許多網路資源得到相關的應用程式) 應用 對於系統整合商而言檔案傳輸幾乎是每天都在使用的,要將每個子系統的產出資料傳進中心資料倉儲,然爾每個子系統大多都是已經誕生許久不是說改就改,於是只要大家乖乖的把檔案丟到FTP server上那我們系統整合商就有辦法將資料拿出來並且整合利用。 SSH Secure Shell (安全外殼協定簡稱SSH) - 加密的網路傳輸協定,在不安全的網路中為網路服務提供安全的傳輸環境,最常見的用途是遠端登入系統 SSH的原理 SSH以非對稱加密實現身分驗證,自動生成公鑰-私鑰對來加密網路連接或是透過人工生成的方法產出公私鑰 SSH的應用 FTP -> sFTP : 將FTP協定透過SSH安全殼機制讓傳遞的檔案不會輕易的被竊取。這也是目前大多系統的做法,甚至是唯一做法。 資源 SSH - Secure Shell wiki

讓Primary Key交給JPA處理

讓Primary Key交給JPA處理 目的 透過本篇文章了解自動產生Primary Key的方法,大綱如下: GeneratedValue GenericGenerator (UUID) SequenceGenerator (透過Database的sequence) GeneratedValue快速產生Primary Key GenerateValue最快速且最常用的方法,通常是直接使用GenerateValue annotation如下就結束 @Getter @Setter @Entity @Table(name = "user") public class User { @Id @GeneratedValue private long id; private String name; } 更進一步了解,GenerateValue包含了strategy屬性,要讓他不做而外行為,自動生產的屬性有 GenerationType.IDENTITY GenerationType.AUTO 此為@GeneratedValue預設的策略參數,如沒特別設定則使用的參數就為此 注意: 不是每個資料庫都支援此功能 IDENTITY 和 AUTO 差異 GenerationType.AUTO是整個使用到此標籤的Primary key都共用一個記數器。 代表如果今天有兩個物件都自動產生Primary Key的話,當A物件產出後pk計數器則會跳到1,若是在產製B物件則此B物件的pk則會變成2,而不是從1開始。 GenerationType.IDENTITY則是使用到個別的計數器。 和上方AUTO成反例,A和B物件都會個別產出自己的計數器。 程式碼 @Data @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String name; } @Data @Entity @Table(name = "use

Git 的基本技巧

圖片
目的 每次搜尋Git指令並且看過文章後都可以快速記得,但莫名其妙的過一段時間又會回去依賴GUI介面,然而GUI介面用久了常常最根本的指令和標配的-option都會忘光光,所以透過此文紀錄常用的基本Git的指令,讓未來自己想回憶時可以快速進入狀況。 流程 通常Git的使用情境如下 文字描述 情境 : 假設今天專案要開發新的功能並且由我負責,目前整個專案只有兩個branch master develop 而討論過後決定新功能的分支要叫做new-feature,所以我的工作流程就會如下面的步驟 ( checkout ) 將目前遠端develop的程式碼拉下來 ( branch ) 建立要完成功能的new-feature分支 撰寫完程式碼 ( add ) 將更改的程式加入Git進行追蹤 ( commit ) 建立Git節點,並且加入到目前的工作區中 ( pull ) 再次將遠端開發分支的程式碼拉下來 如果有衝突則解決衝突,並且回到第四個步驟;如果沒衝突則往下 ( push ) 將節點推到遠端儲存庫中 ( merge ) 將功能分支與開發分支合併 流程圖描述 指令介紹 Checkout 將遠端的分支拉到本地端 git checkout -b <branch-name> origin/<branch-name> Pull 通常自動設定都會將remote-name設定為origin pull git pull [remote-name] <branch-name> fetch git fetch [remote-name] <branch-name> pull與fetch的差別在於,pull會直接將遠端的資料merge進你目前的工作區 簡單來說 pull = fetch + merge Branch 展示目前branch的情況 git branch -vv 直接讓遠端的branch和本地端branch作連動,連動後以後可以直接輸入git push推出程式碼 git branch -u origin/mybranch -u為 (參考 git官方網站 ) -u <upstream> –set-upstream-to=<upstream&

Java Thread和Runnable的執行差異

文章目的 了解Java多執行緒操作中,Thread和Runnable的差異 實作多個Thread 實作多個Runnable 如何實作可以參考 Java Thread的基礎實踐方法 實作多個Thread 原始碼 class MyThread extends Thread{ private int ticket = 5; public void run(){ for (int i=0;i<10;i++) { if(ticket > 0){ System.out.println("ticket = " + ticket--); } } } public static void main(String[] args){ new MyThread().start(); new MyThread().start(); new MyThread().start(); } } Result ticket = 5 ticket = 4 ticket = 3 ticket = 5 ticket = 4 ticket = 5 ticket = 3 ticket = 2 ticket = 1 ticket = 2 ticket = 4 ticket = 3 ticket = 2 ticket = 1 ticket = 1 解析 透過原始碼與結果可以看到 多執行緒的呼叫是隨機的,所以在Result階段並沒有如實的呈現規律的5~1排列 每個執行續使用的資源(ticket)都是獨一歸屬個別執行緒的。 所以假設今天的業務邏輯是,活動商要賣出五張票,如果使用了如上方一樣的三個執行緒,那結果可能會賣出15張超賣了10張 實作多個Runnable 原始碼 public class MyRunnable implements Runnable { private int ticket = 5; public void run(){ for (int i=0;i<10;i++)

Java Thread的基礎實踐方法

文章目的 讓讀者了解Java Thread的方法,目前Java Thread有三種實踐方法如下 實作Runnable介面 實作Callable介面 繼承Thread類別 實作Runnable Runnable是甚麼? Runnable是一個介面提供一個run方法,原始程式碼如下 原始碼 @FunctionalInterface public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); } 原始碼要點 @FunctinalInerface annotation是標明此介面可以透過Java8 lambda的方式去實踐 run方法沒有回傳值,代表執行後無法接收解果 實踐方法 實作runnable中的run方法,在傳入thread的建構者創建新的thread,並且執行run public class MyRunnable implements Runnable { @Override public void run() { System.out.println("Hi my name is Monster Lee");

Java List家族大解惑

前言 在學時還有工作初期,看了市面上的Java教科書發現都沒有深入探討這些List底層與關鍵要素,都只教如何使用。但這個坑常常會在面試或是追蹤效能上體現出自己的不足,所以寫一篇文章鞏固自己的觀念 目標 搞清楚List中ArrayList & LinkedList & Vector List 我目前開發最常使用的資料結構,因為ArrayList的方便性可以儲存各種物件。而真的只能用ArrayList去做這些處理嗎?如果遇到瓶頸還有甚麼解決方法呢? 接下來會以下方兩個討論去做比較 ArrayList & LinkedList ArrayList & Vector List & LinkedList 差別 實作 List的底層結構是Object陣列 LinkedList是LinkedList資料結構, 也就是在搜尋時是透過Node的連結做移動 快速隨機存取 ArrayList實作RandomAccess而LinkedList沒有 透過物件導向的概念這代表的ArrayList支持隨機存取但LinkedList沒有 LinkedList的資料結構本身是不支援隨機存取的,需要遍歷的方式才能找到元素 可以看到LinkedList原始碼繼承AbstractSequentialList就可知道它需要遍歷抓取元素 ,而ArrayList只需要給index並且直接去找出陣列中的記憶體位置就可以取得元素,可以透過下方的程式碼觀察出差別。 所以在get(index)方法中 ArrayList在正常條件下會優於LinkedList ArratList public E get(int index) { rangeCheck(index); return elementData(index); } E elementData(int index) { return (E) elementData[index]; } LinkedList public E get(int index) { checkElementIndex(index); return nod

一次搞懂POJO、PO、DTO、VO、BO

圖片
前言 在還是學生時,腦袋完全沒有所謂的Bean的觀念,直到進入職場開始使用Spring並且看到物件的命名(PO、DTO、VO、BO)才發現原來每個物件,對於他們的功能都有一個相對的命名,所以就抽空整理網路上看到的資料並且記錄下來,如果內文有錯誤的話煩請高手糾正指導。 主文 POJO (Plain Old Java Object) Martin Fowler、Rebecca Parsons和Josh MacKenzie在2000年的一次一講提出的概念,當初提出的背景是EJB過於複雜,所以想要找一個簡單的方式取代他,而現在也證明他成功了,應為套用POJO概念的Spring已經是Java不可或缺的框架。 定義 簡單並且純粹,POJO就是一個Java物件只包含自己的屬性(private)和提取或儲存這些屬性的method(get、set),而其他的Object也是以POJO為基準開始延伸。 題外話 對於一個進入正式開發階段的Java工程師在工作時常常看到Entity應該都不知道他們的正式名稱就是POJO。 下方參考 Webopedia 介紹 POJO, or Plain Old Java Object, is a normal Java object class (that is, not a JavaBean, EntityBean etc.) and does not serve any other special role nor does it implement any special interfaces of any of the Java frameworks. This term was coined by Martin Fowler, Rebbecca Parsons and Josh MacKenzie who believed that by creating the acronym POJO, such objects would have a “fancy name”, thereby convincing people that they were worthy of use. PO (persistent object) 定義 因為ORM框架的誕生所以才有PO的概念,可以簡單地將它視為資料庫table對應的