对于web.xml文件的解析所使用的Rule为WebRuleSet类,查看其addRuleInstances可得知其设置的具体Rule内容,如下:
在解析之前该Digester将StandardContext实例push到Stack里,因此解析完的所有对象均会放到该Context里或其子对象里
1. 设置context-param,如下:
其中需要注意的是addCallMethod方法加入了CallMethodRule类,该类是用于对位于栈顶的对象调用方法的,一般需要给出调用方法时参数的个数,参数的类型都是String类型
当参数个数为空时,将以标签体内容做为参数,如果参数个数不为空,则还需要继续添加设置个数的Rule,如上
2.EJB的调用,如下:
尽管TOMCAT不是一个EJB容器,但依然有支持其对EJB的调用,那应该是必然的吧,不然就太OUT了
3.设置本Context将使用的Name Context相关的信息,如下
这里将构建org.apache.catalina.deploy.ContextEnvironment对象,放入到StandardContext所持有的namingResources对象里
4.Filter配置
可以看到
这里将调用StandardContext.addFilterDef方法,内容如下:
filterDefs为一个HashMap,参数filterDef需要有FilterName,我们可以看到该名字是要在web.xml配置的,但调用这个方法的时候名字做了配置没呢?我们看到上面有一段如下的代码:
这里便设置了FilterName,但这语句是在addSetNext后加入的,到底是在addFilterDef方法调用之前还是之后运行呢?当然是之后运行的啦,因为addSetNext是在结束标签的时候执行该方法的,因此其实该方法是在解析</Filter>时才执行的,当然也在setFilterName之后执行的,这个机制真的是太厉害了,也不知当时tomcat的工程师花了多长时间想到这个的:)
另一个值得称道的地方在这
当要设置<init-param>或<context-param>,便会这样处理,开始的时候设置一个两个参数的CallMethodRule,该RULE的begin方法会产生一个长度为2的参数数组,放到栈里,如下
body方法如下,这个主要是设置了参数个数为0的,要用标签体内容做为参数
end方法如下:
如果参数个数大于0,则使用栈顶的参数数组;如果个数为0,则新产生长度为1的参数数组,并将值设置为标签体内容,最后调用目标上(参数数组之前放入栈的对象)的相应方法.
有趣的地方有两点:
1.如果设置了个数大于0,则后续需要再加RULE设置参数的值,通过给出参数索引来对具体的参数赋值.
2.调用目标方法时是使用反射机制实现的,反射机制调用对象上方法刚好使用的是参数数组,与这个实现不谋而合
与Filter一致,剩余的部分还有加入<filter-mapping>
5.设置Lintener的相关信息
略过,后续再讲
6.设置jsp-config
不太常用,略过
7.设置用户使用系统的角色及权限控制
产生了LoginConfig类,并设置到StandardContext的loginConfig对象里
.....
产生了SecurityConstraint对象,设置到StandardContext的SecurityConstraint数组
产生了SecurityCollection对象,代表的是一组权限被保护的路径对象,它将被放入到SecurityConstraint所持有的SecurityCollection数组
6.设置将调用到的web service
7.servlet的设置
WrapperCreateRule将调用context.createWrapper方法,该方法将产生StandardWrapper对象,并为其设置应有的监听器,该类构造器如下:
之后有调用StandardWrapper.addInitParameter加入初始化参数,设置jspFile,load-on-startup,run-as,servlet-class
接着将调用StandardContext.addServletMapping设置servletMapping,该方法如下:
参数name即为所配置的servlet-name,首先校验一下该servlet是否进行了配置findChild(name),没有进行配置则直接退出,接着对配置的url-pattern进行一些转义,接着一段查看是否该pattern已有对应的servlet配置,如果有的话只让最新的servlet对应该pattern,// Don't allow more than one servlet on the same pattern
调用wrapper.addMapping(String pattern),再更新Context的Mapper,该对象将用于与客户端请求进行匹配来确定由哪一个servlet处理该请求.addMapping方法如下:
最令人难以忘怀的是这里的context并不是前面的StandardContext实例,而是一个Mapper类挂有的一个对象属性,被雷到,我们再看一下这个方法里面
new Wrapper()语句实例化的竟然不是如StandardWrapper,而是一个Mapper内部类,又被雷到;为何要在Mapper类里新增这么两个名字与前面对象父类一样的名字,除了扰乱别人的视线外是否还有其它意图,暂不得其解啊,可能需要我们后续在讲如何查找客户请求所对应的servlet才能搞明白吧:)
最后调用addChild将产生的StandardWrapper对象加入到StandardContext里
tomcat解析(十四)web.xml解析
最新推荐文章于 2023-07-07 16:36:46 发布