简体   繁体   中英

Tomcat Catalina context - add existing servlet to context

I would like to add an existing servlet to a context and it works, when I use (Main.java):

Tomcat.addServlet(ctx, "MyServlet", new MyServlet());
ctx.addServletMappingDecoded("/url_pattern", "MyServlet")

However, I have annotations inside servlet to map 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
)

Unfortunately, these annotations do not work. I would like to delete mapping from Main.java and use mapping from my Servlet annotation.

I use 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, "MyServlet", new MyServlet());
    
    ctx.setAllowCasualMultipartParsing(true);
    ctx.addServletMappingDecoded("/url_pattern", "MyServlet");
    
    
    tomcat.start();
    tomcat.getConnector();
    }
}

The idea behind embedded Tomcat is to do in code, what the usual Tomcat does through configuration. Therefore the configuration of servlets through annotations is not as straightforward as it is in Tomcat.

You'll be facing two problems:

Annotation scanning

The main difference between Tomcat#addContext and Tomcat#addWebapp is that the latter adds some default web.xml (the jsp and default servlet) and scans for Servlet 3.0 annotations and ServletContainerInitializer s.

If you don't need or don't want the default web.xml configuration, you can obtain the same thing with:

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

Resources

Even after enabling annotation scanning Tomcat will not find your servlets, because it looks under /WEB-INF/classes of your docBase (which you set to be the current folder). This is a probably empty folder. If you want Tomcat to scan also the classes in your application you'll need to:

  1. Find the JAR file or directory that contains your Main class,
  2. Mount the contents of that JAR to the /WEB-INF/classes (virtual) folder of your application (cf. 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.");
}

Summary

At the end you'll end up with:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM