7 Proven Spring Boot Performance Optimizations for Faster Apps
This article presents seven practical Spring Boot performance tuning techniques—including asynchronous execution, Tomcat connection tuning, component scanning, switching to Undertow, BufferedWriter usage, DeferredResult handling, and AsyncHandlerInterceptor interception—each illustrated with concise Java code examples to help developers boost application speed and scalability.
1. Asynchronous Execution
Two implementation methods are provided: using the @Async annotation together with @EnableAsync on the main class, and leveraging JDK 8's CompletableFuture class.
@AllArgsConstructor
public class AskThread implements Runnable {
private CompletableFuture<Integer> re = null;
public void run() {
int myRe = 0;
try {
myRe = re.get() * re.get();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(myRe);
}
public static void main(String[] args) throws InterruptedException {
final CompletableFuture<Integer> future = new CompletableFuture<>();
new Thread(new AskThread(future)).start();
Thread.sleep(1000);
future.complete(60);
}
}The example starts a thread where AskThread initially blocks on myRe = re.get() * re.get() until the future is completed, after which the thread proceeds.
2. Increase Embedded Tomcat Maximum Connections
@Configuration
public class TomcatConfig {
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory tomcatFactory = new TomcatServletWebServerFactory();
tomcatFactory.addConnectorCustomizers(new MyTomcatConnectorCustomizer());
tomcatFactory.setPort(8005);
tomcatFactory.setContextPath("/api-g");
return tomcatFactory;
}
class MyTomcatConnectorCustomizer implements TomcatConnectorCustomizer {
public void customize(Connector connector) {
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
// set max connections
protocol.setMaxConnections(20000);
// set max threads
protocol.setMaxThreads(2000);
protocol.setConnectionTimeout(30000);
}
}
}3. Use @ComponentScan() for Faster Package Scanning
Applying @ComponentScan() locates packages more quickly than relying on @SpringBootApplication scanning.
4. Switch Default Tomcat Container to Undertow
Undertow (JBoss) offers higher throughput (≈8000) compared to Tomcat (≈5000).
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>5. Use BufferedWriter for Buffering
BufferedWriter can be employed to improve I/O efficiency; implementation is left as an exercise.
6. Deferred Approach for Asynchronous Calls
@RestController
public class AsyncDeferredController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final LongTimeTask taskService;
@Autowired
public AsyncDeferredController(LongTimeTask taskService) {
this.taskService = taskService;
}
@GetMapping("/deferred")
public DeferredResult<String> executeSlowTask() {
logger.info(Thread.currentThread().getName() + "进入executeSlowTask方法");
DeferredResult<String> deferredResult = new DeferredResult<>();
taskService.execute(deferredResult);
logger.info(Thread.currentThread().getName() + "从executeSlowTask方法返回");
deferredResult.onTimeout(() -> {
logger.info(Thread.currentThread().getName() + " onTimeout");
deferredResult.setErrorResult("time out!");
});
deferredResult.onCompletion(() -> {
logger.info(Thread.currentThread().getName() + " onCompletion");
});
return deferredResult;
}
}7. Intercept Asynchronous Calls with AsyncHandlerInterceptor
@Component
public class MyAsyncHandlerInterceptor implements AsyncHandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(MyAsyncHandlerInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info(Thread.currentThread().getName() + "服务调用完成,返回结果给客户端");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
if (ex != null) {
System.out.println("发生异常:" + ex.getMessage());
}
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String resp = "my name is chhliu!";
response.setContentLength(resp.length());
response.getOutputStream().write(resp.getBytes());
logger.info(Thread.currentThread().getName() + " 进入afterConcurrentHandlingStarted方法");
}
}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.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
