Master Spring Boot 3.2.5: Custom Failure Analyzer, Environment & Web Server Settings
This guide walks through creating custom FailureAnalyzers, registering EnvironmentPostProcessors, configuring non‑web applications, switching profiles for YAML settings, altering the embedded web server, and customizing server factories in Spring Boot 3.2.5, complete with code examples and screenshots.
1. Failure Analysis
Spring Boot allows intercepting startup exceptions via the FailureAnalyzer interface, which returns a FailureAnalysis instance. Returning null lets other analyzers run. Example implementation:
<code>public class PackAbstractFailureAnalyzer extends AbstractFailureAnalyzer<NullPointerException> {
@Override
protected FailureAnalysis analyze(Throwable rootFailure, NullPointerException cause) {
System.err.println(rootFailure.getMessage());
System.out.printf("发生了空指针异常:%s%n", cause);
return new FailureAnalysis(rootFailure.getMessage(), cause.getMessage(), cause);
}
}
</code>Register the analyzer in META-INF/spring.factories :
<code>org.springframework.boot.diagnostics.FailureAnalyzer=\
com.pack.test.failure_analyzer.PackAbstractFailureAnalyzer</code>Trigger a startup exception manually:
<code>@Bean
User user() {
String name = null;
System.out.println(name.charAt(0));
return new User(666L, "李四");
}
</code>Application start output:
2. Custom Environment Before Startup
During startup, before ApplicationContext is instantiated, Spring Boot publishes ApplicationEnvironmentPreparedEvent , which is handled by EnvironmentPostProcessorApplicationListener . Implement EnvironmentPostProcessor to add custom properties.
<code>public class PackEnvironmentPostProcessor implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource path = new ClassPathResource("com/pack/test/environment_post_processor/config.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 (IOException ex) {
throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
}
}
}
</code>YAML file ( config.yml ) content:
<code>app:
version: 1.0.0
name: myapp
</code>Register in META-INF/spring.factories :
<code>org.springframework.boot.env.EnvironmentPostProcessor=\
com.pack.test.environment_post_processor.PackEnvironmentPostProcessor</code>Test the injected properties:
<code>@Resource
private Environment env;
System.out.printf("version: %s, name: %s%n",
env.getProperty("app.version"),
env.getProperty("app.name"));
// Output: version: 1.0.0, name: myapp
</code>3. Creating a Non‑Web Application
By default Spring Boot starts a web application when the web starter is on the classpath. To run a non‑web app, either set the type programmatically:
<code>SpringApplication app = new SpringApplication(Application.class);
app.setWebApplicationType(WebApplicationType.NONE);
app.run(args);
</code>or configure it in application.yml :
<code>spring:
main:
web-application-type: none
</code>With this configuration, the JVM exits after all non‑daemon threads finish.
4. Profile‑Based Configuration
Spring Boot can activate different YAML documents based on the active profile. Example:
<code>spring:
config:
activate:
on-profile: dev
server:
port: 9001
---
spring:
config:
activate:
on-profile: prod
server:
port: 8080
</code>Activate a profile with:
<code>spring:
profiles:
active:
- dev
</code>When the dev profile is active, the application starts on port 9001.
5. Web Service Customization
The default embedded server is Tomcat. To switch to Jetty, exclude Tomcat and add the Jetty starter:
<code><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</code>Undertow can be used similarly with spring-boot-starter-undertow .
To disable HTTP endpoints while still creating a WebApplicationContext :
<code>server:
port: -1
</code>For a random port:
<code>server:
port: 0
</code>Retrieve the actual port after startup via WebServerInitializedEvent :
<code>@Component
public class PackWebServerListener implements ApplicationListener<WebServerInitializedEvent> {
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
System.out.printf("服务运行端口: %d%n", event.getWebServer().getPort());
}
}
</code>In tests, obtain the random port with:
<code>@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationTests {
@LocalServerPort
private int port;
@Test
public void contextLoads() {
System.out.printf("测试随机端口: %d%n", port);
}
}
</code>6. Custom Web Server
For fine‑grained server tweaks, implement WebServerFactoryCustomizer for the specific server type (Tomcat, Jetty, Undertow, Netty). Example for Tomcat:
<code>@Component
public class PackTomcatWebServerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
// custom Tomcat settings here
}
}
</code>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.