標籤

JAVA

2020-02-27

如何編寫可怕的 Java 代碼?

 

  • 1. 對一切使用異常
  • 2. 不用擔心訪問修飾符
  • 3. 在 Java 中沒有什麼是真正的 final
  • 4. 使用 Java 序列化,干就對
  • 5. 將對象用於一切
  • 6. 充分擁抱便捷編程的藝術
  • 7. 不要學習任何新知識–你總是最了解

我決定告訴你如何編寫可怕的Java代碼。如果你厭倦了所有這些美麗的設計模式和最佳實踐,並且想寫些瘋狂的東西,請繼續閱讀。

如果你正在尋找有關如何編寫良好代碼的建議,請查看其它文章!

1. 對一切使用異常

你知道循環對嗎?差一錯誤(英語:Off-by-one error,縮寫 OBOE,是在計數時由於邊界條件判斷失誤導致結果多了一或少了一的錯誤,通常指計算機編程中循環多了一次或者少了一次的程序錯誤,屬於邏輯錯誤的一種)很容易犯。當你迭代一個集合時,很容易出錯。讓我們看看如何使用 Java 異常處理來解決該問題,而不用擔心這些討厭的差一錯誤!

public static void horribleIteration(String [] words){
    int i = 0;
    try {
        while(true){
            System.out.println(words[i]);
            i++;
        }
    } catch (IndexOutOfBoundsException e){
        //iteration complete
    }
}

2. 不用擔心訪問修飾符

你說什麼?Java 中的訪問修飾符,這不是浪費時間嘛!你是否知道將屬性/方法等設為私有隻是一個建議?如果你想修改它,那就去做吧!沒什麼能阻止你(除了缺乏知識之外)。如果是這種情況,請看如下代碼。

public static void readPrivate() throws NoSuchFieldException, IllegalAccessException {
    Field f = System.class.getDeclaredField("lineSeparator");
    f.setAccessible(true);
    String separator = (String) f.get(System.class);
    System.out.println("Line separator is " + separator + ".");
}

我們在這裡讀取 lineSeparator,這並沒有什麼。但是修改 lineSeparator 會帶來更多樂趣!在我們修改代碼中的 lineSeparator 之後,看看 System.out.println 發生了什麼:

public static void readWritePrivate() throws NoSuchFieldException, IllegalAccessException {
    Field f = System.class.getDeclaredField("lineSeparator");
    f.setAccessible(true);
    String separator = (String) f.get(System.class);
    System.out.println("Line separator is " + separator + ".");

    f.set(System.class ,"!!!");
    System.out.println("Line one");
    System.out.println("Line two");
    System.out.println("Line three");
}

輸出為:

Line separator is
WARNING: All illegal access operations will be denied in a future release
.
Line one!!!Line two!!!Line three!!!

看起來不錯!

3. 在 Java 中沒有什麼是真正的 final

一些開發人員認為他們通過將 final 關鍵字放在變數前面來以說明不會去更改這個值。事實是——有時候你真的想要改變一個 final 欄位的值,所以這是如何做的:

public static void notSoFinal() throws NoSuchFieldException, IllegalAccessException, InterruptedException {
    ExampleClass example = new ExampleClass(10);
    System.out.println("Final value was: "+ example.finalValue);
    Field f = example.getClass().getDeclaredField("finalValue");
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
    f.setInt(example, 77);
    System.out.println("Final value was: "+ example.finalValue);
}

public static class ExampleClass {
    final int finalValue;

    public ExampleClass(int finalValue){
        this.finalValue = finalValue;
    }
}

注意,在構造函數中提供最終值時,這對我很有用。如果你在類中設置了 final 值,那麼它將不起作用。(可能是一些編譯器級別的優化破壞了所有的樂趣)

4. 使用 Java 序列化,干就對

這很簡單,用 Java 序列化,玩得開心,好好享受。

好吧,我想你想要一些理由。我看到 Java 平台首席架構師 Mark Reinhold 表示,他們後悔將序列化引入到 Java。顯然,Java 中大約 1/3 的安全漏洞僅來自於序列化。

5. 將對象用於一切

你知道類嗎?浪費時間!你是否想看到代碼重用的巔峰之作?你去!

public static void printThings (List things){
    int i = 0;
    try {
        while(true){
            System.out.println(things.get(i));
            i++;
        }
    } catch (IndexOutOfBoundsException e){
        //iteration complete
    }
}

List superList = new ArrayList();
superList.add(7);
superList.add("word");
superList.add(true);
superList.add(System.class);
printThings(superList);

您可以相信我們一直以來都擁有這種力量嗎?另外,組合兩個模式還有額外的好處!

這只是你使用 Object 進行操作的開始。如果有疑問,請記住-使用對象。如果需要,你隨時可以使用這種驚人的模式進行回退!

public static void printThingsUppercaseStrings (List things){
    int i = 0;
    try {
        while(true){
            Object o = things.get(i);
            System.out.println(o);
            if(o.getClass() == String.class){
                String so = (String) o;
                so = so.toUpperCase();
                System.out.println(so);
            }
            i++;
        }
    } catch (IndexOutOfBoundsException e){
        //iteration complete
    }
}

這還是類型安全的,多麼健壯的解決方案。

6. 充分擁抱便捷編程的藝術

你知道比爾·蓋茨更喜歡懶惰的開發人員嗎?比爾·蓋茨說過:

“I will always choose a lazy person to do a difficult job…because, he will find an easy way to do it. –Bill Gates”

“我總是會選擇一個懶人去完成一份困難的工作…因為,他會找到捷徑。” — 比爾蓋茨

因此,有了比爾·蓋茨(Bill Gates)的大力支持,我們可以完全接受我們的懶惰。你準備好了嗎?那就開始吧!

  • 永遠不要編寫測試,只是不要編寫錯誤!
  • 將所有都定義為 public -方便訪問!
  • 支持全局變數–您可能需要它們!
  • 大型介面優於小型專用介面–可以使用的方法越多越好!
  • 支持繼承而不是合成(使用介面中的默認方法從未如此簡單)!
  • 始終使用裝箱類型–它們也可以用作對象!
  • 儘可能使用最短的名字(a, b, n 最好)!

7. 不要學習任何新知識–你總是最了解

一個程序員最重要的品質就是對自己有信心。相信自己什麼都懂,沒有什麼可學的!

考慮到這一點,請確保不要學習:

  • 新類庫
  • 新語言
  • 新框架

這樣可以節省你的時間!你永遠都不應學習任何新知識,因為你已經是最好的了。

你有能力去做這件事,並不代表你應該做



2020-02-25

Java 14 令人期待的 5 大新特性,打包工具終於要來了!

  • 1. instanceof 模式匹配
  • 2. 文本塊再次作為預覽特性保留
  • 3. 記錄類型(Record Type)的引入
  • 4. 打包工具終於來了
  • 5. 一個組合垃圾收集器被棄用
  • 6. 結束語

隨著新的 Java 發布生命周期的到來,新版本預計將於 2020 年 3 月發布,本文將對其中的 5 個主要特性作些概述。

Java 13 剛剛發布給開發人員使用不久,最新版本的JDK於2019年9月發布。但是很少有公司現在改用了Java 13 ,因為這個版本看起來無論如何都不會從甲骨文公司獲得長期支持(LTS)。更不要說現在Java 14又已經出現了。

隨著新的Java發布生命周期的到來,新的Java版本預計將於2020年3月發布。時間已經所剩不多了,這就是為什麼甲骨文公司的Java首席架構師Mark Reinhold剛剛提出應該將JDK增強提案(JEP)中的5個主要特性包含進Java 14中的原因。

因此,在這篇文章里我將對這5個主要特性作些概述。這些特性應該作為Java 14的一部分,以便它們可以從2020年3月起提供給開發人員使用。

1. instanceof 模式匹配

作為預覽模式提供的這個新特性旨在通過向用戶提供instanceof操作符的模式匹配來改進Java。

模式匹配在其他語言中已經出現,它使得以一種更安全和更簡潔的方式來表達程序邏輯成為可能。

instanceof操作符的模式匹配將有助於從對象中有條件地提取組件。

在大多數Java程序中,都有下面這種類型的代碼:

if (obj instanceof Integer) {
    int intValue = (Integer) obj;
    // ... use intValue ...
}

在這段代碼中,我們通過instanceof運算符來檢查obj變數是否是Integer的實例。如果條件為真的話,我們不能將obj直接作為一個整數變數使用,因為必須首先對它進行轉換。

上面的代碼不簡潔,也不是很清晰。此外,在程序中重複這種類型的構造會增加出錯的風險。

而作為預覽狀態在Java 14中引入的instanceof操作符的模式匹配將允許對上述代碼作如下簡化:

if (x instanceof Integer i) {
    // ... use i as an Integer directly ...
}

在下面更複雜的例子中,我們可以更加理解Java 14中可以做到什麼:

String formatted = "unknown";if (obj instanceof Integer i) {
    formatted = String.format("int %d", i);
}
else if (obj instanceof Byte b) {
    formatted = String.format("byte %d", b);
}
else if (obj instanceof Long l) {
    formatted = String.format("long %d", l);
}
else if (obj instanceof Double d) {
    formatted = String.format(「double %f", d);
}
else if (obj instanceof String s) {
    formatted = String.format("String %s", s);
}// ... use formatted variable ...

這個例子中最有趣的地方是instanceof模式匹配可以擴展到其他的語法結構中。首先,我們應該可以想到switch表達式。

在未來的Java 15、16或17中,我們可以想象用以下的代碼替換先前的if/else序列是可能的:

String formatted =
    switch (obj) {
        case Integer i -> String.format("int %d", i);
        case Byte b -> String.format("byte %d", b);
        case Long l -> String.format("long %d", l);
        case Double d -> String.format("double %f", d);
        case String s -> String.format("String %s, s);
        default -> String.format("Object %s", obj);
    };// ... use formatted variable

2. 文本塊再次作為預覽特性保留

文本塊(Text Block)在Java 13 中作為預覽特性引入,在Java 14中再次作為預覽特性保留下來。

鑒於在Java 13 發布之後從各大Java社區收集上來的反饋,對文本塊添加了兩個新的轉義序列。

轉義序列符「/」顯式地消除了插入新行字元的需要。以下面這個使用位於小字元串之間的連接運算符「+」來拆分較大字元串的例子為例:

String literal = "This is a string splitted " +
                 "in several smaller " +
                 "strings.";

使用轉義序列符「/」,在Java 14中我們可以像下面這樣來改寫上面的代碼:

String text = """
                This is a string splitted /
                in several smaller /
                strings./
                """;

由於字元文本和傳統字元串文本不允許嵌入換行符,因此轉義序列符「/」僅適用於文本塊。

另一方面,新的轉義序列符「/s」可以被轉換為一個簡單的空白。這樣可以防止空白字元被清除掉。

基於這個轉義序列符,我們可以構建一個字元串,確保每一行的長度相同:

String colors = """
red /s
green/s
blue /s
""";

注意:這個將在Java 14中引入的新轉義序列符(/s)也可以用於傳統的字元串文本。

3. 記錄類型(Record Type)的引入

Java 14中應該可以看到記錄類型(Record Type)作為預覽特性被引入。記錄對象允許使用緊湊的語法來聲明類,而這些類是淺不變數據的透明持有者。

和枚舉類型一樣,記錄也是類的一種受限形式。記錄聲明其表示並提交到與此表示相對應的API。記錄對象放棄了Java類從中受益的自由:也就是將API和其表示分離的能力。作為回報,記錄對象在簡潔性方面提供了顯著的好處。

記錄對象擁有一個名字和一個聲明其組件的狀態描述。記錄對象的主體(body)是可選的。下面是創建一個記錄對象Point的例子:

record Point(int x, int y) { }

這個寫法相當於下面的類聲明:

final class Point {
    public final int x;
    public final int y;


    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }


    // state-based implementations of equals, hashCode, toString
    // nothing else
}

為了在Java 14中引入這種新類型,需要在Java.lang.Class對象中添加如下兩個新方法:

RecordComponent[] getRecordComponents()
boolean isRecord()

這兩個方法的目的是更新Java Reflection API,以便將記錄類型納入其中。

4. 打包工具終於來了

Java 13 發布前的最後一刻被從外圍移除的打包工具jpackage終於可以在Java 14中使用了。但是要注意,它只在Incubator版本中提供。

這個打包工具應該可以讓開發人員創建自主的Java應用程序,它以JavaFX javapackager這個打包工具為基礎。它的主要特點有如下三個:

  • 支持本地打包格式,為用戶提供自然的安裝體驗;
  • 打包時可以指定啟動參數;
  • 通過命令行或使用ToolProvider API的程序來啟動。

5. 一個組合垃圾收集器被棄用

Java 14中令人期待的最新創新顯然不是針對所有Java開發人員的,實際上,它打算棄用ParallelScavenge + SerialOld垃圾收集器組合。

支持這一改變的JEP 366清楚地表明,他們的目的不是要刪除掉這個組合,而是要棄用它。

棄用這種演算法組合的原因是:它很少被使用,同時需要大量的維護工作。

6. 結束語

預定於2020年3月發布的Java 14,對Java開發人員的日常工作影響相對較小。最前沿的新特性是instanceof的模式匹配,這是大多數開發人員都渴望嘗試的新特性。

但是,在生產環境中使用此特性之前,你必須要有耐心,因為它們在Java 14中僅僅作為預覽特性出現。

好消息是,instanceof的模式匹配代表了在Java 15、16或17中進行更廣泛的模式匹配的第一步。

所有這些改變都讓開發人員感到非常高興,因為他們所有人將在程序的可讀性和個人的開發效率方面獲得顯著的收益。title: Java 14 令人期待的 5 大新特性,打包工具終於要來了!date: 2020-03-10
tags:
categories: 精進
permalink: Fight/
author: CSDN 翻譯,譯者:蘇本如
from_url: medium.com/better-programming/top-5-new-features-expected-in-java-14-82c0d85b295e
wechat_url:


隨著新的 Java 發布生命周期的到來,新版本預計將於 2020 年 3 月發布,本文將對其中的 5 個主要特性作些概述。

Java 13 剛剛發布給開發人員使用不久,最新版本的JDK於2019年9月發布。但是很少有公司現在改用了Java 13 ,因為這個版本看起來無論如何都不會從甲骨文公司獲得長期支持(LTS)。更不要說現在Java 14又已經出現了。

隨著新的Java發布生命周期的到來,新的Java版本預計將於2020年3月發布。時間已經所剩不多了,這就是為什麼甲骨文公司的Java首席架構師Mark Reinhold剛剛提出應該將JDK增強提案(JEP)中的5個主要特性包含進Java 14中的原因。

因此,在這篇文章里我將對這5個主要特性作些概述。這些特性應該作為Java 14的一部分,以便它們可以從2020年3月起提供給開發人員使用。

1. instanceof 模式匹配

作為預覽模式提供的這個新特性旨在通過向用戶提供instanceof操作符的模式匹配來改進Java。

模式匹配在其他語言中已經出現,它使得以一種更安全和更簡潔的方式來表達程序邏輯成為可能。

instanceof操作符的模式匹配將有助於從對象中有條件地提取組件。

在大多數Java程序中,都有下面這種類型的代碼:

if (obj instanceof Integer) {
    int intValue = (Integer) obj;
    // ... use intValue ...
}

在這段代碼中,我們通過instanceof運算符來檢查obj變數是否是Integer的實例。如果條件為真的話,我們不能將obj直接作為一個整數變數使用,因為必須首先對它進行轉換。

上面的代碼不簡潔,也不是很清晰。此外,在程序中重複這種類型的構造會增加出錯的風險。

而作為預覽狀態在Java 14中引入的instanceof操作符的模式匹配將允許對上述代碼作如下簡化:

if (x instanceof Integer i) {
    // ... use i as an Integer directly ...
}

在下面更複雜的例子中,我們可以更加理解Java 14中可以做到什麼:

String formatted = "unknown";if (obj instanceof Integer i) {
    formatted = String.format("int %d", i);
}
else if (obj instanceof Byte b) {
    formatted = String.format("byte %d", b);
}
else if (obj instanceof Long l) {
    formatted = String.format("long %d", l);
}
else if (obj instanceof Double d) {
    formatted = String.format(「double %f", d);
}
else if (obj instanceof String s) {
    formatted = String.format("String %s", s);
}// ... use formatted variable ...

這個例子中最有趣的地方是instanceof模式匹配可以擴展到其他的語法結構中。首先,我們應該可以想到switch表達式。

在未來的Java 15、16或17中,我們可以想象用以下的代碼替換先前的if/else序列是可能的:

String formatted =
    switch (obj) {
        case Integer i -> String.format("int %d", i);
        case Byte b -> String.format("byte %d", b);
        case Long l -> String.format("long %d", l);
        case Double d -> String.format("double %f", d);
        case String s -> String.format("String %s, s);
        default -> String.format("Object %s", obj);
    };// ... use formatted variable

2. 文本塊再次作為預覽特性保留

文本塊(Text Block)在Java 13 中作為預覽特性引入,在Java 14中再次作為預覽特性保留下來。

鑒於在Java 13 發布之後從各大Java社區收集上來的反饋,對文本塊添加了兩個新的轉義序列。

轉義序列符「/」顯式地消除了插入新行字元的需要。以下面這個使用位於小字元串之間的連接運算符「+」來拆分較大字元串的例子為例:

String literal = "This is a string splitted " +
                 "in several smaller " +
                 "strings.";

使用轉義序列符「/」,在Java 14中我們可以像下面這樣來改寫上面的代碼:

String text = """
                This is a string splitted /
                in several smaller /
                strings./
                """;

由於字元文本和傳統字元串文本不允許嵌入換行符,因此轉義序列符「/」僅適用於文本塊。

另一方面,新的轉義序列符「/s」可以被轉換為一個簡單的空白。這樣可以防止空白字元被清除掉。

基於這個轉義序列符,我們可以構建一個字元串,確保每一行的長度相同:

String colors = """
red /s
green/s
blue /s
""";

注意:這個將在Java 14中引入的新轉義序列符(/s)也可以用於傳統的字元串文本。

3. 記錄類型(Record Type)的引入

Java 14中應該可以看到記錄類型(Record Type)作為預覽特性被引入。記錄對象允許使用緊湊的語法來聲明類,而這些類是淺不變數據的透明持有者。

和枚舉類型一樣,記錄也是類的一種受限形式。記錄聲明其表示並提交到與此表示相對應的API。記錄對象放棄了Java類從中受益的自由:也就是將API和其表示分離的能力。作為回報,記錄對象在簡潔性方面提供了顯著的好處。

記錄對象擁有一個名字和一個聲明其組件的狀態描述。記錄對象的主體(body)是可選的。下面是創建一個記錄對象Point的例子:

record Point(int x, int y) { }

這個寫法相當於下面的類聲明:

final class Point {
    public final int x;
    public final int y;


    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }


    // state-based implementations of equals, hashCode, toString
    // nothing else
}

為了在Java 14中引入這種新類型,需要在Java.lang.Class對象中添加如下兩個新方法:

RecordComponent[] getRecordComponents()
boolean isRecord()

這兩個方法的目的是更新Java Reflection API,以便將記錄類型納入其中。

4. 打包工具終於來了

Java 13 發布前的最後一刻被從外圍移除的打包工具jpackage終於可以在Java 14中使用了。但是要注意,它只在Incubator版本中提供。

這個打包工具應該可以讓開發人員創建自主的Java應用程序,它以JavaFX javapackager這個打包工具為基礎。它的主要特點有如下三個:

  • 支持本地打包格式,為用戶提供自然的安裝體驗;
  • 打包時可以指定啟動參數;
  • 通過命令行或使用ToolProvider API的程序來啟動。

5. 一個組合垃圾收集器被棄用

Java 14中令人期待的最新創新顯然不是針對所有Java開發人員的,實際上,它打算棄用ParallelScavenge + SerialOld垃圾收集器組合。

支持這一改變的JEP 366清楚地表明,他們的目的不是要刪除掉這個組合,而是要棄用它。

棄用這種演算法組合的原因是:它很少被使用,同時需要大量的維護工作。

6. 結束語

預定於2020年3月發布的Java 14,對Java開發人員的日常工作影響相對較小。最前沿的新特性是instanceof的模式匹配,這是大多數開發人員都渴望嘗試的新特性。

但是,在生產環境中使用此特性之前,你必須要有耐心,因為它們在Java 14中僅僅作為預覽特性出現。

好消息是,instanceof的模式匹配代表了在Java 15、16或17中進行更廣泛的模式匹配的第一步。

所有這些改變都讓開發人員感到非常高興,因為他們所有人將在程序的可讀性和個人的開發效率方面獲得顯著的收益。



2020-02-22

Vert.x!這是目前最快的 Java 框架

如果您搜索「最佳網路框架 」,您可能會偶然發現Techempower基準測試,其中排名超過300個框架,在那裡你可能已經注意到Vert.x是排名最高的。

Vert.x是一個多語言 Web 框架,它支持Java ,Kotlin,Scala,Ruby和Javascript支持的語言之間的共同功能。無論語言如何,Vert.x都在Java虛擬機(JVM)上運行。模塊化和輕量級,它面向微服務開發。

Techempower基準測試衡量從資料庫更新,獲取和交付數據的性能。每秒提供的請求越多越好。在這種涉及很少計算的IO場景中,任何非阻塞框架都會有優勢。近年來,這種範式幾乎與Node.js不可分割,Node.js通過其單線程事件循環來推廣它。

與Node類似,Vert.x運行單個事件循環。但Vert.x也利用了JVM。Node運行在單個核心上,而Vert.x維護的線程池大小可以與可用核心數相匹配。憑藉更強的併發支持,Vert.x不僅適用於IO,也適用於需要并行計算的CPU繁重流程。

然而,事件循環只是故事的一半。另一半與Vert.x幾乎沒有關係。Java必備的 15 個框架,推薦看下。

要連接到資料庫,客戶端需要連接器驅動程序。在Java領域,Sql最常見的驅動程序是JDBC。問題是,這個驅動程序阻塞了。它在套接字級別阻塞。一個線程總會卡在那裡,直到它返回一個響應。

毋庸置疑,驅動程序一直是實現完全無阻塞應用程序的瓶頸。幸運的是,在具有多個活動分叉的非同步驅動程序上取得了進展(儘管是非官方的),其中包括:

  • https://github.com/jasync-sql/jasync-sql(適用於Postgres和MySql)
  • https://github.com/reactiverse/reactive-pg-client(Postgres)

黃金法則

使用Vert.x非常簡單,只需幾行代碼即可啟動http伺服器。

val vertx = Vertx.vertx()
vertx.createHttpServer().requestHandler(req => {

}).listen(8080)

方法requestHandler是事件循環傳遞請求事件的地方。由於Vert.x沒有意見,處理它是自由的風格。但請記住非阻塞線程的唯一重要規則:不要阻止它。

在使用併發時,我們可以從如今的許多選項中獲取,例如Promise,Future,Rx,以及Vert.x自己的慣用方法。但隨著應用程序複雜性的增加,單獨使用非同步功能是不夠的。我們還需要輕鬆協調和鏈接調用,同時避免回調地獄,以及優雅地傳遞任何錯誤。

Scala Future滿足上述所有條件,並具有基於函數式編程原理的額外優勢。雖然本文不深入探討Scala Future,但我們可以通過一個簡單的應用程序來嘗試它。

假設該應用程序是一個API服務,用於查找給定其ID的用戶:

val vertx = Vertx.vertx()
vertx.createHttpServer().requestHandler(req => {

req.path() match {
  case p if p contains("/user") =>
  val f = for {
    f1 <- Future { req.getParam("id").get.toInt }
    f2 <- if (f1 < 100) Future.unit else Future.failed(CustomException())
    f3 <- Future { getUserFromDb(f1) }
  } yield f3
  f map (r => printout(req, r)) recover {case exception => printout(req, handleException(exception))}

  case _ => printout(req, "Default page")
}

})
.listen(8080)

def printout(req: HttpServerRequest, msg: String) = req.response().end(msg)

def handleException(e: Throwable): String = {
e match {
  case t: NoSuchElementException => "Missing parameter"
  case t: NumberFormatException => "Parameter not number"
  case t: CustomException => "Custom exception"
  case t: SQLException => "Database error"
  case _ => "Unknown error"
}
}

def getUserFromDb(id: Int) = "mock user name"

case class CustomException() extends Exception("custom exception")

涉及三個操作:檢查請求參數,檢查id是否有效以及獲取數據。我們將把這些操作包裝在Future中,並在「for comprehension」結構中協調執行。

第一步是將請求與服務匹配。

Scala具有強大的模式匹配功能,我們可以將其用於此目的。在這裡,我們攔截任何提及「/ user」並將其傳遞給我們的服務。

接下來是這項服務的核心,我們的期貨按順序排列。

第一個furture 未來f1包裝參數檢查。我們特別想從get請求中檢索id並將其轉換為int。(如果返回值是方法中的最後一行,Scala不需要顯式返回。)如您所見,此操作可能會拋出異常,因為id可能不是int或甚至不可用,但現在可以。

第二個furture f2檢查id的有效性。

我們通過使用我們自己的CustomException顯式調用Future.failed來阻止任何低於100的id。否則,我們以Future.unit的形式傳遞一個空的Future作為成功驗證。

最後的furture f3將使用f1提供的id檢索用戶。

由於這只是一個示例,我們並沒有真正連接到資料庫。我們只返回一些模擬字元串。

map運行從f3生成用戶數據的排列,然後將其列印到響應中。

現在,如果在序列的任何部分發生錯誤,則傳遞Throwable進行恢復。

在這裡,我們可以將其類型與合適的恢復策略相匹配。回顧一下我們的代碼,我們已經預料到了幾個潛在的失敗,例如缺少id,或者id不是int或者無效會導致特定異常。我們通過向客戶端傳遞錯誤消息來處理handleException中的每一個。

這種安排不僅提供從開始到結束的非同步流程,還提供處理錯誤的乾淨方法。由於它是跨處理程序的簡化,我們可以專註於重要的事情,如資料庫查詢。

Verticles,Event Bus和其他陷阱

Vert.x還提供了一個名為verticle的併發模型,類似於Actor系統。Verticle隔離其狀態和行為以提供線程安全的環境。與之通信的唯一方法是通過事件匯流排。

但是,Vert.x事件匯流排要求其消息為String或JSON。

這使得傳遞任意非POJO對象變得困難。在高性能系統中,處理JSON轉換是不可取的,因為它會帶來一些計算成本。如果您正在開發IO應用程序,最好不要使用Verticle或事件匯流排 ,因為這樣的應用程序幾乎不需要本地狀態。

使用某些Vert.x組件也非常具有挑戰性。

您可能會發現缺少文檔,意外行為甚至無法正常運行。Vert.x可能正在遭受其雄心壯志,因為開發新組件需要移植多種語言。這是一項艱巨的任務。因此,堅持核心將是最好的。

如果您正在開發公共API,那麼vertx-core就足夠了。如果它是一個Web應用程序,您可以添加vertx-web,它提供http參數處理和JWT / Session身份驗證。

無論如何,這兩個是主導基準的。在使用vertx-web的一些測試中,性能有所下降,但由於它似乎源於優化,因此可能會在後續版本中得到解決。



2020-02-22

在boss上更新簡歷后,找上門的全是外包…什麼情況?

你是否有過這麼一段經歷,一直做著OA,CRM管理系統等傳統項目,簡歷技能開頭第一行,基本都是「Java基礎紮實」,然後下面接著就是熟悉XXX。然後不斷列名詞,舉例一下:

  • Java基礎紮實
  • 熟悉Mysql…
  • 熟悉Redis…
  • 熟悉HTML/CSS/JS…
這個,是否就是你的簡歷套路???

但是你發現,這樣的簡歷,沒有絲毫亮點,收到的面試機會更是少得可憐,而且還是低質量的外包居多。

於是,你就看了一些書,加上了一些高大上的名詞來修飾,比如JVM調優、分散式事務、分散式鎖、分散式作業等。

這樣一來面試是有了,可是面試官一上來,就一頓連環問!

 你說你有做過JVM調優,那你說下你們線上都設置了哪些JVM參數?GC日誌怎麼看,怎麼調優?

你說你們用了分散式事務,在哪個業務場景用的?對於TCC和可靠消息最終一致性,怎麼選擇?可靠消息,是怎麼保證可靠的?

分散式鎖有哪些方案,ZK和Redis你的選擇是基於什麼業務場景考慮的?分散式鎖續期問題有沒有考慮過啊?

 為什麼要用到分散式作業?有沒有遇到過什麼坑啊?

當然,最後面試還是失敗了…
從這裡可以看出,現在面試越來越難,已經不是簡簡單單看看書,掌握點簡單的理論就能通過了,更多的是考察一些開放性的問題,比如「有沒有遇到一些坑」之類的。

也許你會說,要遇到坑,也要有實戰場景,你不讓我通過面試,進公司實戰,哪來的實戰經驗。話雖如此,但是實際情況我們也要接受!
道理其實大家都知道,但是實施起來就遇到了問題,所以這裡我推薦最簡單的方式:

2020-02-07

2019 年最受歡迎的 JVM 配置參數是怎樣的?

以下是 JVM 常見十大配置參數:

1.-Xms初始堆大小。只要啟動,就佔用的堆大小。

2.-Xmx最大堆大小。java.lang.OutOfMemoryError:Java heap這個錯誤可以通過配置-Xms和-Xmx參數來設置。

3.-Xss棧大小分配。棧是每個線程私有的區域,通常只有幾百K大小,決定了函數調用的深度,而局部變數、參數都分配到棧上。

當出現大量局部變數,遞歸時,會發生棧空間OOM(java.lang.StackOverflowError)之類的錯誤。

4.XX:NewSize:設置新生代大小的絕對值。

5.-XX:NewRatio設置年輕代和年老代的比值。比如設置為3,則新生代:老年代=1:3,新生代佔總heap的1/4。

6.-XX:MaxPermSize:設置持久代大小。

java.lang.OutOfMemoryError:PermGenspace這個OOM錯誤需要合理調大PermSize和MaxPermSize大小。

7.-XX:SurvivorRatio:年輕代中Eden區與兩個Survivor區的比值。注意,Survivor區有form和to兩個。比如設置為8時,那麼eden:form:to=8:1:1。

8.-XX:HeapDumpOnOutOfMemoryError:發生OOM時轉儲堆到文件,這是一個非常好的診斷方法。

9.-XX:HeapDumpPath:導出堆的轉儲文件路徑。

10.-XX:OnOutOfMemoryError:OOM時,執行一個腳本,比如發送郵件報警,重啟程序。後面跟著一個腳本的路徑。