1. Introduction
The Server Push technology — part of HTTP/2 (RFC 7540) — allows us to send resources to the client proactively from the server-side. This is a major change from HTTP/1.X pull-based approach.
One of the new features that Spring 5 brings – is the server push support that comes with Jakarta EE 8 Servlet 4.0 API. In this article, we’ll explore how to use server push and integrate it with Spring MVC controllers.
2. Maven Dependency
Let’s start by defining dependencies we’re going to use:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.1.5</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0-M2</version>
<scope>provided</scope>
</dependency>
The most recent versions of spring-mvc and servlet-api can be found on Maven Central.
3. HTTP/2 Requirements
To use server push, we’ll need to run our application in a container that supports HTTP/2 and the Servlet 4.0 API. Configuration requirements of various containers can be found here, in the Spring wiki.
Additionally, we’ll need HTTP/2 support on the client-side; of course, most current browsers do have this support.
4. PushBuilder Features
The PushBuilder interface is responsible for implementing server push. In Spring MVC, we can inject a PushBuilder as an argument of the methods annotated with @RequestMapping.
At this point, it’s important to consider that – if the client doesn’t have HTTP/2 support – the reference will be sent as null.
Here is the core API offered by the PushBuilder interface:
- path (String path) – indicates the resource that we’re going to send
- push() – sends the resource to the client
- addHeader (String name, String value) – indicates the header that we’ll use for the pushed resource
5. Quick Example
To demonstrate the integration, we’ll create the demo.jsp page with one resource — logo.png:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>PushBuilder demo</title>
</head>
<body>
<span>PushBuilder demo</span>
<br>
<img src="<c:url value="/resources/logo.png"/>" alt="Logo"
height="126" width="411">
<br>
<!--Content-->
</body>
</html>
We’ll also expose two endpoints with the PushController controller — one that uses server push and another that doesn’t:
@Controller
public class PushController {
@GetMapping(path = "/demoWithPush")
public String demoWithPush(PushBuilder pushBuilder) {
if (null != pushBuilder) {
pushBuilder.path("resources/logo.png").push();
}
return "demo";
}
@GetMapping(path = "/demoWithoutPush")
public String demoWithoutPush() {
return "demo";
}
}
Using the Chrome Development tools, we can see the differences by calling both endpoints.
When we call the demoWithoutPush method, the view and the resource is published and consumed by the client using the pull technology:
When we call the demoWithPush method, we can see the use of the push server and how the resource is delivered in advance by the server, resulting in a lower load time:
The server push technology can improve the load time of the pages of our applications in many scenarios. That being said, we do need to consider that, although we decrease the latency, we can increase the bandwidth – depending on the number of resources we serve.
It’s also a good idea to combine this technology with other strategies such as Caching, Resource Minification, and CDN, and to run performance tests on our application to determine the ideal endpoints for using server push.
6. Conclusion
In this quick tutorial, we saw an example of how to use the server push technology with Spring MVC using the PushBuilder interface, and we compared the load times when using it versus the standard pull technology.
As always, the source code is available over on GitHub.