Serving static resources in a Micronaut Framework application
Learn how to expose static resources such as CSS or images in a Micronaut Framework application.
On this guide
In this section
Getting Started
In this guide, we will create a Micronaut application written in Java.
What you will need
To complete this guide, you will need the following:
-
Some time on your hands
-
A decent text editor or IDE (e.g. IntelliJ IDEA)
-
JDK 21 or greater installed with
JAVA_HOMEconfigured appropriately
Solution
We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.
-
Download and unzip the source
Writing the Application
Create an application using the Micronaut Command Line Interface or with Micronaut Launch.
mn create-app example.micronaut.micronautguide \
--features=validation,views-thymeleaf \
--build=gradle \
--lang=java \
--test=junit|
Note
|
If you don’t specify the --build argument, Gradle with the Kotlin DSL is used as the build tool. If you don’t specify the --lang argument, Java is used as the language.If you don’t specify the --test argument, JUnit is used for Java and Kotlin, and Spock is used for Groovy.
|
The previous command creates a Micronaut application with the default package example.micronaut in a directory named micronautguide.
If you use Micronaut Launch, select Micronaut Application as application type and add validation, and views-thymeleaf features.
|
Note
|
If you have an existing Micronaut application and want to add the functionality described here, you can view the dependency and configuration changes from the specified features, and apply those changes to your application. |
Views
To use the Thymeleaf Java template engine to render views in a Micronaut application, add the following dependency on your classpath.
implementation("io.micronaut.views:micronaut-views-thymeleaf")Thymeleaf template
Create a Thymeleaf template in src/main/resources/views/index.html:
Message service
Create an interface that describes our message service.
package example.micronaut;
import io.micronaut.core.annotation.NonNull;
import jakarta.validation.constraints.NotBlank;
interface MessageService {
String sayHello(@NonNull @NotBlank String name);
}And then create a default implementation of the service.
Controller
Create a controller that takes a name and generates our templated HTML page.
Assets
Then create a static CSS file in src/main/resources/static/css/style.css:
html, body {
margin: 0;
padding: 0.5em;
background: #eee;
font-family: sans-serif;
color: #333;
}
section {
display: flex;
flex-direction: column;
text-align: center;
justify-content: left;
width: fit-content;
}
section h1 {
margin: 0;
padding: 0.5em;
font-size: 1.5em;
font-variant: small-caps;
}And a static PNG file in src/main/resources/static/images/micronaut_stacked_black.png:

Configuration
We can then add a static-mapping to our application.properties so that any missing requests are attempted to be resolved from the static assets.
First configure a route /css/*.css to map any routes matching that pattern to be mapped to the static/css resources.
micronaut.router.static-resources.css.mapping=/css/*.css
micronaut.router.static-resources.css.paths=classpath\:static/css-
The first line matches any request to the server that does not match a controller route.
-
The second line defines that the classpath inside a root static directory should be searched for the resource.
This means that a request to /css/style.css will be resolved to src/main/resources/static/css/style.css (if that resource exists and there is no matching controller path).
And then configure a route /images/** to be mapped to the static/images resources.
We use a wildcard here as images may have different file extensions.
micronaut.router.static-resources.images.mapping=/images/**
micronaut.router.static-resources.images.paths=classpath\:static/imagesThis means that a request to /images/some/image.png will be resolved to src/main/resources/static/images/some/image.png (if that resource exists and there is no matching controller path).
A note on wildcard mappings
For every request, the framework searches for a controller route; if no route is found, it searches for a static resource. In the above configuration, we could have used a single wildcard mapping for all assets similar to:
micronaut.router.static-resources.assets.mapping=/**
micronaut.router.static-resources.assets.paths=classpath\:staticHowever, searching for a static resource in every request is a waste.
We know specific paths (e.g., /bogus) will not match any resource.
Therefore, as we only want to search for static resources for paths starting with /css or /images, we can limit our static resource mappings to these paths.
Testing
Create a test that verifies the MessageService is working as expected.
And another that verifies the generated HTML contains the expected text.
And another that verifies the static resources are returned on the expected URLs.
Testing the Application
To run the tests:
./gradlew testThen open build/reports/tests/test/index.html in a browser to see the results.
Running the Application
To run the application, use the ./gradlew run command, which starts the application on port 8080.
Visit http://localhost:8080/hello/Micronaut and the browser displays our templated HTML page with styling and an image.
Next Steps
Explore more features with Micronaut Guides.
Learn more about static resources in the Micronaut Framework.
View other guides tagged with static-resources.
Help with the Micronaut Framework
The Micronaut Foundation sponsored the creation of this Guide. A variety of consulting and support services are available.
License
|
Note
|
All guides are released with an Apache License 2.0 for the code and a Creative Commons Attribution 4.0 license for the writing and media (images). |