(iii) Mina source code analysis of the Iofilter

Source: Internet
Author: User

This article mainly analyzes how the filter in Mina is implemented.

The first is to introduce a simple complete server-side example, the code is as follows

public class Server {public static void main (string[] args) {Ioacceptor acceptor = new Niosocketacceptor (); acceptor.getses Sionconfig (). Setreadbuffersize (2048), Acceptor.getsessionconfig (). Setidletime (Idlestatus.both_idle, 100000); Acceptor.getfilterchain (). AddFirst ("Logfilter", New Loggingfilter ())//① join the system's own log filter Acceptor.sethandler (new MyHandler ()); try {acceptor.bind (new inetsocketaddress (9123));} catch (IOException e) {//TODO auto-generated catch Blocke.printstacktrace ();}}}
In code 1 To add a system comes with the filter, first without the system to bring the log filter Loggingfilter internal is how to achieve, and so on to understand the entire filter of Mina after the context of the natural know how to achieve, After getting filterchain through acceptor at Code 1 (the Defaultiofilterchainbuilder object was created when the Niosocketacceptor object was created, as shown in 1)


Figure 1

The Defaultiofilterchainbuilder class provides four ways to add filters, namely AddFirst (), AddLast (), Addbefore (), Addafter (), and all four of these methods call a register () method, the Register method is implemented, is to a list in a certain order to add the filter (do not control how the filter is implemented, the text will be described in detail), that is, after the server started, the client before connecting to the server, Mina just put the filter we added to a list, we have been talking about the filter chain, is now clearly a static list is not a chain, the filter is exactly when the "chain" up, the answer is to establish a connection between the client and the server

   Private final list<entry> entries;   private void Register (int index, Entry e) {        if (contains (E.getname ())) {            throw new IllegalArgumentException (" Other filter is using the same name: "+ e.getname ());        }        Entries.Add (index, e);    }

Let's see what the Mina server does when the client and server are connected, Mina is the message that handles the new connection and connection transmission in the processor class (as discussed in Mina Source resolution (ii)), and each time a new connection comes in, the Addnow method is called. Let's see what the Addnow method has done.

    Private Boolean Addnow (S session) {Boolean registered = false;            try {init (session);            Registered = TRUE;            Build The filter chain of this session.            Iofilterchainbuilder ChainBuilder = Session.getservice (). Getfilterchainbuilder (); Chainbuilder.buildfilterchain (Session.getfilterchain ()); <span style= "color: #33CC00;" ></span>//①//Defaultiofilterchain.connect_future is cleared inside here/in Abstractiof            Ilterchain.firesessionopened (). Propagate the session_created event up to the chain ioservicelistenersupport listeners = ((Abstractioservice            ) Session.getservice ()). Getlisteners ();        Listeners.firesessioncreated (session);            } catch (Exception e) {exceptionmonitor.getinstance (). Exceptioncaught (e);            try {destroy (session); } catch (Exception E1) {exceptionmonitor.getinstance (). ExceptionCaught (E1);            } finally {registered = false;    }} return registered; }
At code 1, the static list that holds the filter is constructed into a filter chain to see how it was constructed, first getting a Fiterchain object through the Session.getfilterchain () method, Note that Filterchain is not the Defaultiofilterchainbuilder mentioned earlier, this Filterchain object is an object created when the session object was created, as shown in 2

Figure 2

Let's look at what we did when we created the Defaultiofilterchain object, and the code for the new Defaultiofilterchain is as follows:

    Public Defaultiofilterchain (abstractiosession session) {        if (session = = null) {            throw new IllegalArgumentException ("session");        }        This.session = Session;        Head = new Entryimpl (NULL, NULL, "Head", New Headfilter ());//①        tail = new Entryimpl (head, NULL, "tail", new Tailfilter ());//②        head.nextentry = tail;    }

Figure 3

When creating Defaultiofilterchain, the head attribute and the tail attribute are initialized, and the students who have studied the data structure must be very familiar with these two things, yes, this is the head node and the tail node in the list, Entryimpl This class is designed to implement the list in Java, 3 Entryimpl contains 5 properties, where preventry points to the previous filter, NextEntry points to the next filter, name is the name of the filter, Filter is used to implement the filtering function (the implementation method is described later), Nextfilter used to invoke the next filter, the above ①② code execution will generate a two nodes of the linked list, 4 shows


Figure 4
After executing the code ① of the Addnow method, the filter is linked, as shown in 5

Figure 5

The filter chain is established after the message is how the head node through the filter chain to our business logic processing of the Iohandler, to know this problem, we first look at the Mina in the filter chain related to the class there, in the Mina filter related classes are mainly divided into 3 categories, The first class is the Iofilterchainbuilder interface and its implementation class Defaultiofilterchainbuilder. The function of these two classes is to create a filter chain in a pre-defined order when Iosession is created (if you forget the two classes you can go back to the above to find out where these two classes are used), Iofilterchainbuilder only provides an interface method that Buildfilterchain () establishes a filter chain. Some of the other ways to implement class Defaultiofilterchainbuilder are to provide additional support for this method

The second category is Iofilterchain and Defaultiofilterchain. These two classes provide the ability to build filter chains and, when events arrive, forward the events through the filter chain to Iohandler (explained later in this article), and each iosessiond has its own filter chain. Some students may not understand the construction function is not the above said Defaultiofilterchainbuilder responsible for it, how to become Defaultiofilterchain responsible, In fact, the construction of the filter chain when Defaultiofilterchainbuilder called the Defaultiofilterchain of the construction of the filter chain implementation, in fact, this is the implementation is a design pattern: Command mode, do not understand it does not matter, will not affect your understanding, Command mode We're not going to talk about it here.


The third class is the Iofilter interface and its specific implementation, Mina has provided us with a number of filter implementations, the following list is a relatively common part of the implementation, iofilteradapter implementation of the Iofilter interface provides us with the default implementation, This allows us to directly inherit the Iofilteradapter interface when we create our own filters, so that we can implement only the methods we are interested in, which will make our code more concise.

We see how headfilter is implemented, Headfilter not implement sessioncreated, sessionopened, messagereceived and so on a series of methods, So when the message comes, we call the implementation of Headfilter's parent class Iofilteradapter, and Iofilteradapter's implementation is to call the next filter chain sessioncreated, sessionopened, Messagereceived and so on.

Private class Headfilter extends Iofilteradapter {@SuppressWarnings ("unchecked") @Override public Vo ID filterwrite (Nextfilter nextfilter, iosession session, Writerequest Writerequest) throws Exception {Abstract            Iosession s = (abstractiosession) session;            Maintain counters. if (Writerequest.getmessage () instanceof iobuffer) {Iobuffer buffer = (iobuffer) writerequest.getmessage ()                ; I/O processor implementation would call Buffer.reset ()//It after the write operation is finished, Becau                SE//The buffer is specified with Messagesent event.                Buffer.mark ();                int remaining = buffer.remaining ();                if (Remaining > 0) {s.increasescheduledwritebytes (remaining);            }} else {s.increasescheduledwritemessages (); } writerequestqueue Writerequestqueue = S.GEtwriterequestqueue (); if (!s.iswritesuspended ()) {if (Writerequestqueue.isempty (session)) {//We can write D                irectly the Message s.getprocessor (). Write (S, writerequest);                    } else {S.getwriterequestqueue (). Offer (S, writerequest);                S.getprocessor (). Flush (s);            }} else {S.getwriterequestqueue (). Offer (S, writerequest); }} @SuppressWarnings ("Unchecked") @Override public void Filterclose (Nextfilter nextfilter, Io        Session session) throws Exception {((abstractiosession) session). Getprocessor (). Remove (session); }    }
Let us see how tailfilter is implemented, because Tailfilter is already a tail node, so the implementation of Tailfilter does not call the next filter, but calls the method in Iohandler, so that the message is passed to the Iohandler, Now we can deal with our business logic in Iohandler.

private static class Tailfilter extends Iofilteradapter {@Override public void sessioncreated (Nextfilter ne Xtfilter, Iosession session) throws Exception {try {session.gethandler (). sessioncreated (Sessio            n);                } finally {//Notify the related future.                Connectfuture future = (connectfuture) session.removeattribute (session_created_future);                if (future! = null) {future.setsession (session);  }}} @Override public void sessionopened (Nextfilter Nextfilter, iosession session) throws        Exception {Session.gethandler (). sessionopened (session);            } @Override public void sessionclosed (Nextfilter Nextfilter, iosession session) throws Exception {            Abstractiosession s = (abstractiosession) session;            try {s.gethandler (). sessionclosed (session);                } finally {try {s.getwriterequestqueue (). Dispose (session);                    } finally {try {S.getattributemap (). Dispose (session);                            } finally {try {//Remove all filters.                        Session.getfilterchain (). Clear (); } finally {if (S.getconfig (). Isusereadoperation ()) {S.offerclo                            Sedreadfuture ();  }}}}} @Override public void Sessionidle (Nextfilter Nextfilter, iosession session, Idlestatus status) throws Exception {Session.gethandler        (). Sessionidle (session, status); } @Override public void Exceptioncaught (Nextfilter Nextfilter, iosession session, Throwable cause) throws Ex ception {abstractiosession s = (abstractiOsession) session;            try {s.gethandler (). Exceptioncaught (S, cause);                } finally {if (S.getconfig (). Isusereadoperation ()) {s.offerfailedreadfuture (cause); }}} @Override public void inputclosed (Nextfilter nextfilter, iosession ses        Sion) throws Exception {Session.gethandler (). inputclosed (session); } @Override public void messagereceived (Nextfilter Nextfilter, iosession session, Object message) throws Exc            eption {abstractiosession s = (abstractiosession) session; if (! (            Message instanceof Iobuffer) {s.increasereadmessages (System.currenttimemillis ()); } else if (! (            (iobuffer) message). Hasremaining ()) {s.increasereadmessages (System.currenttimemillis ());             }//Update The statistics if (Session.getservice () instanceof Abstractioservice) {   ((Abstractioservice) Session.getservice ()). Getstatistics (). Updatethroughput (System.currenttimemillis ());            }//Propagate The message try {Session.gethandler (). messagereceived (S, message); } finally {if (S.getconfig (). Isusereadoperation ()) {S.offerreadfuture (messag                e); }}} @Override public void Messagesent (Nextfilter Nextfilter, iosession session, Writereq Uest writerequest) throws Exception {(abstractiosession) session). Increasewrittenmessages (Writerequest, Syste            M.currenttimemillis ()); Update the statistics if (Session.getservice () instanceof Abstractioservice) {(abstractiose            Rvice) Session.getservice ()). Getstatistics (). Updatethroughput (System.currenttimemillis ()); }//Propagate the Message Session.gethandler (). Messagesent (Session, Writerequest.getmessage ()); } @Override public void Filterwrite (Nextfilter Nextfilter, iosession session, Writerequest Writerequest) thr        oWS Exception {Nextfilter.filterwrite (session, Writerequest);            } @Override public void Filterclose (Nextfilter Nextfilter, iosession session) throws Exception {        Nextfilter.filterclose (session); }    }




(iii) Mina source code analysis of the Iofilter

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.