Servlet的处理顺序与规则

Mewchan介绍
Playground(HTTP与WebSocket服务)
Servlet定义

首先Servlet整体分为两个过程:before与after。当一个请求进入到Servlet处理链中的时候,将会按照请求的URL分析目前所有已经注册了的Servlet列表中,提取出符合路径申明的Servlet集合,然后按照由粗旷到细致的顺序执行before序列,然后再反向执行after序列的Servlet。最后将Servlet的处理结果返回。同时,处理序列也可以在中间环节直接拦截中断后续的Servlet处理链路。

以下,对上述过程进行了一个简单的举例:

// http://talk.mewchan.com/lab.upload.download?36a27706-4d7d-40b2-8c11-6e0aac64059c
// 上述URL的处理顺序将按照如下的处理顺序进行:

@servlet.before("//*", ...); // 第一步:处理URL [http://talk.mewchan.com//*]
@servlet.before("/lab.upload.download", ...); // 第二步:处理URL [http://talk.mewchan.com/lab.upload.download]
@servlet.after("/lab.upload.download", ...); // 第三步:处理URL [http://talk.mewchan.com/lab.upload.download]
@servlet.after("//*", ...); // 第四步:处理URL [http://talk.mewchan.com//*]

通常情况下,before步骤是用来处理HTTP请求HEAD数据的,无论处理,还是设置,都会通过before过程来进行,这样可以确保在最终处理BODY请求前,分析和输出完所有需要的HEAD信息数据,因为在开始正式输出BODY之后,HEAD数据将无法再进行任何补充,同时before过程也可以确保多个路径分析HEAD时的多重输出可能。

Servlet路径的表示,则按照了@.as(path, "regex-path")的规则来进行分析。常用规则一般只有以下的两条:

以上两条规则可以确保基本大部分情况下的路径分析正确,以下是对于路径分析的案例:

// 以下是一些可以参照的路径测试情况

let tester = @.as("//a.bc", "regex-path");
@dump(tester.test("/a.bc")); // true
@dump(tester.test("/d/a.bc")); // true
@dump(tester.test("/d/e/a.bc")); // true
@dump(tester.test("/b.bc")); // false
@dump(tester.test("/a.bc/d")); // false

let tester2 = @.as("/*.bc", "regex-path");
@dump(tester2.test("/b.bc")); // true
@dump(tester2.test("/abc.bc")); // true
@dump(tester2.test("/a.b.bc")); // true
@dump(tester2.test("/a/b.bc")); // false
@dump(tester2.test("/a.bcd")); // false

另外,一般情况下//*代表了,任何路径都允许的情况。

最后,这里需要确定申明的是Servlet路径的顺序排列规则,也即当两个路径比对都成功的时候(同时为before,或者after),如何确定Servlet的调用顺序问题。前文只是描述了一个最基本、但很粗略的主观意见(before过程里从粗旷到细致,after过程里反向)。这里将对这个顺序的安排和计算提供详细的定义:

每一个路径规则都会对应一个分数。分数的计算中,分别会统计以下的三个数据:

最后的分数计算按下方的公式既可以得到:

score = paths + asterisks * 100 + components * 10000

计算得到的分数越大,则结果越细致,反之则越粗旷。根据这个分数,对before和after的servlet序列进行排序,并按照前文所述的规则,进行servlet链式调用过程。

最后更新时间:2018年10月30日 10:55:29