Backend Development 11 min read

Run a Spring MVC App with Embedded Tomcat in One Class – Step‑by‑Step Guide

This tutorial shows how to build and run a Spring MVC application using an embedded Tomcat server with just a single Java class, covering Maven dependencies, Tomcat configuration, Servlet registration, Spring‑driven startup, and core Spring MVC component setup.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Run a Spring MVC App with Embedded Tomcat in One Class – Step‑by‑Step Guide

Overview

Spring MVC is a powerful module of the Spring framework for building web applications based on the MVC pattern, simplifying development with annotations and efficiently handling requests and responses.

In modern projects most developers prefer Spring Boot, which auto‑configures common settings and eliminates the need to manually configure Spring MVC, saving a whole day of work.

Configure basic application information such as name and port in application.properties or application.yml .

Configure static resource paths.

Configure view resolver prefix and suffix.

Create controller classes and add request‑handling methods.

Create interceptor classes and configure paths.

Create exception‑handler classes and configure related information.

Configure internationalization support.

With Spring Boot, most Spring MVC components require little to no configuration; only a few custom settings in the configuration file are needed.

Prepare Environment

To run a Spring MVC program with a single class we use an embedded Tomcat, just like a Spring Boot application.

<code>&lt;dependency&gt;
  &lt;groupId&gt;org.apache.tomcat.embed&lt;/groupId&gt;
  &lt;artifactId&gt;tomcat-embed-core&lt;/artifactId&gt;
  &lt;version&gt;9.0.67&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.springframework&lt;/groupId&gt;
  &lt;artifactId&gt;spring-webmvc&lt;/artifactId&gt;
  &lt;version&gt;5.3.23&lt;/version&gt;
&lt;/dependency&gt;</code>

Use Embedded Tomcat

The following method creates and starts an embedded Tomcat server.

<code>protected static void createWebServer() throws Exception {
  final int PORT = 8088;
  Tomcat tomcat = new Tomcat();
  // Server configuration
  Server server = tomcat.getServer();
  Service service = server.findService("Tomcat");
  // Connector configuration
  Http11NioProtocol protocol = new Http11NioProtocol();
  ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
  protocol.setExecutor(executor);
  protocol.setConnectionTimeout(20000);
  Connector connector = new Connector(protocol);
  connector.setPort(PORT);
  connector.setURIEncoding("UTF-8");
  service.addConnector(connector);
  // Engine configuration
  StandardEngine engine = new StandardEngine();
  engine.setDefaultHost("localhost");
  StandardHost host = new StandardHost();
  host.setName("localhost");
  host.setAppBase(System.getProperties().getProperty("user.home"));
  engine.addChild(host);
  service.setContainer(engine);
  // Context configuration
  StandardContext context = new StandardContext();
  context.addLifecycleListener(new FixContextListener());
  context.setPath("");
  host.addChild(context);
  tomcat.start();
}

public static void main(String[] args) throws Exception {
  createWebServer();
}</code>

Test Embedded Tomcat

Running the program produces log output similar to:

<code>2025-05-17 10:10:04 上午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler["http-nio-8088"]
2025-05-17 10:10:05 上午 org.apache.catalina.core.StandardService startInternal
信息: Starting service [Tomcat]
2025-05-17 10:10:05 上午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet engine: [Apache Tomcat/9.0.67]
2025-05-17 10:10:06 上午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
警告: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [1,269] ms.
2025-05-17 10:10:06 上午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler["http-nio-8088"]</code>

Register Servlet with ServletContainerInitializer

Using the Servlet 3.0 ServletContainerInitializer interface we can programmatically register a servlet.

<code>void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException;</code>

Implementation example:

<code>context.addServletContainerInitializer(new ServletContainerInitializer() {
  @Override
  public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
    Hello hello = new Hello();
    Dynamic dynamic = ctx.addServlet("hello", hello);
    dynamic.setLoadOnStartup(0);
    dynamic.addMapping("/hello");
  }
}, null);</code>

Spring‑driven Tomcat Startup

By mimicking Spring Boot’s startup process we can launch the embedded Tomcat from a Spring context.

<code>public static void main(String[] args) throws Exception {
  AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext() {
    @Override
    protected void onRefresh() {
      super.onRefresh();
      try {
        createWebServer();
      } catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
      }
    }
  };
  context.refresh();
}</code>

Configure Spring MVC Core Components

Core components can be defined manually or via @EnableWebMvc . Below is a manual configuration example.

<code>static class AppConfig {
  @Bean
  public RequestMappingHandlerMapping requestMappingHandlerMapping(){
    RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
    mapping.setDetectHandlerMethodsInAncestorContexts(true);
    return mapping;
  }
  @Bean
  public RequestMappingHandlerAdapter requestMappingHandlerAdapter(){
    RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
    adapter.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    return adapter;
  }
}
// Register in main
context.register(AppConfig.class);
</code>

Define Controller and Test

Finally, create a simple REST controller and register it.

<code>@RestController
@RequestMapping("/demos")
static class DemoController {
  @GetMapping("/index")
  public Object index(){
    Map<String,Object> res = new HashMap<>();
    res.put("code",0);
    res.put("message","success");
    res.put("data",Arrays.asList(1,2,3,4,5));
    return res;
  }
}
// Register controller
context.register(DemoController.class);
</code>

After starting the application, accessing /hello (or the /demos/index endpoint after replacing the servlet with DispatcherServlet ) returns the expected response, confirming that the embedded Tomcat and Spring MVC configuration work correctly.

JavaBackend DevelopmentSpring BootSpring MVCEmbedded Tomcat
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.