这几年restful非常流行,稍微了解了一下,感觉最有趣的就是那个无状态。以我目前的认知来理解一下什么是状态:比如用户已经登录,这就是一个状态。而之前传统的web应用是如何判断用户已经登录的呢?一般来说是在登录的action执行时将userId存入session对象中。那么之后的action调用前判断一下session中是否存在userId(可以用拦截器interceptor实现,方便点),就可知道用户是否已经登录了。每个用户的连接到服务器后都会在服务器上保持一个session,因此session是存在很多很多个的。而web容器比如tomcat之类的是怎么找到对应的session的呢?这就是通过sessionId来找到的。在使用tomcat+ssh的技术开发时,我们并不会察觉到sessionId的存在,比如获取session时并不需要传入sessionId。但是实际上它是有的,比如在浏览器的cookie里,我们可以发现一个叫JSESSIONID的东东。这就是sessionId了。当请求到达服务器时,就会根据这个sessionId找到对应的session。而要是在浏览器清除了cookie,则JSESSIONID就没了,那么服务器则会新建一个session对象出来,关联到当前线程。很自然的这个新的session对象中不会存在userId,因此用户登录状态就丢失了。同时如果客户端长时间没有连接到服务器,那么服务器保存的session对象会被销毁掉(时间长短视配置而定)。如果session不会被序列化到磁盘或者保存到数据库,那么重启服务器也有可能丢失session。

以上就是将状态保存在服务器的机制。那么无状态的意思就是不要让服务器来维持这个状态。服务器维持状态靠的是session,实现判断连接状态的是靠存在session里的某些东西比如当前登录用户id。首先要明确一点,session不管咱们用不用,它都是存在那的。 我们能做的只是可以不往session里存东西。有一点要搞清楚,无状态的目的是不要让服务器来保持状态(以利于分布式部署),而不是说服务器上不允许存在状态。如果是这样理解的话就悲剧了,之前我就是没想通这点而走进了死胡同。 也就是说并不是不允许使用session!明白这一点就好办了,比如要是服务器能根据客户端请求恢复session中的内容呢?那么问题就解决了!

前面说到过,服务器是如何识别出状态的,比如是通过能否从session中获取userId来判断。那么要恢复状态,只需要往session中重新存入userId即可。当然,肯定需要一些条件能识别出客户端是登陆过的。这个条件是什么呢?说实话之前一直傻乎乎没想到,直到前段时间使用了阿里云oss,它就是一个restful服务。在使用它的生成授权访问URL时我发现了一些额外的参数,一个是AccessKey,一个是根据某种算法得出的签名字符串。而阿里云服务的调用需要accessKey和accessSecret。瞬间受到启发了,accessKey和accessSecret不就是userId和userPassWord吗?只需要在客户端请求的时候把userId和签名带上,就可以认为是把状态带上了。而且因为不像阿里云的签名是对外公开的,只具备时限效果,我可以弄一个一直有效的签名,反正这个签名只会服务器和用户自己才知道。至于签名的生成,我是完全随机的,并且签名与userId的对应关系存在于数据库中。

那么结果就只需要在用户登录后往cookie中存入userId和签名,再配合拦截器去实现认证,就轻松简单的实现了无状态。