前一段时间,我们讲了很多StandardContext的属性,内部组件。
但是在StandardContext属性中,我们还可以定义一些Nest Components节点,和内部组件一样,也可以定义在StandardContext的节点下面:

这些嵌套组件一般都有什么呢?

这么多。
而在StandardContext中,可以配置的嵌套组件有:

从这一篇文章开始,我们开始分析这些Nested Components,先从CookieProcessor。
该标签可以定义在Tomcat的核心容器的几个级别中。
1.RFC规范
首先,我们来看一下RFC的规范,对于cookie在http协议的制定是有规范所依据的,其主要是两个规范:
第一个是 http://www.rfc-editor.org/rfc/rfc2616.txt HTTP11规范,该规范的重要性就不用说了;
第二个是 http://www.rfc-editor.org/rfc/rfc2109.txt RFC2109规范,该规范定义了http的状态保存和管理,如下:

在该规范中,定义了如何使用cookie来定义session会话信息,还有浏览器agent和服务器端交互的内容:

我们了解到的是,二者是通过请求和响应头参与整个http会话的交互的;
本规范还定义了这些字段,如set-cookie,等属性怎么写,有没有=号之类的细节定义。
RFC2109规范定义的很早,那时候的互联网浏览器格局还是netscape和IE一争天下,而其实cookie这块大多数都是由netscape指定的,而现如今浏览器厂家已经发生了翻天覆地的变化,netscape早就没了,而IE现在也苟延残喘,虽然预装到Windows中,大家很少有人用它的,这样就给了RFC2109规范来了一次新版本的更新,也就是 http://www.rfc-editor.org/rfc/rfc6265.txt
RFC6265规范重新编辑了一下 RFC2109规范,改了一些东西:

这些东西,其实Tomcat的配置文档中总结的挺好的,总体来说,是更加的宽泛了,在一些字段的条件限制上,没有RFC2109规范限制的那么死,这其实也是兼容目前各种浏览器中的程序和代码,也算是对市场的一种妥协:

如Tomcat中的RFC6265CookieProcessor,就是对新规范的支持,这里面我们看到了lenient的词汇,其词义就是宽松了很多,如下面说的,= /可以作为cookie的value,cookies没有value是可以的,cookie header是可以保存的等等。
。。。
总之,RFC6265新规范更加贴近市场需求和目前浏览器的情况,而Tomcat 8以后其实也推荐配置这个RFC6265CookieProcessor替代原有的cookieprocessor:

2.CookieProcessor实现类与核心流程
我们来看看CookieProcessor的配置。
通用属性:

className是CookieProcessor的接口的实现类,在Tomcat中CookieProcessor:

主要是两个方法,在Request中进行parseCookieHeader,在Response中进行generatHeader:

对于CookieProcessor一共有两个实现类,一个是基于RFC2109规范的,这个也就是Tomcat早期(8之前的)的最常用的CookieProcessor,就是LegacyCookieProcessor:

而新规范自从Tomcat8开始之后(2011年之后),RFC6265CookieProcessor就占主导了,在Tomcat8013之后,作为Default的CookieProcessor。
我们看看Request和Response的这两个方法,以LegacyCookieProcessor实现类为例:

至于ProcessorCookieHeader究竟是干什么的,这个方法其实就是逐字节的进行读取header体中的cookie部分,这里截取一小段代码,大家看看:

实际就是字符串解析,算偏移嘛,按照规范做事,这个我觉得没什么难度;
对于Response中addCookie实际一个道理,其实也是对于规范的实现,只不过我们需要关注一下,什么时候addCookie触发呢?
一种类型是你自己在服务端没事进行addCookie,这种就由客户端自己控制了,Cookie里面有啥我就不知道了;
第二种是Tomcat的session机制,我们在预研Session这块的时候,session除了url重写之外,还可以采用cookie:

上述的代码中,ApplicationSessionCookieConfig.createSessionConfig这个方法,我们前面重点分析过,Session对象是如何搞到Cookie中的,而下一步其实就是调用CookieProcessor组件按照RFC的格式,往客户端进行写了
3.CookieProcessor实现类配置
Standard Implementation
The standard implementation of CookieProcessor isorg.apache.tomcat.util.http.LegacyCookieProcessor
. Note that it is anticipated that this will change to org.apache.tomcat.util.http.Rfc6265CookieProcessor
in a future Tomcat 8 release.
This is the legacy cookie parser based on RFC6265, RFC2109 and RFC2616. It implements a strict interpretation of the cookie specifications. Due to various interoperability issues with browsers not all strict behaviours are enabled by default and additional options are available to further relax the behaviour of this cookie processor if required.
从这些属性的设置上来看,system.property中的定义和下面的配置是重合的
| Attribute | Description |
|---|---|
allowEqualsInValue | If this is 该属性指示cookie的value中能不能用=号 If not set the specification compliant default value of |
allowHttpSepsInV0 | If this is 该属性指示cookie的名字和value之间是否可以用分隔符号 If not specified, the default specification compliant value of |
allowNameOnly | If this is 有的cookie一个名字就够了(主要是true和false,没写就是true),新规范才允许 If not set the specification compliant default value of |
alwaysAddExpires | If this is 对于是否过期,Max-Age其实就能很好的表达,但是IE6,7非要用Expire字段,挺垃圾的,还得兼容这个 If |
forwardSlashIsSeparator | If this is 该属性是value中是否允许 /,老规范不可以,新规范可以,这个就是一个配置 If |
preserveCookieHeader | This attribute is no longer used. 已废弃,该属性的意思是是否需要保存cookieheader(在服务器端缓存) From Tomcat 8.0.31, Tomcat will always preserve the cookie header returned by |
虽然,目前的Tomcat新版本的CookieProcessor都已经迁移到了RFC6265CookieProcessor新规范上了,但对于上述的细则你有的还想兼容老规范,那么你配置一下就可以了;
我们以alwaysAddExpires这个属性作为代表性属性,看看人家咋实现的,说白了其实这个属性就是给IE6,7下一个台阶,Max-Age字段好好的能代表是否过期,IE非要搞一个Expire,真是没事闲的啊:

总结:
本文从RFC的规范来源开始讲起,最后到Tomcat是怎么实现新老规范的,CookieProcessor可以用于自己程序中addCookie,也可以默认将Session信息按照规范进行转化为Cookie(另一种session实现为url重写);




