Mastering Servlet Registration in Spring Boot 2.3.9: From Annotations to Dynamic Registration
This guide explains three ways to register Servlets in Spring Boot 2.3.9—including @ServletComponentScan with @WebServlet, ServletRegistrationBean, and dynamic registration via ServletContextInitializer—while detailing the underlying scanning mechanism, BeanFactory post‑processor workflow, and how Tomcat ultimately registers the servlet.
1. Servlet Registration
Method 1: Add @ServletComponentScan on the configuration class and annotate the servlet class with @WebServlet("/hello"). Corresponding annotations for filter and listener are @WebFilter and @WebListener.
@SpringBootApplication
@ServletComponentScan
public class SpringBootComprehensiveApplication { } @WebServlet("/hello")
public class MyServlet extends HttpServlet { }Method 2: Register a ServletRegistrationBean in a @Bean method, allowing injection of other beans and access to application properties.
@Bean
public ServletRegistrationBean<MyServlet> servlet() {
ServletRegistrationBean<MyServlet> servlet = new ServletRegistrationBean<>(new MyServlet());
servlet.addUrlMappings("/hello");
return servlet;
}Method 3: Dynamically register a servlet by implementing ServletContextInitializer (available since Servlet 3.0).
@Component
public class DynamicRegServlet implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
ServletRegistration.Dynamic initServlet = servletContext.addServlet("myServlet", MyServlet.class);
initServlet.addMapping("/hello");
}
}Dynamic registration relies on the SPI mechanism and the ServletContainerInitializer interface.
2. Scanning Servlet Implementation Principle
In method 1, Spring scans the classpath for @WebServlet, @WebFilter, and @WebListener annotations and registers them via the bean registration process.
2.1 Import Core Classes
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServletComponentScanRegistrar.class)
public @interface ServletComponentScan { }The ServletComponentScanRegistrar registers a ServletComponentRegisteringPostProcessor bean.
class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
if (registry.containsBeanDefinition(BEAN_NAME)) {
updatePostProcessor(registry, packagesToScan);
} else {
addPostProcessor(registry, packagesToScan);
}
}
}2.2 Register BeanFactory Post Processor
class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
private void addPostProcessor(BeanDefinitionRegistry registry, Set<String> packagesToScan) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ServletComponentRegisteringPostProcessor.class);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(packagesToScan);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
}
}2.3 Instantiate Scanning Components
The static block of ServletComponentRegisteringPostProcessor creates handlers for servlet, filter, and listener annotations.
class ServletComponentRegisteringPostProcessor implements BeanFactoryPostProcessor, ApplicationContextAware {
private static final List<ServletComponentHandler> HANDLERS;
static {
List<ServletComponentHandler> servletComponentHandlers = new ArrayList<>();
servletComponentHandlers.add(new WebServletHandler());
servletComponentHandlers.add(new WebFilterHandler());
servletComponentHandlers.add(new WebListenerHandler());
HANDLERS = Collections.unmodifiableList(servletComponentHandlers);
}
}Each handler extracts annotation attributes and registers a corresponding ServletRegistrationBean.
2.4 Find and Register Beans
The post‑processor scans candidate components, matches them with the handlers, and invokes handle to create bean definitions.
abstract class ServletComponentHandler {
void handle(AnnotatedBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
Map<String, Object> attributes = beanDefinition.getMetadata()
.getAnnotationAttributes(this.annotationType.getName());
if (attributes != null) {
doHandle(attributes, beanDefinition, registry);
}
}
}2.5 Tomcat Registers the Servlet
During Spring Boot startup, AnnotationConfigServletWebServerApplicationContext creates the embedded web server and invokes all ServletContextInitializer beans, including ServletRegistrationBean, which registers the servlet with the servlet container.
public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
@Override
public final void onStartup(ServletContext servletContext) throws ServletException {
if (!isEnabled()) {
return;
}
register(description, servletContext);
}
protected abstract void register(String description, ServletContext servletContext);
}Finally, ServletRegistrationBean adds the servlet to the ServletContext and configures URL mappings, load‑on‑startup, and multipart settings.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
