Java 9 新功能之 HTTP2 和 REPL

對Java 9的炒作將不再局限于模塊化(modularity),Java 9正在搜羅大量額外的功能模塊,這些功能模塊正作為Java增強提案(JEP)提交,并在OpenJDK (Java SE的參考實現項目)中實現。

在這篇文章中,我們將重點關注一些或將在Java 9整個生命周期中,對開發者的工作生活影響最大的JEP,包括新的HTTP/2支持和JShell REPL(讀取-求值-打印-循環),后者帶來了基于shell的交互式Java開發環境和探索性開發API。
HTTP/2

HTTP/2標準是HTTP協議的最新版本。當前版本HTTP/1.1始于1999年,存在著非常嚴重的問題,包括:

對頭阻塞

在HTTP/1.1中,響應接收的順序和請求發送的順序相同。這意味著,例如,當查看一個包含許多小圖像的大HTML頁面時,圖像資源將不得不在 HTML頁面資源之后排隊,在瀏覽器完全加載完HTML頁面之前,圖像資源無法被發送。這就是“對頭阻塞”,會導致許多潛在的頁面渲染問題。

在HTTP/2中,響應數據可以按塊(chunk)傳輸,甚至可以交叉傳輸,因此真正實現了請求和響應的多路復用。

一個站點的連接數限制

在HTTP/1.1標準中有這樣的描述:“一個單用戶的客戶端不能與任何服務器保持2個以上的連接”。這個限制和對頭阻塞問題一起,嚴重限制了頁面的性能。

HTTP/2打破這種限制并認為連接是持久的,只有當用戶跳轉后或者發生技術性故障事件時,連接才會關閉。對多路復用的使用將有助于降低頁面性能瓶頸。

HTTP控制頭的開銷

當前的HTTP版本使用簡單的、基于文本的HTTP頭信息來控制通信。這樣做的優點是非常簡單且易于理解,調試也很簡單,只需通過連接指定端口并輸 入一些文本。然而,使用基于文本的協議會讓小的響應包不成比例地膨脹。此外,大量的HTTP響應幾乎沒有或者根本沒有有效負載(比如,HEAD請求只是要 確定資源是否發生變化)。為實際上只包含最后修改時間的響應,使用完全基于文本的頭信息(大約有700個字節,在HTTP1.1中,它們不能被壓縮,盡管 很容易做到)是當前HTTP標準中,不可思議的浪費。

另一個思路是對HTTP頭信息使用二進制編碼。這種方式能夠極大地提高較小請求的速度且占用的網絡帶寬非常小。這正是HTTP/2已經選擇的方法,雖然以協議精神制定標準應該選擇基于文本的協議,但是二進制的效率有令人信服的理由,讓我們這樣做。

HTTP/2帶來的期望

HTTP/2 標準是由 IETF HTTP工作組創建的,該組織由來自 Mozilla、Google、 Microsoft、Apple,以及其他公司的代表和工程師組成,由來自CDN領軍公司Akamai的高級工程師Mark Nottingham任主席。因此,HTTP/2是一個為優化大型、高流量的網站而生的版本,它在實現簡單、易于調試的基礎上,確保了性能和網絡帶寬消 耗。

該組織主席總結了一些HTTP/2的關鍵屬性:

相同的HTTP API

成本更低的請求

網絡和服務器端友好

緩存推送

思維革命

更多加密方式

帶給Java的意義

自從1.0版本開始,Java就支持HTTP,但是多數代碼出自完全不同的時代。例如,Java對HTTP的支持是圍繞相對協議無關的框架(URL類)設計的,因此在網站成為主導地位的90年代,這種實現顯得很不清晰。

Java對HTTP的支持是基于當時最好的設計思想,但是時過境遷,最重要的是Java對HTTP原始的支持出來時,HTTPS還沒有出現。因此,Java的API將HTTPS作為一種移花接木,導致了不能簡化的復雜性。

在現代社會,HTTPS開始變得無所不在,讓HTTP日漸成為落后的技術。甚至,美國政府現在都通過了完全遷到HTTPS-only的計劃。

JDK內核對HTTP的支持已經無法跟上現實網絡的發展步伐。實際上,甚至JDK8也只不過是交付了一個支持HTTP/1.0的客戶端,然而,大多數的開發者早已轉而使用第三方客戶端庫了,比如Apache的HttpComponents。

所有這一切意味著,對HTTP/2的支持將是Java未來十年的核心功能。這也讓我們重新審視我們的固有思維,重新寫一套API并提供重新來過的機會。HTTP/2將是未來數年內,每位開發者主要面對的API。

新的API不再堅持協議中立性,使開發者可以完全拋棄過去的使用方式。這套API只關注HTTP協議,但是要進一步理解的是HTTP/2并沒有從根本上改變原有的語義。因此,這套API是HTTP協議獨立的,同時提供了對新協議中幀和連接處理的支持。

在新的API中,一個簡單的HTTP請求,可以這樣創建和處理:

HttpResponse response = HttpRequest.create(new URI("http://www.infoq.com")).body(noBody()).GET().send();int responseCode = response.responseCode();String responseBody = response.body(asString());System.out.println(responseBody);

這種符合流暢風格/建造者模式(fluent/builder)的API,與現存的遺留系統相比,對開發者來說,更具現代感和舒適感。

雖然當前的代碼庫只支持HTTP/1.1,但是已經包含了新的API。這使得在對HTTP/2支持完成對過程中,開發者可以實驗性地使用和驗證新的API。

相關代碼已經進入OpenJDK沙箱倉庫中,并很快登陸JDK 9的主干。到那個時候,新的API將開始自動構建到Oracle的二進制beta版本中。現在,對HTTP/2的支持已經可用,并將在未來數月內最終完成。

在此期間,你可以使用Mercurial遷出源代碼,并根據AdoptOpenJDK構建指導編譯你遷出地代碼,這樣你就可以實驗性地使用新的API了。

第一批完成的功能之一是當前版本力不能及的異步API。這個功能讓長期運行的請求,可以通過sendAsync()方法,切換到VM

管理的后臺線程中:

HttpRequest req = HttpRequest.create(new URI("http://www.infoq.com")).body(noBody()).GET();CompletableFuture<HttpResponse> aResp = req.sendAsync();Thread.sleep(10);if (!aResp.isDone()) {aResp.cancel(true);System.out.println("Failed to reply quickly...");return;}HttpResponse response = aResp.get();

相比HTTP/1.1的實現,新的API帶給開發者最多的是方便性,因為HTTP/1.1沒有提供對已經發送到服務器端的請求的取消機制,而HTTP/2可以讓客戶端向已經被服務器端處理的請求,發送取消命令。

JShell

很多語言都為探索性開發提供了交互式環境。在某些情況下(特別是Clojure和其他Lisp方言),交互式環境占據了開發者的大部分編碼時間,甚至是全部。其他語言,比如Scala或者JRuby也廣泛使用REPL。

當然,此前Java曾經推出過Beanshell腳本語言,但是它沒有實現完全標準化,而且近年來,該項目已經處于不活躍狀態。在Java 8(以及jjs REPL)中引入的Nashorn Javascript實現打開了更廣泛地考慮REPL并將交互式開發成為可能的大門。

一項努力將現代REPL引入Java 9的工作,以JEP 222作為開始,收錄在OpenJDK的Kulla項目中。Kulla這個名字來自古巴比倫神話,是建造之神。該項目的主旨是提供最近距離的“完整 Java”體驗。該項目沒有引入新的非Java語義,并禁用了Java語言中對交互式開發沒有用處的語義(比如上層的訪問控制修改或同步的語義)。

與所有REPL一樣,JShell提供了命令行,而不是類似IDE的體驗。語句和表達式能夠在執行狀態上下文中,被立即求值,而不是非得打包到類中。方法也是自由浮動的,而不必屬于某個特定的類。相反,JShell使用代碼片斷“snippets”來提供上層執行環境。

與HTTP/2 API相似,JShell已經在獨立的項目開發,以免在快速發展的時期影響主干構建的穩定性。JShell預計在2015年8月期間合并到主干。

現在,開發者可以參考AdoptOpenJDK說明指導,從頭構建Kulla(源代碼可以從Mercurial地址獲得)。

對于一些上手實驗,最簡單的可能是使用一個獨立的試驗jar。這些jar包是社區專為不想從頭構建的開發者構建好的。

這些試驗jar包可以從AdoptOpenJDK CloudBees的CI構建實例中獲得。

要使用它們,你需要安裝Java 9 beta版(或者OpenJDK 9的構建版本)。然后下載jar文件,重命名為kulla.jar,然后在命令行輸入如下:

$ java -jar kulla.jar
|  Welcome to JShell -- Version 0.610
|  Type /help for help->

這是REPL的標準界面,和往常一樣,命令是從單個字符開始并最終發出的。

JShell有一個相當完整(但仍在發展)的幫助語法,可以通過如下命令輕松獲得:

-> /help
Type a Java language expression, statement, or declaration.
Or type one of the following commands:/l  or /list [all]                -- list the source you have typed/seteditor <executable>    -- set the external editor command to use
/e  or /edit <name or id>         -- edit a source entry referenced by name or id
/d  or /drop <name or id>         -- delete a source entry referenced by name or id
/s  or /save [all|history] <file> -- save the source you have typed
/o  or /open <file>               -- open a file as source input
/v  or /vars                      -- list the declared variables and their values
/m  or /methods                   -- list the declared methods and their signatures
/c  or /classes                   -- list the declared classes
/x  or /exit                      -- exit the REPL
/r  or /reset                     -- reset everything in the REPL
/f  or /feedback <level>          -- feedback information: off, 
concise, normal, verbose, default, or ?
/p  or /prompt                    -- toggle display of a prompt
/cp or /classpath <path>          -- add a path to the classpath
/h  or /history                   -- history of what you have typed/setstart <file>           -- read file and set as the new start-up definitions/savestart <file>          -- save the default start-up definitions to the file
/?  or /help                      -- this help message/!                         -- re-run last snippet/<n>                       -- re-run n-th snippet/-<n>                      -- re-run n-th previous snippetSupported shortcuts include:-- show possible completions for the current text
Shift- -- for current method or constructor invocation, 
show a synopsis of the method/constructor

JShell支持TAB鍵自動補全, 因此我們可以很容易找到println()或者其他我們想使用的方法:

-> System.out.print
print(     printf(    println(

傳統的表達式求值也很容易,但是相比其他動態類型語言,Java的靜態類型特征會更嚴格一點。JShell會自動創建臨時變量來保存表達式的值,并確保它們保持在上下文域內供以后使用:

-> 3 * (4 + 5)
|  Expression value is: 27
|    assigned to temporary variable $1 of type int-> System.out.println($1);
27

我們還可以使用/list命令,查看到目前為止輸入的所有源代碼:

-> /list9 : 3 * (4 + 5)10 : System.out.println($1);

使用/vars命令顯示所有的變量(包括顯式定義的和臨時的),以及他們當前持有的值:

-> String s = "Dydh da"
|  Added variable s of type String with initial value "Dydh da"-> /vars
|    int $1 = 27
|    String s = "Dydh da"

除了支持簡單的代碼行,REPL還允許非常簡單地創建類和其它用戶定義的類型。例如,可以用如下短短一行來創建類(請注意,開始和結束括號是必需的):

-> class Pet {}
|  Added class Pet-> class Cat extends Pet {}
|  Added class Cat

JShell代碼非常簡潔、自由浮動的性質意味著我們可以非常簡單地使用REPL來演示Java語言的功能。例如,讓我們來看看著名的類型問題,即Java數組的協變問題:

-> Pet[] pets = new Pet[1]
|  Added variable pets of type Pet[] with initial value [LPet;@2be94b0f-> Cat[] cats = new Cat[1]
|  Added variable cats of type Cat[] with initial value [LCat;@3ac42916-> pets = cats
|  Variable pets has been assigned the value [LCat;@3ac42916-> pets[0] = new Pet()
|  java.lang.ArrayStoreException thrown: REPL.$REPL13$Pet
|        at (#20:1)

這樣的功能使JShell成為一種偉大的教學或研究工具,而且最接近Scala REPL的體驗。使用/classpath切換,可以加載額外的jar包,從而可以在REPL直接使用互動式探索性API。

文章轉載自 開源中國社區 [http://www.oschina.net]

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395479.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395479.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395479.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c語言編譯程序首要工作,c語言試卷

c語言試卷一、選擇題(每小題1分&#xff0c;共40分)。(以下A、B、C、D四個選項中只有一個是正確的。)1&#xff0e;一個C語言程序是由()。A&#xff0e;一個主程序和若干子程序組成B&#xff0e;函數C&#xff0e;若干過程組成D&#xff0e;若干子程序組成2&#xff0e;C語言源…

Mac通過wifi連接 Android設備

公司用的全是mac開發&#xff0c;但是全是type-C接口&#xff0c;每次背電腦回家啊&#xff0c;還得帶個數據線轉換器…… 想著回來&#xff0c;直接通過Wi-Fi連接手機就好&#xff0c;發現完全忘了之前套路&#xff0c;現在趕緊記下一波&#xff0c;保證包教包會&#xff01; …

貝葉斯統計推斷_統計推斷對決:頻繁主義者與貝葉斯主義者

貝葉斯統計推斷by Kirill Dubovikov通過基里爾杜博維科夫(Kirill Dubovikov) 統計推斷對決&#xff1a;頻繁主義者與貝葉斯主義者 (Statistical Inference Showdown: The Frequentists VS The Bayesians) 推理 (Inference) Statistical Inference is a very important topic t…

iOS之由身份證號返回性別

該博文出自&#xff1a;http://www.cnblogs.com/yang-guang-girl/p/5683454.html - (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.NSString *sex[self sexStrFromIdentityCard:"139876456767892345"];NSLog("--s…

c語言程序設計k.r,【答題】C語言程序設計問題與解釋實驗

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓#include#define N 13main(){int y,m,D,q,t0,i,day0,a0,Day,n,k,O[N]{0,31,29,31,30,31,30,31,31,30,31,30,31},p[N]{0,31,28,31,30,31,30,31,31,30,31,30,31};//y是年&#xff0c;m是月&#xff0c;D是日&#xff0c;q計算周幾&am…

運維命令

1 文件管理2 軟件管理3 系統管理4 服務管理5 網絡管理6 磁盤管理7 用戶管理8 腳本相關9 服務配置----------------------------------1 文件管理----------------------------------創建空白文件touch不提示刪除非空目錄rm -rf 目錄名(-r:遞歸刪除-f 強制)####################…

[原創]K8_C段旁注工具6.0 新增SMB漏洞掃描

工具: K8_C段旁注工具6.0_0510[K.8]編譯: 自己查殼組織: K8搞基大隊[K8team]作者: K8拉登哥哥博客: http://qqhack8.blog.163.com發布: 2017/5/24 13:25:54簡介: 圖片: 功能: 更新歷史:6.0 20170510[] C段SMB漏洞掃描(探測系統版本)[] 批量操作-文本比較提取新增內容[] 旁注查…

qt creator 快捷鍵

http://www.cnblogs.com/jingzhishen/p/4067657.html轉載于:https://www.cnblogs.com/chencesc/p/5733858.html

棧的C語言案例,堆棧實例代碼(C語言)

堆棧實例代碼(C語言)如下所示&#xff1a;#include int MAXSIZE 8;int stack[8];int top -1;int isempty() {if(top -1)return 1;elsereturn 0;}int isfull() {if(top MAXSIZE)return 1;elsereturn 0;}int peek() {return stack[top];}int pop() {int data;if(!isempty()) …

從vue遷移到react_從AngularJS遷移到React-您如何衡量性能提升?

從vue遷移到reactby Gupta Garuda通過古普塔歌魯達(Gupta Garuda) 從AngularJS遷移到React-您如何衡量性能提升&#xff1f; (Migrating from AngularJS to React — how do you measure your performance gains?) Are you looking into migrating a large AngularJS single …

【公告】社區周刊即日起停刊

各位訂閱51CTO社區周刊的小伙伴們&#xff0c;大家好&#xff0c;我是51CTO社區的大管家蘑菇&#xff0c;今天來是想跟大家說&#xff0c;本期周刊將是我們最后一期郵件期刊&#xff0c;沒錯&#xff0c;是最后一期&#xff08;請珍惜它~&#xff09;。或許你會問&#xff0c;停…

springcloud-zuul路由網關

路由網關(zuul) 在微服務架構中&#xff0c;需要多個基礎的服務治理組件&#xff0c;包括服務注冊與發現、服務消費、負載均衡、斷路器、智能 路由、配置管理等&#xff0c;由這個基礎組件相互協作&#xff0c;共同組建了一個簡單的微服務系統。一個簡單的微服務系統如下 圖 總…

python DB.fetchall()--獲取數據庫所有記錄列表

查詢到的數據格式為列表&#xff1a; 多個元素的列表&#xff1a; 單個元素的列表&#xff1a; 轉載于:https://www.cnblogs.com/apple2016/p/5734161.html

c語言中文件讀寫面試題,在C ++中有效讀取非常大的文本文件

我將對其進行重新設計以充當流式傳輸&#xff0c;而不是在一個塊上。一個更簡單的方法是&#xff1a;std::ifstream ifs("input.txt");std::vector parsed(std::istream_iterator(ifs), {});如果您大致知道期望多少個值&#xff0c;那么預先使用std::vector::reserve…

每次調試都必須clean_如何使用“ The Clean Architecture”每次編寫健壯的應用程序...

每次調試都必須cleanby Daniel Oliveira丹尼爾奧利維拉(Daniel Oliveira) 如何使用“ The Clean Architecture”每次編寫健壯的應用程序 (How to write robust apps every time, using “The Clean Architecture”) As developers, we can’t keep from using external librar…

404. Sum of Left Leaves

題目來源&#xff1a; 自我感覺難度/真實難度&#xff1a; 題意&#xff1a; 分析&#xff1a; 自己的代碼&#xff1a; class Solution(object):def sumOfLeftLeaves(self, root):""":type root: TreeNode:rtype: int"""left[]if not root:retu…

Laravel Composer 命令大全

2019獨角獸企業重金招聘Python工程師標準>>> ???????1、安裝 Laravel composer create-project --prefer-dist laravel/laravel 5.xx user-project 2、.env 文件操作 生成 APP_KEY&#xff1a;php artisan key:generate 緩存 .env 配置&#xff…

linux中initrd的含義,Linux2.6 內核的 Initrd 機制解析

1&#xff0e;什么是 Initrdinitrd 的英文含義是 boot loaderinitialized RAM disk&#xff0c;就是由 boot loader 初始化的內存盤。在 linux內核啟動前&#xff0c; boot loader 會將存儲介質中的 initrd 文件加載到內存&#xff0c;內核啟動時會在訪問真正的根文件系統前先訪…

VBS基礎篇 - 常量

VBS基礎篇 - 常量 常量&#xff1a;指的是在程序運行過程中其值保持不變的量&#xff0c;它用來保存固定不變的數值&#xff0c;字符串等常數 。 常量的定義&#xff1a;在vbscript中使用使用 Const 指令可以創建名稱具有一定含義的字符串型或數值型常量&#xff0c;并給它們賦…

為什么虛擬助手的前途一片光明

by Steve史蒂夫(Steve) 為什么虛擬助手的前途一片光明 (Why the future is bright for Virtual Assistants) I purchased my first mobile phone in the summer of 1999. I was 17 years old, growing up in a nondescript town in the Midlands of the United Kingdom. The p…