Tomcat Catalina 上下文 - 将现有 servlet 添加到上下文 注释扫描资源总结

如何解决Tomcat Catalina 上下文 - 将现有 servlet 添加到上下文 注释扫描资源总结

我想将现有的 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 注释中的映射。

我使用 Tomcat 10.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,new MyServlet());
    
    ctx.setAllowCasualMultipartParsing(true);
    ctx.addServletMappingDecoded("/url_pattern","MyServlet");
    
    
    tomcat.start();
    tomcat.getConnector();
    }
}

解决方法

嵌入式Tomcat背后的想法是在代码中完成,通常Tomcat通过配置来完成。因此通过注解来配置servlets并不像在Tomcat中那么简单。

您将面临两个问题:

注释扫描

Tomcat#addContextTomcat#addWebapp 的主要区别在于后者添加了一些默认的 web.xmljspdefault servlet)并扫描 Servlet 3.0注释和 ServletContainerInitializer

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

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

资源

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

  1. 找到包含您的 Main 类的 JAR 文件或目录,
  2. 将该 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) {
    final ClassLoader cl = Main.class.getClassLoader();
    if (cl instanceof URLClassLoader) {
        final URLClassLoader urlCl = (URLClassLoader) cl;
        final String mainClassName = clazz.getName().replaceAll("\\.","/") + ".class";
        final String mainResource = urlCl.findResource(mainClassName)//
                                         .toString();
        for (final URL url : urlCl.getURLs()) {
            if (mainResource.toString().startsWith(url.toString())) {
                return url;
            }
        }
    }
    throw new RuntimeException("Didn't find the URL of the Main class.");
}

总结

最后你会得到:

    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,"/");
        ctx.setResources(root);
        // Run Tomcat
        tomcat.getConnector();
        tomcat.start();
        tomcat.getServer().await();
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?