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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Servlet Registration in Spring Boot 2.3.9: From Annotations to Dynamic Registration

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaSpring BootWeb DevelopmentannotationServletDynamic Registration
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

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.