当前位置: 首页 > 知识库问答 >
问题:

嵌入式tomcat 7 servlet 3.0注释无法工作

宰父衡
2023-03-14

我有一个精简的测试项目,其中包含一个Servlet3.0版本,使用如下注释声明:

    @WebServlet("/test")
public class TestServlet extends HttpServlet {

    private static final long serialVersionUID = -3010230838088656008L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
        response.getWriter().write("Test");
        response.getWriter().flush();
        response.getWriter().close();
    }
}
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

      <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>g1.TestServlet</servlet-class>
      </servlet>      

      <servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/testWebXml</url-pattern>
      </servlet-mapping>

</web-app> 

我尝试使用Embedded Tomcat7进行JUnit测试。启动嵌入式Tomcat时,只能通过web.xml(/testwebxml)中声明的URL模式访问servlet。如果我试图通过注释(/test)声明的URL模式访问它,它会说404页找不到。

下面是我测试的代码:

    String webappDirLocation = "src/main/webapp/";
    Tomcat tomcat = new Tomcat();
    tomcat.setPort(8080);

    tomcat.addWebapp("/jerseyTest", new File(webappDirLocation).getAbsolutePath());

    tomcat.start();
    tomcat.getServer().await();

为了确保正确设置了项目,我还安装了一个实际的Tomcat7并部署了WAR。这一次,web.xml声明的url和我的servlet的注释url都正常工作。

所以我的问题是:有人知道如何使嵌入式Tomcat7考虑我的Servlet3.0注释吗?

我还应该声明它是一个Maven项目,pom.xml包含以下依赖项:

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-catalina</artifactId>
        <version>7.0.29</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>7.0.29</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jasper</artifactId>
        <version>7.0.29</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.1</version>
        <scope>test</scope>
    </dependency>

这里有一个与此类似的问题(除了不起作用的Servlet3.0注释是在Listener上,而不是在Servlet上),它有一个建议的修复方法:

https://issues.apache.org/bugzilla/show_bug.cgi?id=53903

我试过了但没有用:

将嵌入的Tomcat开始代码更改为:

String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();

tomcat.enableNaming();
tomcat.setPort(8080);


Context ctx = tomcat.addWebapp(tomcat.getHost(), "/embeddedTomcat", new File(webappDirLocation).getAbsolutePath());
((StandardJarScanner) ctx.getJarScanner()).setScanAllDirectories(true);

tomcat.start();

tomcat.getServer().await();

将Maven依赖项更新到7.0.30版本

正在调试org.apache.catalina.startup.ContextConfig类。那里有检查@webservlet注释的代码,只是它从未被执行过(第2115行)。这可能是一个很好的方法来解决问题的根源,但是这个类是相当大的,我现在没有时间这样做。如果有人愿意看看这个类是如何工作的,以及在什么条件下(配置参数)它可以正确地检查项目的类中的注释,那么它可能会得到一个有效的答案。

共有1个答案

唐麒
2023-03-14

通过查看Tomcat7源代码,即处理EmbeddedTomcat和Servlet3.0注释的单元测试,我最终解决了这个问题。

基本上,您必须像这样启动嵌入式Tomcat7,以使它知道您的注释类:

String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);

StandardContext ctx = (StandardContext) tomcat.addWebapp("/embeddedTomcat",
                new File(webappDirLocation).getAbsolutePath());

//declare an alternate location for your "WEB-INF/classes" dir:     
File additionWebInfClasses = new File("target/classes");
VirtualDirContext resources = new VirtualDirContext();
resources.setExtraResourcePaths("/WEB-INF/classes=" + additionWebInfClasses);
ctx.setResources(resources);

tomcat.start();
tomcat.getServer().await();

为了清楚起见,我应该提到这适用于标准Maven项目,其中您的“Web资源”(如静态和动态页面、WEB-INF目录等)位于:

并且您的类被编译成

[项目的根目录]/target/classes

(这样您就有了[项目的根目录]/target/classes/[某个包]/someCompiledServletClass.class)

感谢@kwak注意到了这一点。

API发生了一些变化,以下是使用Embedded Tomcat 8时上面的示例的变化:

String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);

StandardContext ctx = (StandardContext) tomcat.addWebapp("/embeddedTomcat",
                new File(webappDirLocation).getAbsolutePath());

//declare an alternate location for your "WEB-INF/classes" dir:     
File additionWebInfClasses = new File("target/classes");
WebResourceRoot resources = new StandardRoot(ctx);
resources.addPreResources(new DirResourceSet(resources, "/WEB-INF/classes", additionWebInfClasses.getAbsolutePath(), "/"));
ctx.setResources(resources);

tomcat.start();
tomcat.getServer().await();
 类似资料:
  • 问题内容: 我有一个终结点实现,即将一个对象传递给参数列表。我正在尝试使用@NotNull批注来验证该对象是否为null。 如果该对象被验证为非null,则端点将仅返回200 OK响应。但是,当我使用指定的路径向该终结点发出请求时,体内没有任何内容时,不会引发任何错误。相反,我能够检索200响应(即使我在返回响应之前检查对象是否为null,也表明是这种情况)。 有人可以指导我如何以正确的方式验证对

  • 问题内容: 我可以在文件中保留这样的嵌入式注释吗? 我不希望在CSS输出中使用此注释。 问题答案: 在SASS中要考虑两种不同类型的注释。 单行注释将由.scss预处理器删除,并且不会出现在.css文件中。 多行注释是有效的CSS,在从.scss到您的.css文件的转换之间将保留*。 听起来内联注释是您想要的。

  • 我已经在我的项目中实现了Hilt依赖项,但是当我需要构造函数的@inject注释时,它就不起作用了。基本上,当我试图手动导入它时,我发现javax中的inject文件夹是空的。因此该结构类似于javax.inject。之后,我什么也得不到,因为inject文件夹是空的。我试过重建和清洁他的项目。我也尝试过使缓存无效,但似乎没有任何效果。我怎么才能让这起作用? 依赖项列表 刀柄版本-2.37

  • 问题内容: 我需要定义一个切入点,该切入点触发使用自定义注释注释的spring服务的所有方法的执行。我想定义切入点的注释将在另一个注释上。 然后该服务将被注释如下 我尝试使用以下切入点定义,但是仅当@Y在服务本身上时才有效,这意味着它看不到注释在@X上 问题答案: 我在应用程序中有这个确切的需求。我找到了这个答案,但不满意无法完成。 经过更多搜索之后,我发现了用于AspectJ / Spring切

  • 无法用[class java.lang.String]注入@test注释方法[launchB]. 下面是代码:

  • 问题内容: 我在属性文件中定义了一个属性: 然后,我有了class, 仅 当属性设置为true时, 才 应 创建一个Property Configuration bean 。 __ 这是我的课: 如果我在里面添加,只是为了进行实验并查看的值是多少,那么 确实 创建了bean , 并且我看到的值是。 如果我删除了,留下的条件作为和属性更改来自于豆,从未创建(既不也不对)。 我应该怎么做才能基于该属性