且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

消息字节——MessageBytes

更新时间:2022-08-14 22:14:24

在tomcat核心处理中有这么一个需求——“为了提高编码性能,对于socket接收到的字节流不马上进行某种编码的转码,而是应该保留字节流的形式,在需要时、在指定编码时才进行转码工作”。MessageBytes正是为解决这个问题而提出的一个类。

消息字节封装了不同类型方式用于表示信息,它包含了四种类型:T_BYTES、T_CHARS、T_STR、T_NULL,分别表示字节类型、字符类型、字符串类型、空。由于web服务器通信过程使用ASCII码通信,对应的是字节,所以这里选取T_BYTES类型作为案例说明,其他类型与之类似。消息字节的使用方法很简单,假如有一个字节数组byte[] buffer,它坐标的第3到第20之间的字节数组组成的字符表示Request对象中的方法变量的值,那么用以下代码简单表示:

①   public class Request{

MessageBytes methodMB = new MessageBytes();

 

public MessageBytes method() {

        returnmethodMB;

    }

}

②   Request request = new Request();

request.method().setBytes(buffer, 3, 18);

 

执行上面操作后就完成对字节数组的某段进行标记操作,方便以后获取指定的一段字节数组,参照下图,你可以用多个消息字节对buffer标记,例如对请求变量、协议版本等变量进行标记,每个消息字节实例标识了一段字节数组,可以通过如下获取并转为字符串类型:

request.method().toString();

 

消息字节——MessageBytes

使用起来很简单,接着看下实际实现原理,化繁为简,由于tomcat底层接收的是字节流,于是只考虑T_BYTES的情况。

①   MessageBytes类

public class MessageBytes {

         private finalByteChunk byteC = new ByteChunk();

 

         public voidsetBytes(byte[] b, int off, int len) {

                   byteC.setBytes(b,off, len);

         }

 

         public StringtoString() {

                   returnbyteC.toString();

         }

}

②   ByteChunk类

public class ByteChunk {

         privatebyte[] buff;

         private intstart = 0;

         private intend;

 

         public voidsetBytes(byte[] b, int off, int len) {

                   buff= b;

                   start= off;

                   end= start + len;

         }

 

         public StringtoString() {

                   Charsetcharset=Charset.forName("ISO_8859_1");

                   CharBuffercb = charset.decode(ByteBuffer.wrap(buff, start, end - start));

                   returnnew String(cb.array(), cb.arrayOffset(), cb.length());

         }

}

 

前面示例中methodMB.setBytes(buffer, 3, 18)其实是调用了ByteChunk的setBytes方法,把字节流及始末坐标设置好,后面methodMB.toString()同样调用了ByteChunk的toString方法,根据指定编码进行转码,这里是ISO_8859_1。这样一来就达到了延迟处理模式的效果,在需要时才根据指定编码转码并获取字符串,不需要的话则无需转,处理性能得到提高。

Tomcat对于socket接收的信息都用消息字节表示,好处是实现一种延迟处理模式,提高性能。而且实际上tomcat还引入了字符串缓存,在转码之前会先从缓存中查找是否有对应的编码的字符串,如果存在则不必再执行转码动作而直接返回对应的字符串,性能进一步得到优化。为了性能我们必须要多做一些额外的工作,这也是tomcat接收到的信息为何不直接用字符串String保存的原因。


点击订购作者《Tomcat内核设计剖析》