嵌入式tomcat 7 servlet 3.0注释无法正常工作 [英] Embedded tomcat 7 servlet 3.0 annotations not working

查看:287
本文介绍了嵌入式tomcat 7 servlet 3.0注释无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a stripped down test project which contains a Servlet version 3.0, declared with annotations like so:

    @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.xml文件,如下所示:

I also have a web.xml file like so:

<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> 

我尝试使用嵌入式Tomcat 7进行JUnit测试。当我启动嵌入式Tomcat时只能通过web.xml(/ testWebXml)中声明的url-pattern访问servlet。如果我尝试通过注释(/ test)声明的url-pattern访问它,则找不到404页面。

I've tried to make a JUnit test using Embedded Tomcat 7. When I start the Embedded Tomcat I can only access the servlet via the url-pattern declared in web.xml (/testWebXml). If I try to access it via the url-pattern declared via annotation (/test) it sais 404 page not found.

这是我测试的代码:

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

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

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

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

Just to make sure I've set up my project correctly, I've also installed an actual Tomcat 7 and deployed the war. This time, both web.xml declared url and annotation url for my servlet work ok.

所以我的问题是:有没有人知道如何使嵌入式Tomcat 7考虑到我的Servlet 3.0注释?

So my question is: does anyone know how to make Embedded Tomcat 7 take into account my Servlet 3.0 annotations?

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

I should also state that it's a Maven project, and the pom.xml contains the following dependencies:

    <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>



==更新==



这是一个看起来与此类似的问题(除了Servlet 3.0注释不起作用的是Listener,而不是Servlet),它有一个建议的修复:

== UPDATE ==

Here's an issue that seems similar to this (except the Servlet 3.0 annotation that is not working is on Listener, not Servlet), which has a suggested fix:

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

我已经尝试过它并不起作用:

I've tried it and it didn't work:

将嵌入式Tomcat启动代码更改为:

Changed the Embedded Tomcat start code to:

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();

我试过的其他事情也没有成功:

Other things I've tried, also without success:


  • 在web.xmlweb-app标签中专门设置metadata-complete =false

  • specifically setting metadata-complete="false" in web.xml "web-app" tag

将Maven依赖项更新到版本7.0.30

updating the Maven dependencies to version 7.0.30

调试 org.apache.catalina.startup.ContextConfig 上课。那里的代码检查 @WebServlet 注释,只是它永远不会被执行(第2115行)。这可能是找到问题根源的好方法,但课程相当大,我现在没有时间做这件事。也许如果有人愿意看看这个类是如何工作的,并且在哪些条件下(config params)能够正确检查项目的注释类,它可能会得到一个有效的答案。

debugging the org.apache.catalina.startup.ContextConfig class. There's code there that checks for @WebServlet annotations, it's just that it never gets executed (line 2115). This may be a good way to get to the root of the issue, but the class is pretty big, and I don't have time to do this now. Maybe if someone would be willing to look how this class works, and under which conditions (config params) does it get to correctly check your project's classes for that annotation, it might get to a valid answer.

推荐答案

好吧我终于通过查看Tomcat7来源解决了它,即在处理EmbeddedTomcat的单元测试中和servlet 3.0注释。

Well I finally solved it by looking in the Tomcat7 sources, namely in the unit tests that deal with EmbeddedTomcat and servlet 3.0 annotations.

基本上,您必须像这样启动嵌入式Tomcat 7,以使其了解您的注释类:

Basically, you must start your Embedded Tomcat 7 like this to make it aware of your annotated classes:

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目录等)可在以下位置找到:

For the sake of clarity I should mention that this works for a standard Maven project where your "web resources" (such as static and dynamic pages, WEB-INF directory etc) are found in:

[您项目的根目录] / src / main / webapp

[your project's root dir]/src/main/webapp

你的课程被编译成

[你项目的根目录] /目标/班级

[your project's root dir]/target/classes

(这样你就可以[你的项目的根目录] / target / classes / [some package] /SomeCompiledServletClass.class)

(such that you'd have [your project's root dir]/target/classes/[some package]/SomeCompiledServletClass.class)

For其他目录布局,这些位置需要相应更改。

For other directories layouts, these locations need to be changed accordingly.

====更新:嵌入式Tomcat 8 ====

==== UPDATE: Embedded Tomcat 8 ====

感谢@kwak注意到这一点。

Thanks to @kwak for noticing this.

API有所改变,这里使用嵌入式Tomcat 8时上述示例如何变化:

The APIs have changed a bit, here how the above example changes when using 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();

这篇关于嵌入式tomcat 7 servlet 3.0注释无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆