職責鍊模式
将對象連成一條鍊,使得請求可以在鍊中進行傳遞,直到有一個對象處理他為止。
責任鍊中的角色
抽象處理者角色(Handler):定義出一個處理請求的接口。如果需要,接口可以定義出一個方法以設定和傳回對下家的引用。這個角色通常由一個Java抽象類或者Java接口實作。
具體處理者角色(ConcreteHandler):具體處理者接到請求後,可以選擇将請求處理掉,或者将請求傳給下家。由于具體處理者持有對下家的引用,是以,如果需要,具體處理者可以通路下家。
抽象處理者角色
public abstract class Handler {
protected Handler successor;
public abstract void handleRequest();
public Handler getSuccessor() {
return successor;
}
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
具體處理者角色
public class ConcreteHandler extendsHandler {
@Override
public void handleRequest() {
if(getSuccessor() != null)
{
System.out.println("放過請求");
getSuccessor().handleRequest();
}else
{
System.out.println("處理請求");
}
}
}
用戶端類
public class Client {
public static void main(String[] args) {
//組裝責任鍊
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
//送出請求
handler1.handleRequest();
}
}
例子中的責任鍊處理邏輯很簡單:當有下一個處理者的時候,則直接傳遞給下一個處理者,當沒有的時候,則自己處理。
以上就是一般的責任鍊模式的處理邏輯。和我們在web開發中經常使用到的filter非常相似。下面看看在netty中是如何使用責任鍊模式的。
Netty中的責任鍊模式使用
在netty中,将Channel的資料管道抽象為ChannelPipeline,消息在ChannelPipeline中流動和傳遞。ChannelPipeline是ChannelHandler的容器,持有I/O事件攔截器ChannelHandler的連結清單,負責對ChannelHandler的管理和排程。由ChannelHandler對I/O事件進行攔截和處理,并可以通過接口友善地新增和删除ChannelHandler來實作不同業務邏輯的處理。
ChannelPipeline的責任鍊事件處理過程
圖中展示了一個消息被ChannelPipeline鍊攔截和處理的過程。
(1) 底層的SocketChannel read方法讀取ByteBuf,觸發ChannelRead事件,由I/O線程NioEventLoop調用ChannelPipeline的fireChannelRead方法,将消息傳輸到ChannelPipeline中。
(2) 消息依次被HeadHandler、ChannelHandler1、ChannelHandler2……TailHandler攔截和處理,在這個過程中,任何ChannelHandler都可以中斷目前的流程,結束消息的傳遞。
(3) 當調用ChannelHandlerContext的write方法發送消息,消息從TailHandler開始,經ChannelHandlerN……ChannelHandler1、HeadHandler,最終被添加到消息發送緩沖區中等待重新整理和發送,在此過程中也可以被中斷
在Netty中将事件根據源頭的不同分為InBound事件和OutBound事件。InBound事件通常由I/O線程觸發,例如TCP鍊路建立和關閉、讀事件等等,分别會觸發相應的事件方法。而OutBound事件則一般由使用者主動發起的網絡I/O操作,例如使用者發起的連接配接操作,綁定操作和消息發送操作等,也會分别觸發相應的事件方法。由于netty中提供了一個抽象類ChannelHandlerAdapter,它預設不處理攔截的事件。是以,在實際程式設計過程中,我們隻需要繼承ChannelHandlerAdapter,在我們的自定義Handler中覆寫業務關心的事件方法即可。