Tomcat Catalina 上下文 - 将现有的 servlet 添加到上下文

Tomcat Catalina context - add existing servlet to context

我想将现有的 servlet 添加到上下文中,当我使用 (Main.java):

时它可以工作
Tomcat.addServlet(ctx, "MyServlet", new MyServlet());
ctx.addServletMappingDecoded("/url_pattern", "MyServlet")

但是,我在 servlet 中有注释来映射 url_pattern(MyServlet.java):

@WebServlet(name = "MyServlet", urlPatterns = { "/url_pattern" })
@MultipartConfig(
  fileSizeThreshold = 1024 * 1024 * 1, // 1 MB
  maxFileSize = 1024 * 1024 * 10,      // 10 MB
  maxRequestSize = 1024 * 1024 * 100   // 100 MB
)

不幸的是,这些注释不起作用。我想从 Main.java 中删除映射并使用我的 Servlet 注释中的映射。

我用的是Tomcat10.0.0.

Main.java

import java.io.File;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;

public class Main {

    public static void main(String[] args) throws LifecycleException,
    InterruptedException {
    Tomcat tomcat = new Tomcat();
    tomcat.setPort(8082);

    Context ctx = tomcat.addContext("", new File(".").getAbsolutePath());

    Tomcat.addServlet(ctx, "MyServlet", new MyServlet());
    
    ctx.setAllowCasualMultipartParsing(true);
    ctx.addServletMappingDecoded("/url_pattern", "MyServlet");
    
    
    tomcat.start();
    tomcat.getConnector();
    }
}

嵌入式 Tomcat 背后的想法是在代码中完成,而通常的 Tomcat 通过配置完成。因此通过注解配置servlet并不像在Tomcat.

中那么简单

您将面临两个问题:

注释扫描

Tomcat#addContext and Tomcat#addWebapp 之间的主要区别是后者添加了一些默认 web.xmljspdefault servlet)并扫描 Servlet 3.0 注释和 ServletContainerInitializers.

如果您不需要或不想要默认的 web.xml 配置,您可以通过以下方式获得同样的东西:

Context ctx = tomcat.addContext("", new File(".").getAbsolutePath());
ctx.addLifecycleListener(new ContextConfig());

资源

即使在启用注释扫描后,Tomcat 也不会找到您的 servlet,因为它会在您的 docBase(您设置为当前文件夹)的 /WEB-INF/classes 下查找。这可能是一个空文件夹。如果您希望 Tomcat 也扫描您应用程序中的 classes,您需要:

  1. 找到包含您的 Main class,
  2. 的 JAR 文件或目录
  3. 将该 JAR 的内容安装到应用程序的 /WEB-INF/classes(虚拟)文件夹中(参见 Tomcat resources):
public static void main(String[] args) throws LifecycleException, InterruptedException {
   ...
   // Add the JAR/folder containing this class to PreResources
   final WebResourceRoot root = new StandardRoot(ctx);
   final URL url = findClassLocation(Main.class);
   root.createWebResourceSet(ResourceSetType.PRE, "/WEB-INF/classes", url, "/");
   ctx.setResources(root);
   ...
}

/*
 * Tries to find the URL of the JAR or directory containing {@code clazz}.
 */
private static URL findClassLocation(Class< ? > clazz) {
    return clazz.getProtectionDomain().getCodeSource().getLocation();
}

总结

最后你会得到:

    public static void main(String[] args) throws LifecycleException {
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8082);
        final Context ctx = tomcat.addContext("", Paths.get(".").toAbsolutePath().toString());
        // Add the standard ContextConfig, which scans for annotations
        ctx.addLifecycleListener(new ContextConfig());
        // Add the JAR/folder containing this class to PreResources
        final WebResourceRoot root = new StandardRoot(ctx);
        final URL url = findClassLocation(Main.class);
        root.createWebResourceSet(ResourceSetType.PRE, "/WEB-INF/classes", url, "/");
        ctx.setResources(root);
        // Run Tomcat
        tomcat.getConnector();
        tomcat.start();
        tomcat.getServer().await();
    }