@ Skip in the Netty framework in java

Source: Internet
Author: User
Tags current time flush stub

I recently learned about the Netty framework and wrote a simple netty application to the tutorial. However, the debugging failed. I can't find the cause after reading the program and the tutorial several times, later, I wrote it again, and the server program was successfully debugged. The reason was that the @ Skip annotation was used. The code is as follows:

Package com. chris. netty;

Import io. netty. bootstrap. ServerBootstrap;
Import io. netty. buffer. ByteBuf;
Import io. netty. buffer. Unpooled;
Import io. netty. channel. ChannelFuture;
Import io. netty. channel. ChannelHandler. Skip;
Import io. netty. channel. ChannelHandlerAdapter;
Import io. netty. channel. ChannelHandlerContext;
Import io. netty. channel. ChannelInitializer;
Import io. netty. channel. ChannelOption;
Import io. netty. channel. ChannelPromise;
Import io. netty. channel. EventLoopGroup;
Import io. netty. channel. SimpleChannelInboundHandler;
Import io. netty. channel. nio. NioEventLoopGroup;
Import io. netty. channel. socket. SocketChannel;
Import io. netty. channel. socket. nio. NioServerSocketChannel;
Import io. netty. example. discard. DiscardServerHandler;
Import io. netty. handler. logging. LogLevel;
Import io. netty. handler. logging. LoggingHandler;
Import io. netty. util. ReferenceCountUtil;

Import java.net. SocketAddress;
Import java. SQL. Date;


/**
* @ Author Chris
* @ Date 2015-4-12
*/
Public class NettyTimerServer {
 
 
Public void bind (int port) throws Exception {
  
EventLoopGroup bossGroup = new NioEventLoopGroup ();
EventLoopGroup workGroup = new NioEventLoopGroup ();
  
Try {
ServerBootstrap B = new ServerBootstrap ();
B. group (bossGroup, workGroup)
. Channel (NioServerSocketChannel. class)
. Option (ChannelOption. SO_BACKLOG, 1024)
. Handler (new LoggingHandler (LogLevel. INFO ))
. ChildHandler (new ChildChannelHandler ());
System. out. println ("server bind 8888 ");
ChannelFuture f = B. bind (port). sync ();
System. out. println ("finish bind ");
F. channel (). closeFuture (). sync ();
} Catch (Exception e ){
// TODO Auto-generated catch block
E. printStackTrace ();
} Finally {
BossGroup. shutdownGracefully ();
WorkGroup. shutdownGracefully ();
  }
  
  
 }
 
Private class ChildChannelHandler extends ChannelInitializer <SocketChannel> {

/* (Non-Javadoc)
* @ See io. netty. channel. ChannelInitializer # initChannel (io. netty. channel. Channel)
*/
@ Override
Protected void initChannel (SocketChannel arg0) throws Exception {
System. out. println ("server initChannel ");
Arg0.pipeline (). addLast (new TimeServerHandler ());
// Arg0.pipeline (). addl
   
  }
  
 }

/**
* @ Param args
*/
Public static void main (String [] args ){
// TODO Auto-generated method stub
  
Try {
New NettyTimerServer (). bind (8888 );
} Catch (Exception e ){
// TODO Auto-generated catch block
E. printStackTrace ();
  }

 }

}

Class TimeServerHandler extends ChannelHandlerAdapter {

@ Override
@ Skip
Public void channelActive (ChannelHandlerContext ctx) throws Exception {
Super. channelActive (ctx );
 }

@ Override
@ Skip
Public void channelRead (ChannelHandlerContext ctx, Object msg)
Throws Exception {
ByteBuf buf = (ByteBuf) msg;
  
Byte [] bytes = new byte [buf. readableBytes ()];
  
Buf. readBytes (bytes );
  
String body = new String (bytes, "UTF-8 ");
System. out. println ("the server receive order:" + body );
  
String currentTIme = "query current time". Why signorecase (body )? (New Date (System. currentTimeMillis (). toString (): "receive error order ";
  
ByteBuf resp = Unpooled. copiedBuffer (currentTIme. getBytes ());
  
Ctx. write (resp );
 }

@ Override
@ Skip
Public void channelReadComplete (ChannelHandlerContext ctx) throws Exception {
Ctx. flush ();
 }

@ Override
@ Skip
Public void connect (ChannelHandlerContext ctx, SocketAddress remoteAddress,
SocketAddress localAddress, ChannelPromise promise)
Throws Exception {
// TODO Auto-generated method stub
Super. connect (ctx, remoteAddress, localAddress, promise );
 }
 
 
 
 
 
 
}
 

Each method of this implementation class has a @ Skip annotation. After the annotation is removed, the program is successfully debugged. The server program developed by netty can normally receive and process client connections.

It took a day to get stuck with this comment, so I went to view the netty source code. The following is a description of @ Skip source code:

/**
* Indicates that the annotated event handler method in {@ link ChannelHandler} will not be invoked
* {@ Link ChannelPipeline}. This annotation is only useful when your handler method implementation
* Only passes the event through to the next handler, like the following:
     *
* <Pre>
* {@ Code @ Skip}
* {@ Code @ Override}
* Public void channelActive ({@ link ChannelHandlerContext} ctx ){
* Ctx. fireChannelActive (); // do nothing but passing through to the next handler
*}
* </Pre>
     *
* {@ Link # handlerAdded (ChannelHandlerContext)} and {@ link # handlerRemoved (ChannelHandlerContext)} are not able
* Pass the event through to the next handler, so they must do nothing when annotated.
     *
* <Pre>
* {@ Code @ Skip}
* {@ Code @ Override}
* Public void handlerAdded ({@ link ChannelHandlerContext} ctx ){
* // Do nothing
*}
* </Pre>
     *
* <P>
* Note that this annotation is not {@ linkplain Inherited inherited}. If you override a method annotated
* {@ Link Skip}, it will not be skipped anymore. Similarly, you can override a method not annotated
* {@ Link Skip} and simply pass the event through to the next handler, which reverses the behavior of
* Supertype.
* </P>
*/
@ Target (ElementType. METHOD)
@ Retention (RetentionPolicy. RUNTIME)
@ Interface Skip {
// No value
    }
In general, it means that @ Skip annotation is used to annotate the method in the implementation class of Handler. If @ Skip annotated a method in the implementation class of a handler during the program running, this method will not be called by the ChannelPipeline object. Therefore, this is why my server program failed debugging. Let's take a look at how netty handles @ Skip annotation during internal execution. By scanning the full text of the source code file, we found that @ Skip Annotation Processing is concentrated in AbstractChannelHandlerContext, the following is the source code of the method for processing @ Skip:

/**
* Returns an integer bitset that tells which handler methods were annotated with {@ link Skip }.
* It gets the value from {@ link # skipFlagsCache} if an handler of the same type were queried before.
* Otherwise, it delegates to {@ link # skipFlags0 (Class)} to get it.
*/
Static int skipFlags (ChannelHandler handler ){
WeakHashMap <Class <?>, Integer> cache = skipFlagsCache. get ();
Class <? Extends ChannelHandler> handlerType = handler. getClass ();
Int flagsVal;
Integer flags = cache. get (handlerType );
If (flags! = Null ){
FlagsVal = flags;
} Else {
FlagsVal = skipFlags0 (handlerType );
Cache. put (handlerType, Integer. valueOf (flagsVal ));
        }

Return flagsVal;
    }
 

/**
* Determines the {@ link # skipFlags} of the specified {@ code handlerType} using the reflection API.
*/
Static int skipFlags0 (Class <? Extends ChannelHandler> handlerType ){
Int flags = 0;
Try {
If (isSkippable (handlerType, "handlerAdded ")){
Flags | = MASK_HANDLER_ADDED;
            }
If (isSkippable (handlerType, "handlerRemoved ")){
Flags | = MASK_HANDLER_REMOVED;
            }
If (isSkippable (handlerType, "exceptionCaught", Throwable. class )){
Flags | = MASK_EXCEPTION_CAUGHT;
            }
If (isSkippable (handlerType, "channelRegistered ")){
Flags | = MASK_CHANNEL_REGISTERED;
            }
If (isSkippable (handlerType, "channelUnregistered ")){
Flags | = MASK_CHANNEL_UNREGISTERED;
            }
If (isSkippable (handlerType, "channelActive ")){
Flags | = MASK_CHANNEL_ACTIVE;
            }
If (isSkippable (handlerType, "channelInactive ")){
Flags | = MASK_CHANNEL_INACTIVE;
            }
If (isSkippable (handlerType, "channelRead", Object. class )){
Flags | = MASK_CHANNEL_READ;
            }
If (isSkippable (handlerType, "channelReadComplete ")){
Flags | = MASK_CHANNEL_READ_COMPLETE;
            }
If (isSkippable (handlerType, "channelWritabilityChanged ")){
Flags | = MASK_CHANNEL_WRITABILITY_CHANGED;
            }
If (isSkippable (handlerType, "userEventTriggered", Object. class )){
Flags | = MASK_USER_EVENT_TRIGGERED;
            }
If (isSkippable (handlerType, "bind", SocketAddress. class, ChannelPromise. class )){
Flags | = MASK_BIND;
            }
If (isSkippable (handlerType, "connect", SocketAddress. class, SocketAddress. class, ChannelPromise. class )){
Flags | = MASK_CONNECT;
            }
If (isSkippable (handlerType, "disconnect", ChannelPromise. class )){
Flags | = MASK_DISCONNECT;
            }
If (isSkippable (handlerType, "close", ChannelPromise. class )){
Flags | = MASK_CLOSE;
            }
If (isSkippable (handlerType, "deregister", ChannelPromise. class )){
Flags | = MASK_DEREGISTER;
            }
If (isSkippable (handlerType, "read ")){
Flags | = MASK_READ;
            }
If (isSkippable (handlerType, "write", Object. class, ChannelPromise. class )){
Flags | = MASK_WRITE;
            }
If (isSkippable (handlerType, "flush ")){
Flags | = MASK_FLUSH;
            }
} Catch (Exception e ){
// Shoshould never reach here.
PlatformDependent. throwException (e );
        }

Return flags;
    }
 

@ SuppressWarnings ("rawtypes ")
Private static boolean isSkippable (
Class <?> HandlerType, String methodName, Class <?>... ParamTypes) throws Exception {

Class [] newParamTypes = new Class [paramTypes. length + 1];
NewParamTypes [0] = ChannelHandlerContext. class;
System. arraycopy (paramTypes, 0, newParamTypes, 1, paramTypes. length );

Return handlerType. getMethod (methodName, newParamTypes). isAnnotationPresent (Skip. class );
    }
 

I believe that many netty beginners will encounter such problems. I hope this article will be helpful to you.

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.