Netty ChannelHandler之概述
ChannelHandler(管道處理器)其工作模式類似於Java Servlet過濾器,負責對I/O事件或者I/O操作進行攔截處理。採用事件的好處是,ChannelHandler可以選擇自己感興趣的事件進行處理,也可以對不感興趣的事件進行透傳或者終止。
ChannelHandler介面
基於ChannelHandler介面,使用者可以方便實現自己的業務,比如記錄日誌、編解碼、資料過濾等。ChannelHandler介面定義如下:
package io.netty.channel;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public interface ChannelHandler {
void handlerAdded(ChannelHandlerContext ctx) throws Exception;
void handlerRemoved(ChannelHandlerContext ctx) throws Exception;
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Sharable {
}
}
ChannelHandler介面定義比如簡單,只有三個方法:
- handlerAdded方法在ChannelHandler被新增到實際上下文中並準備好處理事件後呼叫。
- handlerRemoved方法在ChannelHandler從實際上下文中移除後呼叫,表明它不再處理事件。
- exceptionCaught方法會在丟擲Throwable類後呼叫。
還有一個Sharable註解,該註解用於表示多個ChannelPipeline可以共享同一個ChannelHandler。
正式因為ChannelHandler介面過於簡單,我們在實際開發中,不會直接實現ChannelHandler介面,因此,Netty提供了ChannelHandlerAdapter抽象類。
ChannelHandlerAdapter抽象類
ChannelHandlerAdapter抽象類核心程式碼如下:
package io.netty.channel;
import io.netty.util.internal.InternalThreadLocalMap;
import java.util.Map;
import java.util.WeakHashMap;
public abstract class ChannelHandlerAdapter implements ChannelHandler {
boolean added;
public boolean isSharable() {
Class<?> clazz = getClass();
Map<Class<?>, Boolean> cache = InternalThreadLocalMap.get().handlerSharableCache();
Boolean sharable = cache.get(clazz);
if (sharable == null) {
sharable = clazz.isAnnotationPresent(Sharable.class);
cache.put(clazz, sharable);
}
return sharable;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// NOOP
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
// NOOP
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.fireExceptionCaught(cause);
}
}
ChannelHandlerAdapter對exceptionCaught方法做了實現,並提供了isSharable方法。需要注意的是,ChannelHandlerAdapter是抽象類,使用者可以自由的選擇是否要覆蓋ChannelHandlerAdapter類的實現。如果對某個方法感興趣,直接覆蓋掉這個方法即可,這樣程式碼就變得簡單清晰。
ChannelHandlerAdapter抽象類提供了兩個子類ChannelInboundHandlerAdapter、ChannelOutboundHandlerAdapter用於針對出站事件、入站事件的進行處理。其中ChannelInboundHandlerAdapter實現了ChannelInboundHandler介面,而ChannelOutboundHandlerAdapter實現了ChannelOutboundHandler介面。
在實際開發過程中,我們的自定義的ChannelHandler多數是繼承自ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter類或者是這兩個類的子類。比如在前面章節中所涉及的編解碼器ByteToMessageDecoder、MessageToMessageDecoder、MessageToByteEncoder、MessageToMessageEncoder等,就是這兩個類的子類。
參考引用
- Java下一代高併發技術——虛擬執行緒“JEP 425: Virtual Threads (Preview)”
- 713頁鴻蒙鉅作!《鴻蒙HarmonyOS手機應用開發實戰》簡介
- 一文總結Java\JDK 17釋出的新特性
- 資料庫分庫分表的幾種場景
- 拯救大學生手機!用SD卡擴容手機內部儲存
- JDK 16釋出,新特性一覽
- Netty ChannelHandler之概述
- 事件驅動及其設計模式
- Eclipse中安裝反編譯工具Fernflower(Enhanced Class Decompiler)
- Java陷阱——慎用入參做返回值
- 記錄一個Java三元表示式中的陷阱
- MEAN架構實戰:基於MongoDB、Express、Angular、Node.js構建企業級應用
- Java開發仍然是主流,一起學《Java核心程式設計》