Master Spring Boot 3.2: Auto‑Configuration, Custom Environments, and Advanced Tomcat Tweaks
This guide walks through Spring Boot 3.2.5 troubleshooting with ConditionEvaluationReport, customizing the application context and environment via listeners and EnvironmentPostProcessor, building parent‑child containers, managing embedded Tomcat MBeans, returning XML responses, customizing the whitelabel error page, and adding multiple Tomcat connectors, all illustrated with code snippets and images.
1. Auto‑Configuration Troubleshooting
Spring Boot’s ConditionEvaluationReport can be viewed by enabling DEBUG logging or accessing the /actuator/conditions endpoint (JSON format). It shows which auto‑configuration classes were applied or skipped. Pay attention to classes ending with *AutoConfiguration and their @Conditional* annotations, @ConfigurationProperties (e.g., ServerProperties with prefix server ), Binder usage, @Value , and @ConditionalOnExpression annotations.
2. Customizing Context or Environment Before Application Starts
Use SpringApplication listeners and ApplicationContextInitializers . Spring Boot loads many implementations from META-INF/spring.factories . You can register additional ones programmatically via addListeners and addInitializers , or declaratively by adding entries to spring.factories .
Programmatic registration: call SpringApplication.addListeners(...) and addInitializers(...) before run() .
Declarative registration: create a JAR with META-INF/spring.factories containing the fully‑qualified class names.
Example of an EnvironmentPostProcessor that loads a custom YAML file into the environment:
<code>org.springframework.boot.env.EnvironmentPostProcessor=\
com.pack.PackCustomEnvironmentPostProcessor</code> <code>public class PackCustomEnvironmentPostProcessor implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource path = new ClassPathResource("pack.yml");
PropertySource<?> propertySource = loadYaml(path);
environment.getPropertySources().addLast(propertySource);
}
private PropertySource<?> loadYaml(Resource path) {
Assert.isTrue(path.exists(), () -> "Resource " + path + " does not exist");
try {
return this.loader.load("custom-resource", path).get(0);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}</code>3. Building Parent‑Child Containers
Spring Boot does not create parent‑child contexts by default, but you can configure them manually:
<code>SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
// custom parent container
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext("com.pack.parent");
builder.parent(parent);
builder.build().run(args);</code>4. Managing Embedded Tomcat
The embedded Tomcat’s MBean registry is disabled by default. Enable it to expose metrics (e.g., for Micrometer) by adding:
<code>server:
tomcat:
mbeanregistry:
enabled: true</code>View the MBeans with JConsole.
5. Responding with XML Data
Add the Jackson XML and JAXB runtime dependencies, then define an entity and a controller method that produces XML when the client requests it.
<code><dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency></code> <code>@XmlRootElement(name = "person")
public class Person {
private String name;
private Integer age;
private String email;
// getters & setters
}</code> <code>@GetMapping(value = "/list", produces = "application/xml")
public Person person() {
return new Person("张三", 30, "[email protected]");
}</code>6. Customizing the "Whitelabel" Error Page
Disable the default whitelabel error page:
<code>server:
error:
whitelabel:
enabled: false</code>Provide your own error view (e.g., error.html for Thymeleaf or error.ftlh for FreeMarker) or a controller handling /error .
7. Enabling Multiple Tomcat Connectors
Add additional connectors (e.g., another HTTP port) by customizing TomcatServletWebServerFactory :
<code>@Configuration(proxyBeanMethods = false)
public class PackCustomTomcatConfiguration {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> connectorCustomizer() {
return tomcat -> tomcat.addAdditionalTomcatConnectors(createConnector());
}
private Connector createConnector() {
// Add a connector on port 9001
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(9001);
return connector;
}
}</code>You can also implement TomcatConnectorCustomizer , TomcatContextCustomizer , or TomcatProtocolHandlerCustomizer for finer control.
<code>@Component
public class PackTomcatConnectorCustomizer implements TomcatConnectorCustomizer {
@Override
public void customize(Connector connector) {
connector.setPort(9002);
}
}</code>These customizations allow you to run the application with multiple ports or protocols.
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.