http://download.oracle.com/otn-pub/jcp/servlet-3.0-fr-oth-JSpec/servlet-3_0-final-spec.pdf
这将在第12章:将请求映射到Servlet。我查看了JBoss的Maven存储库,虽然spec接口可用,但我似乎无法找到关于servlet url模式匹配的12.1和12.2的底层实现。我有兴趣检查表达式如何映射到另一个项目的规则。
答案 0 :(得分:3)
我正在考虑Tomcat 7.0.42。以下链接回答指向grepcode.com中的7.0.42源代码。
servlet映射在应用程序启动时解析并在org.apache.tomcat.util.http.mapper.Mapper#addWrapper()
内添加Wrapper
,其源代码在这里被复制(注意:术语“包装器”在这里基本上代表“映射的servlet”):
360 protected void addWrapper(ContextVersion context, String path,
361 Object wrapper, boolean jspWildCard, boolean resourceOnly) {
362
363 synchronized (context) {
364 Wrapper newWrapper = new Wrapper();
365 newWrapper.object = wrapper;
366 newWrapper.jspWildCard = jspWildCard;
367 newWrapper.resourceOnly = resourceOnly;
368 if (path.endsWith("/*")) {
369 // Wildcard wrapper
370 newWrapper.name = path.substring(0, path.length() - 2);
371 Wrapper[] oldWrappers = context.wildcardWrappers;
372 Wrapper[] newWrappers =
373 new Wrapper[oldWrappers.length + 1];
374 if (insertMap(oldWrappers, newWrappers, newWrapper)) {
375 context.wildcardWrappers = newWrappers;
376 int slashCount = slashCount(newWrapper.name);
377 if (slashCount > context.nesting) {
378 context.nesting = slashCount;
379 }
380 }
381 } else if (path.startsWith("*.")) {
382 // Extension wrapper
383 newWrapper.name = path.substring(2);
384 Wrapper[] oldWrappers = context.extensionWrappers;
385 Wrapper[] newWrappers =
386 new Wrapper[oldWrappers.length + 1];
387 if (insertMap(oldWrappers, newWrappers, newWrapper)) {
388 context.extensionWrappers = newWrappers;
389 }
390 } else if (path.equals("/")) {
391 // Default wrapper
392 newWrapper.name = "";
393 context.defaultWrapper = newWrapper;
394 } else {
395 // Exact wrapper
396 if (path.length() == 0) {
397 // Special case for the Context Root mapping which is
398 // treated as an exact match
399 newWrapper.name = "/";
400 } else {
401 newWrapper.name = path;
402 }
403 Wrapper[] oldWrappers = context.exactWrappers;
404 Wrapper[] newWrappers =
405 new Wrapper[oldWrappers.length + 1];
406 if (insertMap(oldWrappers, newWrappers, newWrapper)) {
407 context.exactWrappers = newWrappers;
408 }
409 }
410 }
411 }
在处理传入的HTTP请求时,通过映射查找servlet的所有魔力都始于org.apache.catalina.connector.CoyoteAdapter#postParseRequest()
。
647 connector.getMapper().map(serverName, decodedURI, version,
648 request.getMappingData());
649 request.setContext((Context) request.getMappingData().context);
650 request.setWrapper((Wrapper) request.getMappingData().wrapper);
第647行间接调用org.apache.tomcat.util.http.mapper.Mapper #internalMapWrapper()
,这是使用Context
和Wrapper
(本质上是可用的servlet实例)填充当前HTTP请求的映射数据的地方。它只是相当多的代码,我不会在这里复制它,只需单击grepcode链接即可。
然后,第649行和第650行基本上设置了当前请求中的映射Context
和Wrapper
。 Context
保存具体的ServletContext
实例,Wrapper
保存具体的Servlet
实例作为属性org.apache.catalina.core.Wrapper#instance
。
最后,在调用所有过滤器之后,ApplicationFilterChain
将调用servlet的service()
方法。
对于我自己的项目OmniFaces JSF utility library,我曾根据WebXml
实用程序类中的servlet规范12.1(以相当简化的形式)实现了匹配检查。这些也可能对您有帮助,source code is here,以下相关摘录:
private static boolean isExactMatch(String urlPattern, String url) {
return url.equals(urlPattern.endsWith("/*") ? urlPattern.substring(0, urlPattern.length() - 2) : urlPattern);
}
private static boolean isPrefixMatch(String urlPattern, String url) {
return urlPattern.endsWith("/*") ? url.startsWith(urlPattern.substring(0, urlPattern.length() - 2)) : false;
}
private static boolean isSuffixMatch(String urlPattern, String url) {
return urlPattern.startsWith("*.") ? url.endsWith(urlPattern.substring(1)) : false;
}
答案 1 :(得分:-2)
这取决于模式匹配发生的位置。如果你要让JBoss(真的是Tomcat,Mohammad对此非常正确)处理Web.xml中的所有url映射并仅设置这些映射来处理特定端点上的请求,那么org.apache.naming可能就足够了为了你的目的。
虽然,我可能会跳到NamingContext.java作为开始的好地方。并不是特别令人兴奋它处理它,因为你想象它将使用HashMap作为名称关联(绑定)和HashTable用于对象关联(上下文环境),这仍然是绑定和查找发生的地方。
但是,如果您希望通过前端控制器处理自己的路由,或者想要动态重定向或重新映射,那么Tomcat 8 Servlet 3.0 API文档可能更符合您的要求,它也是您在问题中要求的实施信息。
希望有所帮助。