最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何開發(fā)基于Netty的HTTP/HTTPS應(yīng)用程序

 更新時(shí)間:2021年06月29日 14:16:30   作者:低吟不作語(yǔ)  
HTTP/HTTPS是最常見的協(xié)議套件之一,并且隨著智能手機(jī)的成功,它的應(yīng)用也日益廣泛,因?yàn)閷?duì)于任何公司來說,擁有一個(gè)可以被移動(dòng)設(shè)備訪問的網(wǎng)站幾乎是必須的。下面就來看看如何開發(fā)基于Netty的HTTP/HTTPS應(yīng)用程序

一、通過 SSL/TLS 保護(hù)應(yīng)用程序

SSL 和 TLS 安全協(xié)議層疊在其他協(xié)議之上,用以實(shí)現(xiàn)數(shù)據(jù)安全。為了支持 SSL/TLS,Java 提供了 javax.net.ssl 包,它的 SSLContext 和 SSLEngine 類使得實(shí)現(xiàn)解密和加密變得相當(dāng)簡(jiǎn)單。Netty 通過一個(gè)名為 SsLHandler 的 ChannelHandler 實(shí)現(xiàn)了這個(gè) API,其中 SSLHandler 在內(nèi)部使用 SSLEngine 來完成實(shí)際工作

Netty 還提供了基于 OpenSSL 工具包的 SSLEngine 實(shí)現(xiàn),比 JDK 提供的 SSLEngine 具有更好的性能。如果 OpenSSL 可用,可以將 Netty 應(yīng)用程序配置為默認(rèn)使用 OpenSSLEngine。如果不可用,Netty 將會(huì)退回到 JDK 實(shí)現(xiàn)

下述代碼展示了如何使用 ChannelInitializer 來將 SslHandler 添加到 ChannelPipeline 中

public class SslChannelInitializer extends ChannelInitializer<Channel> {

    private final SslContext context;
    private final boolean startTls;

    public SslChannelInitializer(SslContext context, boolean startTls) {
        this.context = context;
        this.startTls = startTls;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        SSLEngine engine = context.newEngine(ch.alloc());
        ch.pipeline().addFirst("ssl", new SslHandler(engine, startTls));
    }
}

大多數(shù)情況下,Sslhandler 將是 ChannelPipeline 中的第一個(gè) ChannelHandler,這確保了只有在所有其他的 ChannelHandler 將它們的邏輯應(yīng)用到數(shù)據(jù)之后,才會(huì)進(jìn)行加密

SSLHandler 具有一些有用的方法,如表所示,例如,在握手階段,兩個(gè)節(jié)點(diǎn)將相互驗(yàn)證并且商定一種加密方式,你可以通過配置 SslHandler 來修改它的行為,或者在 SSL/TLS 握手一旦完成之后提供通知,握手階段之后,所有的數(shù)據(jù)都將會(huì)被加密

方法名稱 描述
setHandshakeTimeout(long, TimeUnit)
setHandshakeTimeoutMillis(long)
getHandshakeTimeoutMillis()
設(shè)置和獲取超時(shí)時(shí)間,超時(shí)之后,握手 ChannelFuture 將會(huì)被通知失敗
setCloseNotifyTimeout(long, TimeUnit)
setCloseNotifyTimeoutMillis(long)
getCloseNotifyTimeoutMillis()
設(shè)置和獲取超時(shí)時(shí)間,超時(shí)之后,將會(huì)觸發(fā)一個(gè)關(guān)閉通知并關(guān)閉連接,這也會(huì)導(dǎo)致通知該 ChannelFuture 失敗
handshakeFuture() 返回一個(gè)在握手完成后將會(huì)得到通知的 ChannelFuture,如果握手先前已經(jīng)執(zhí)行過,則返回一個(gè)包含了先前握手結(jié)果的 ChannelFuture
close()
close(ChannelPipeline)
close(ChannelHandlerContext, ChannelPromise)
發(fā)送 close_notify 以請(qǐng)求關(guān)閉并銷毀底層的 SslEngine

二、HTTP 編解碼器

HTTP 是基于請(qǐng)求/響應(yīng)模式的,客戶端向服務(wù)器發(fā)送一個(gè) HTTP 請(qǐng)求,然后服務(wù)器將會(huì)返回一個(gè) HTTP 響應(yīng),Netty 提供了多種多種編碼器和解碼器以簡(jiǎn)化對(duì)這個(gè)協(xié)議的使用

下圖分別展示了生產(chǎn)和消費(fèi) HTTP 請(qǐng)求和 HTTP 響應(yīng)的方法

如圖所示,一個(gè) HTTP 請(qǐng)求/響應(yīng)可能由多個(gè)數(shù)據(jù)部分組成,并且總以一個(gè) LastHttpContent 部分作為結(jié)束

下表概要地介紹了處理和生成這些消息的 HTTP 解碼器和編碼器

名稱 描述
HttpRequestEncoder 將 HTTPRequest、HttpContent 和 LastHttpContent 消息編碼為字節(jié)
HttpResponseEncoder 將 HTTPResponse、HttpContent 和 LastHttpContent 消息編碼為字節(jié)
HttpRequestDecoder 將字節(jié)編碼為 HTTPRequest、HttpContent 和 LastHttpContent 消息
HttpResponseDecoder 將字節(jié)編碼為 HTTPResponse、HttpContent 和 LastHttpContent 消息

下述代碼中的 HttpPipelineInitializer 類展示了將 HTTP 支持添加到你的應(yīng)用程序是多么簡(jiǎn)單 —— 只需要將正確的 ChannelHandler 添加到 ChannelPipeline 中

public class HttpPipelineInitializer extends ChannelInitializer<Channel> {

    private final boolean client;

    public HttpPipelineInitializer(boolean client) {
        this.client = client;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        if (client) {
            // 如果是客戶端,則添加 HttpResponseDecoder 處理來自服務(wù)器的響應(yīng)
            pipeline.addLast("decoder", new HttpResponseDecoder());
            // 如果是客戶端,則添加 HttpRequestEncoder 向服務(wù)器發(fā)送請(qǐng)求
            pipeline.addLast("encoder", new HttpRequestEncoder());
        } else {
            // 如果是服務(wù)端,則添加 HttpRequestDecoder 處理來自客戶端的請(qǐng)求
            pipeline.addLast("decoder", new HttpRequestDecoder());
            // 如果是客戶端,則添加 HttpResponseEncoder 向客戶端發(fā)送響應(yīng)
            pipeline.addLast("encoder", new HttpResponseEncoder());
        }
    }
}

三、聚合 HTTP 消息

在 ChannelInitializer 將 ChannelHandler 安裝到 ChannelPipeline 中之后,你就可以處理不同類型的 HTTPObject 消息了。但由于 HTTP 請(qǐng)求和響應(yīng)可能由許多部分組成,因此你需要聚合它們以形成完整的消息。Netty 提供了一個(gè)聚合器,它可以將多個(gè)消息部分合并為 FullHttpRequest 或者 FullHttpResponse 消息

由于消息分段需要被緩沖,直到可以轉(zhuǎn)發(fā)下一個(gè)完整的消息給下一個(gè) ChannelInboundHandler,所以這個(gè)操作有輕微的開銷,其所帶來的好處就是你可以不必關(guān)心消息碎片了

引入這種自動(dòng)聚合機(jī)制只不過是向 ChannelPipeline 中添加另外一個(gè) ChannelHandler 罷了,下述代碼展示了如何做到這一點(diǎn):

public class HttpAggregatorInitializer extends ChannelInitializer<Channel> {

    private final boolean isClient;

    public HttpAggregatorInitializer(boolean isClient) {
        this.isClient = isClient;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        if (isClient) {
            // 如果是客戶端,則添加 HttpClientCodec
            pipeline.addLast("codec", new HttpClientCodec());
        } else {
            // 如果是服務(wù)器,則添加 HttpServerCodec
            pipeline.addLast("codec", new HttpServerCodec());
        }
        // 將最大的消息大小為 512KB 的 HTTPObjectAggregator 添加到 ChannelPipeline
        pipeline.addLast("aggregator", new HttpObjectAggregator(512 * 1024));
    }
}

四、HTTP 壓縮

當(dāng)使用 HTTP 時(shí),建議開啟壓縮功能以盡可能多地減小傳輸數(shù)據(jù)的大小。雖然壓縮會(huì)帶來一些消耗,但通常來說它都是一個(gè)好主意,尤其是對(duì)于文本數(shù)據(jù)而言

Netty 為壓縮和解壓都提供了 ChannelHandler 實(shí)現(xiàn),它們同時(shí)支持 gzip 和 deflate 編碼

客戶端可以通過提供以下頭部信息來指示服務(wù)器它所支持的壓縮格式

GET /encrypted-area HTTP/1.1

Host: www.example.com

Accept-Encoding: gzip, deflate

然而,需要注意的是,服務(wù)器沒有義務(wù)壓縮它所發(fā)送的數(shù)據(jù)

public class HttpCompressionInitializer extends ChannelInitializer<Channel> {

    private final boolean isClient;

    public HttpCompressionInitializer(boolean isClient) {
        this.isClient = isClient;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        if (isClient) {
            // 如果是客戶端,則添加 HTTPClientCodec
            pipeline.addLast("codec", new HttpClientCodec());
            // 如果是客戶端,則添加 HttpContentDecompressor 以處理來自服務(wù)器的壓縮內(nèi)容
            pipeline.addLast("decompressor", new HttpContentDecompressor());
        } else {
            // 如果是服務(wù)端,則添加 HttpServerCodec
            pipeline.addLast("codec", new HttpServerCodec());
            // 如果是服務(wù)器,則添加 HttpContentDecompressor 來壓縮數(shù)據(jù)
            pipeline.addLast("decompressor", new HttpContentDecompressor());
        }
    }
}

五、HTTPS

啟用 HTTPS 只需要將 SslHandler 添加到 ChannelPipeline 的 ChannelHandler 組合中

public class HttpsCodecInitializer extends ChannelInitializer<Channel> {

    private final SslContext context;
    private final boolean isClient;

    public HttpsCodecInitializer(SslContext context, boolean isClient) {
        this.context = context;
        this.isClient = isClient;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        SSLEngine engine = context.newEngine(ch.alloc());
        pipeline.addLast("ssl", new SslHandler(engine));
        if (isClient) {
            pipeline.addLast("codec", new HttpClientCodec());
        } else {
            pipeline.addLast("codec", new HttpServerCodec());
        } 
    }
}

六、WebSocket

WebSocket 解決了一個(gè)長(zhǎng)期存在的問題:既然底層協(xié)議(HTTP)是一個(gè)請(qǐng)求/響應(yīng)模式的交互序列,那么如何實(shí)時(shí)地發(fā)布信息呢?AJAX一定程度上解決了這個(gè)問題,但數(shù)據(jù)流仍然是由客戶端所發(fā)送的請(qǐng)求驅(qū)動(dòng)的

WebSocket 提供了在單個(gè) TCP 連接上提供雙向的通信,它為網(wǎng)頁(yè)和遠(yuǎn)程服務(wù)器之間的雙向通信提供了一種替代 HTTP 輪詢的方案

要想向你的應(yīng)用程序添加對(duì)于 WebSocket 的支持,你需要將適當(dāng)?shù)目蛻舳嘶蛘叻?wù)器 WebSocketChannelHandler 添加到 ChannelPipeline 中。這個(gè)類將處理由 WebSocket 定義的稱為幀的特殊消息類型,如表所示,WebSocketFrame 可以被歸類為數(shù)據(jù)幀或者控制幀

名稱 描述
BinaryWebSocketFrame 數(shù)據(jù)幀:二進(jìn)制數(shù)據(jù)
TextWebSocketFrame 數(shù)據(jù)幀:文本數(shù)據(jù)
ContinuationWebSocketFrame 數(shù)據(jù)幀:屬于上一個(gè) BinaryWebSocketFrame 或者 TextWebSocketFrame 的文本或者二進(jìn)制的數(shù)據(jù)
CloseWebSocketFrame 控制幀:一個(gè) CLOSE 請(qǐng)求,關(guān)閉的狀態(tài)碼以及關(guān)閉的原因
PingWebSocketFrame 控制幀:請(qǐng)求一個(gè) PongWebSocketFrame
PongWebSocketFrame 控制幀:對(duì) PingWebSocketFrame 請(qǐng)求的響應(yīng)

因?yàn)?Netty 主要是一種服務(wù)器端技術(shù),所以我們重點(diǎn)創(chuàng)建 WebSocket 服務(wù)器。下述代碼展示了使用 WebSocketChannelHandler 的簡(jiǎn)單示例,這個(gè)類會(huì)處理協(xié)議升級(jí)握手,以及三種控制幀 —— Close、Ping 和 Pong,Text 和 Binary 數(shù)據(jù)幀將會(huì)被傳遞給下一個(gè) ChannelHandler 進(jìn)行處理

public class WebSocketServerInitializer extends ChannelInitializer<Channel> {

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ch.pipeline().addLast(
                new HttpServerCodec(),
                new HttpObjectAggregator(65536),
                // 如果被請(qǐng)求的端點(diǎn)是 /websocket,則處理該升級(jí)握手
                new WebSocketServerProtocolHandler("/websocket"),
                // TextFrameHandler 處理 TextWebSocketFrame
                new TextFrameHandler(),
                // BinaryFrameHandler 處理 BinaryWebSocketFrame
                new BinaryFrameHandler(),
                // ContinuationFrameHandler 處理 Continuation WebSocketFrame
                new ContinuationFrameHandler());
    }

    public static final class TextFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

        @Override
        protected void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
            // do something
        }
    }

    public static final class BinaryFrameHandler extends SimpleChannelInboundHandler<BinaryWebSocketFrame> {

        @Override
        protected void messageReceived(ChannelHandlerContext ctx, BinaryWebSocketFrame msg) throws Exception {
            // do something
        }
    }

    public static final class ContinuationFrameHandler extends SimpleChannelInboundHandler<ContinuationWebSocketFrame> {

        @Override
        protected void messageReceived(ChannelHandlerContext ctx, ContinuationWebSocketFrame msg) throws Exception {
            // do something
        }
    }
}

以上就是如何開發(fā)基于Netty的HTTP/HTTPS應(yīng)用程序的詳細(xì)內(nèi)容,更多關(guān)于Netty HTTP/HTTPS的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java集合之Disruptor操作示例

    Java集合之Disruptor操作示例

    這篇文章主要為大家介紹了Java集合之Disruptor操作示例介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • spring @Profiles和@PropertySource實(shí)現(xiàn)根據(jù)環(huán)境切換配置文件

    spring @Profiles和@PropertySource實(shí)現(xiàn)根據(jù)環(huán)境切換配置文件

    這篇文章主要介紹了spring @Profiles和@PropertySource根據(jù)環(huán)境切換配置文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 基于SpringBoot框架管理Excel和PDF文件類型

    基于SpringBoot框架管理Excel和PDF文件類型

    這篇文章主要介紹了基于SpringBoot框架,管理Excel和PDF文件類型,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java中static的用法及注意點(diǎn)

    java中static的用法及注意點(diǎn)

    在本篇文章里小編給大家整理的是一篇關(guān)于java中static的用法及注意點(diǎn),有興趣的朋友們可以學(xué)習(xí)下。
    2021-03-03
  • SpringBoot小程序推送信息的項(xiàng)目實(shí)踐

    SpringBoot小程序推送信息的項(xiàng)目實(shí)踐

    本文主要介紹了SpringBoot小程序推送信息的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Mybatis中一條SQL使用兩個(gè)foreach的問題及解決

    Mybatis中一條SQL使用兩個(gè)foreach的問題及解決

    這篇文章主要介紹了Mybatis中一條SQL使用兩個(gè)foreach的問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • java中ZXing 生成、解析二維碼圖片的小示例

    java中ZXing 生成、解析二維碼圖片的小示例

    ZXing 是一個(gè)開源 Java 類庫(kù)用于解析多種格式的 1D/2D 條形碼,這篇文章主要介紹了java中ZXing 生成、解析二維碼圖片的小示例 ,有興趣的可以了解一下。
    2017-01-01
  • JAVA中堆、棧,靜態(tài)方法和非靜態(tài)方法的速度問題

    JAVA中堆、棧,靜態(tài)方法和非靜態(tài)方法的速度問題

    這篇文章主要介紹了JAVA中堆、棧,靜態(tài)方法和非靜態(tài)方法的速度問題,堆和棧得速度性能分析多角度給大家分析,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-08-08
  • java服務(wù)器的簡(jiǎn)單實(shí)現(xiàn)過程記錄

    java服務(wù)器的簡(jiǎn)單實(shí)現(xiàn)過程記錄

    在線瀏覽網(wǎng)頁(yè)離不開服務(wù)器,用戶發(fā)出請(qǐng)求request,服務(wù)器做出響應(yīng)response,提供給用戶需要的頁(yè)面,這篇文章主要給大家介紹了關(guān)于java服務(wù)器簡(jiǎn)單實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Java中的static--靜態(tài)變量你了解嗎

    Java中的static--靜態(tài)變量你了解嗎

    Java 中被 static 修飾的成員稱為靜態(tài)成員或類成員。它屬于整個(gè)類所有,而不是某個(gè)對(duì)象所有,即被類的所有對(duì)象所共享。靜態(tài)成員可以使用類名直接訪問,也可以使用對(duì)象名進(jìn)行訪問,.下面我們來詳細(xì)了解一下吧
    2021-09-09

最新評(píng)論

红河县| 库尔勒市| 灌南县| 剑川县| 东莞市| 宣汉县| 海城市| 长春市| 稻城县| 东安县| 梧州市| 天津市| 洪湖市| 阳谷县| 邯郸市| 特克斯县| 读书| 来安县| 辉县市| 宜黄县| 麻阳| 江达县| 福贡县| 杭锦后旗| 玛沁县| 革吉县| 松溪县| 金门县| 沙雅县| 台州市| 丁青县| 白城市| 崇礼县| 灵丘县| 偃师市| 修水县| 河北区| 含山县| 乌恰县| 衡东县| 永吉县|