当前位置: 首页 > 编程笔记 >

java 中 ChannelHandler的用法详解

马安邦
2023-03-14
本文向大家介绍java 中 ChannelHandler的用法详解,包括了java 中 ChannelHandler的用法详解的使用技巧和注意事项,需要的朋友参考一下

java 中 ChannelHandler的用法详解

前言:

ChannelHandler处理一个I/O event或者拦截一个I/O操作,在它的ChannelPipeline中将其递交给相邻的下一个handler。

通过继承ChannelHandlerAdapter来代替

因为这个接口有许多的方法需要实现,你或许希望通过继承ChannelHandlerAdapter来代替。

context对象

一个ChannelHandler和一个ChannelHandlerContext对象一起被提供。一个ChannelHander通过一个context对象和其所属的那个ChannelPipeline进行交互。使用context对象,ChannelHandler可以向上或者向下传递events,动态修改pipeline,或者存储与handler相关的信息(使用AttributeKeys)。

状态管理

一个ChannelHandler经常需要存储一些状态相关的信息。最简单和推荐的方法是使用成员变量:

public interface Message {
  // your methods here
}

public class DataServerHandler extends SimpleChannelInboundHandler<Message> {

  private boolean loggedIn;

  @Override
  protected void messageReceived(ChannelHandlerContext ctx, Message message) {
    Channel ch = e.getChannel();
    if (message instanceof LoginMessage) {
      authenticate((LoginMessage) message);
      loggedIn = true;
    } else (message instanceof GetDataMessage) {
      if (loggedIn) {
        ch.write(fetchSecret((GetDataMessage) message));
      } else {
        fail();
      }
    }
  }
  ...
}

因为handler实例有一个状态变量专注于一个连接,你必须为每一个handler实例创建一个新的handler实例,来避免竞态的情况以至于未认证的客户端可以获得机密的信息:

// Create a new handler instance per channel.
// See ChannelInitializer.initChannel(Channel).
public class DataServerInitializer extends ChannelInitializer<Channel> {
  @Override
  public void initChannel(Channel channel) {
    channel.pipeline().addLast("handler", new DataServerHandler());
  }
}

使用AttributeKeys

虽然使用成员变量来保存一个handler的状态是被推荐的,然而,由于一些原因你或许不想创建很多的handler实例。在这种情况下,你可以使用附在ChannelHandlerContext上的AttributeKeys:

public interface Message {
  // your methods here
}
@Sharable
public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
  private final AttributeKey<Boolean> auth =
     AttributeKey.valueOf("auth");
  @Override
  protected void messageReceived(ChannelHandlerContext ctx, Message message) {
    Attribute<Boolean> attr = ctx.attr(auth);
    Channel ch = ctx.channel();
    if (message instanceof LoginMessage) {
      authenticate((LoginMessage) o);
      attr.set(true);
    } else (message instanceof GetDataMessage) {
      if (Boolean.TRUE.equals(attr.get())) {
        ch.write(fetchSecret((GetDataMessage) o));
      } else {
        fail();
      }
    }
  }
  ...
}

现在handler的状态被附在了ChannelHandlerContext上了,你可以添加同样的Handler实例到不同的pipeline上:

 public class DataServerInitializer extends ChannelInitializer<Channel> {

   private static final DataServerHandler SHARED = new DataServerHandler();

   @Override
   public void initChannel(Channel channel) {
     channel.pipeline().addLast("handler", SHARED);
   }
 }

@Sharable 注解

在上面使用AttributeKey的例子中,你应该已经注意到了@Sharable注解。

如果一个ChannelHandler被注解为@Sharable,那意味着你可以只创建一个handler实例,并把它添加到一个或多个ChannelPipeline中多次,并不用考虑竞态的情况。

如果这个注解没有指定,你就只能为每次需要添加到pipeline中的handler,每次创建一个新的实例。因为它有非共享的状态,比如:成员变量。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

 类似资料:
  • 本文向大家介绍详解Java中final的用法,包括了详解Java中final的用法的使用技巧和注意事项,需要的朋友参考一下 概念 final 具有“不可改变的”的含义,可以修饰 非抽象类、非抽象成员方法和变量。 用 final 修饰的类不能被继承,没有子类。 用 final 修饰的方法不能被子类的方法覆盖(重写)。 用 final 修饰的变量表示常量,只能被赋一次值(声明变量的时候)。 注: fi

  • 本文向大家介绍Java中isAssignableFrom的用法详解,包括了Java中isAssignableFrom的用法详解的使用技巧和注意事项,需要的朋友参考一下 class1.isAssignableFrom(class2) 判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回 true;否则返回 false。如果该

  • 本文向大家介绍java中stringBuilder的用法详解,包括了java中stringBuilder的用法详解的使用技巧和注意事项,需要的朋友参考一下 String对象是不可改变的。每次使用System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的String对象相关的系统开销可能会非常昂贵。如

  • 本文向大家介绍Java中DecimalFormat用法详解,包括了Java中DecimalFormat用法详解的使用技巧和注意事项,需要的朋友参考一下 我们经常要将数字进行格式化,比如取2位小数,这是最常见的。Java 提供DecimalFormat类,帮你用最快的速度将数字格式化为你需要的样子。下面是一个例子: DecimalFormat 类主要靠 # 和 0 两种占位符号来指定数字长度。0 表

  • 本文向大家介绍Java 中 Reference用法详解,包括了Java 中 Reference用法详解的使用技巧和注意事项,需要的朋友参考一下 Java  Reference详解 在 jdk 1.2 及其以后,引入了强引用、软引用、弱引用、虚引用这四个概念。网上很多关于这四个概念的解释,但大多是概念性的泛泛而谈,今天我结合着代码分析了一下,首先我们先来看定义与大概解释(引用类型在包 Java.la

  • 本文向大家介绍Java 中This用法的实例详解,包括了Java 中This用法的实例详解的使用技巧和注意事项,需要的朋友参考一下  Java 中This用法的实例详解 用类名定义一个变量的时候,定义的只是一个引用,外面可以通过这个引用来访问这个类里面的属性和方法。     那们类里面是够也应该有一个引用来访问自己的属性和方法纳?     呵呵,Java提供了一个很好的东西,就是 this 对象,