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.
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><dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.67</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency></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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.