Enable HTTP/2 with Tomcat in Spring Boot
HTTP/2 is a major upgrade to the HTTP protocol that offers significant performance improvements over its predecessor, HTTP/1.1. In this blog post, we'll explore how to enable HTTP/2 support in a Spring Boot application using Tomcat as the embedded web server. We'll cover the necessary configurations, best practices, and example usage to help you take advantage of the benefits of HTTP/2 in your Spring Boot projects.
Table of Contents#
- Prerequisites
- Configuring Tomcat for HTTP/2
- Spring Boot Application Configuration
- Testing HTTP/2 Support
- Best Practices
- Example Usage
- References
Prerequisites#
Before we begin, make sure you have the following:
- A Spring Boot project (version 2.0 or higher)
- Java 8 or higher
- Tomcat 9 or higher (since HTTP/2 support was introduced in Tomcat 9)
- Note for Java 8 users: HTTP/2 requires ALPN (Application-Layer Protocol Negotiation) support. Since Java 8 does not include ALPN natively, you need to add an ALPN implementation such as
spring-boot-starter-undertow(which includes Undertow's ALPN support) or the Jetty ALPN agent. Spring Boot's default Tomcat setup requires additional configuration for ALPN on Java 8.
Configuring Tomcat for HTTP/2#
Step 1: Add Tomcat Dependency#
If you're using Spring Boot's default embedded Tomcat server, you don't need to add an explicit dependency. However, if you're using a different server or need to manage the Tomcat version explicitly, you can add the following dependency to your pom.xml (for Maven) or build.gradle (for Gradle):
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>Gradle
implementation 'org.springframework.boot:spring-boot-starter-tomcat'Step 2: Configure Tomcat Connector#
To enable HTTP/2, we need to configure the Tomcat connector to use the HTTP/2 protocol. In your Spring Boot application's configuration file (e.g., application.properties or application.yml), add the following properties:
application.properties
server.tomcat.protocol-header=x-forwarded-proto
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.add-remote-ip-header=true
server.tomcat.max-http-post-size=0
server.port=8443
server.ssl.enabled=true
server.ssl.protocol=TLSv1.2
server.ssl.enabled-protocols=TLSv1.2,TLSv1.3
server.ssl.ciphers=ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-CHACHA20-POLY1305,DHE-RSA-AES128-GCM-SHA256,DHE-RSA-AES256-GCM-SHA384
server.ssl.client-auth=want
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=changeit
server.ssl.key-alias=tomcatapplication.yml
server:
port: 8443
ssl:
enabled: true
protocol: TLSv1.2
enabled-protocols: TLSv1.2,TLSv1.3
ciphers: ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-CHACHA20-POLY1305,DHE-RSA-AES128-GCM-SHA256,DHE-RSA-AES256-GCM-SHA384
client-auth: want
key-store-type: PKCS12
key-store: classpath:keystore.p12
key-store-password: changeit
key-alias: tomcat
tomcat:
protocol-header: x-forwarded-proto
remote-ip-header: x-forwarded-for
add-remote-ip-header: true
max-http-post-size: 0These properties configure the Tomcat connector to use HTTPS (required for HTTP/2) and specify the SSL/TLS settings. Make sure to replace the key-store and key-store-password values with your actual keystore file and password.
Spring Boot Application Configuration#
Step 1: Add SSL Configuration#
If you're using HTTPS (which is required for HTTP/2), you need to configure SSL in your Spring Boot application. You can generate a self-signed certificate or use a trusted certificate from a certificate authority (CA).
Generating a Self-Signed Certificate
You can use the keytool utility (provided with Java) to generate a self-signed certificate:
keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650Follow the prompts to enter the required information (e.g., keystore password, key password, CN, etc.).
Step 2: Configure Spring Boot to Use SSL#
In your Spring Boot application's main class (e.g., Application.java), add the following annotation to enable SSL:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}Testing HTTP/2 Support#
Step 1: Start the Application#
Run your Spring Boot application using your preferred method (e.g., mvn spring-boot:run or gradle bootRun).
Step 2: Check HTTP/2 Support#
You can use tools like curl or a web browser to check if HTTP/2 is enabled.
Using curl
curl -I --http2 https://localhost:8443If HTTP/2 is enabled, you should see the HTTP/2 protocol in the response headers.
Using a Web Browser
Open your web browser and navigate to https://localhost:8443. Check the browser's developer tools (e.g., Chrome DevTools) to see if the connection is using HTTP/2.
Best Practices#
- Use HTTPS: HTTP/2 requires HTTPS, so always use secure connections for your applications.
- Keep Dependencies Up to Date: Regularly update your Spring Boot, Tomcat, and other dependencies to ensure security and performance improvements.
- Test Thoroughly: Test your application thoroughly to ensure that HTTP/2 is working as expected and that there are no compatibility issues with your existing code.
- Monitor Performance: Use monitoring tools to track the performance of your application and identify any bottlenecks or issues related to HTTP/2.
Example Usage#
Here's a simple example of a Spring Boot controller that returns a "Hello, World!" message:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorldController {
@GetMapping("/")
public String helloWorld() {
return "Hello, World!";
}
}You can access this endpoint using https://localhost:8443/ (assuming your application is running on port 8443).