Tomcat如何识别使用注解指定的Servlet?

3
在servlet 3.0之前,需要通过在web.xml中提供url模式和servlet类来配置servlet。每当发送servlet的请求时,Tomcat会在web.xml中搜索servlet类,并根据请求类型调用doget或dopost。 在servlet 3.0中,我们可以使用注释(如@WebServlet)在servlet类中自行配置servlet。 我的问题是,在这种情况下Tomcat如何识别servlet类,因为在web.xml中没有为servlet指定映射。 提前感谢您的帮助。

1
试着在谷歌上搜索“注解扫描”。 - Evan Knowles
1
通过实现 Processor 接口。 - Luiggi Mendoza
2
请查看:构建自己的注解处理器 - Luiggi Mendoza
1
@LuiggiMendoza 这是在运行时调用的吗?我之前以为它只是编译时的工具。 - chrylis -cautiouslyoptimistic-
@chrylis 注解可以在编译时(查看项目 Lombok)或运行时(例如 servlet 的 @WebServlet 或 JS - Luiggi Mendoza
@LuiggiMendoza 是的,它们可以在运行时以一般意义上进行“处理”,但据我所知,Processor接口仅在编译时使用,而在运行时使用其他反射策略。您是否有关于在运行时使用它进行处理的文章? - chrylis -cautiouslyoptimistic-
2个回答

8
Tomcat扫描Web应用程序的类文件(包括WEB-INF/classes和JAR中的类文件)。然后将这些类文件传递给经过重度编辑、包重命名的Apache Commons字节码工程库(BCEL)的本地副本。Tomcat版本的BCEL被优化为仅处理Tomcat感兴趣的那部分字节码(注释、超类(如果有)、实现的接口),并尽可能快地跳过其他部分。BCEL直接从磁盘读取类文件。
Tomcat对来自BCEL的结果进行了一些仔细的缓存,以便即使对于最复杂的类层次结构,每个类也只会被处理一次,并且不需要进行任何后处理即可获取所有类的完整注释列表(包括从超类继承的注释)。
注释扫描还检查与SCIs的@HandlesTypes注释匹配的情况。
无论如何,扫描每个类的注释都是昂贵的(这也是我不喜欢这个特定功能的原因之一)。在采用高效实现之前,Tomcat的实现经历了多次迭代。

谢谢你提供更详细的信息,Thomas。我在谷歌上看了很多帖子,但没有找到令人满意的描述。你知道哪里有完整解释的文档吗? - sumant.raj
有趣的是... 我真的不知道Tomcat用户使用BCEL而不是反射API来进行注释解析。 - AlexR
@sumant.raj 它被称为“开放源代码”是有原因的。您需要使用 org.apache.catalina.startup.ContextConfig 类。 - Mark Thomas

5
它扫描您的Web应用程序部署中classes目录下的所有jar文件和类文件,使用类似于clazz = Class.forName(theClassName)的代码获取类,然后调用clazz.getDeclaredAnnotations()clazz.getAnnotation(WebServlet.class)。然后它读取注释的属性以提取servlet映射。
这种方式容器可以找到所有的servlet、过滤器等及其URL映射。这是此基于注释的API推出后应用程序部署需要更长时间的原因之一。
显然,代码并不像我解释的那么简单。例如,它在Web应用程序的专有类加载器上下文中加载类。它也不会真正调用Class.forName(),而是将类作为字节数组加载,并将其传递给类加载器。

谢谢提供信息。您知道有哪些链接或书籍可以提供详细的信息吗? - sumant.raj
这意味着注解将被Tomcat转换为web.xml映射吗? - sumant.raj
不对。即使是你的非简单解释也完全偏离了实际情况。Web应用程序类加载器根本不参与加载过程。 - Mark Thomas
@sumant.raj,注解用于提取与web.xml中提取的相同(或类似)信息。 - AlexR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接