Skip to content
Static Resource Paths

Static Resource Paths

Spring Boot static resource mapping

The Java classpath is the collection of directories and JAR files from which the Java process loads compiled classes and application resources. A classpath root is the directory treated as the starting point for those lookups; the root itself is not part of the resource name.

Spring Boot uses several directories below the classpath roots as default static-content directories. Files found there are returned directly in HTTP responses instead of being processed through a controller or template engine. The default directory names include:

classpath:/static/
classpath:/public/
classpath:/resources/
classpath:/META-INF/resources/

The static directory is the lookup root for the public resource and does not appear in the URL. Only the path beneath that directory becomes the request path.

classpath:/static/Css/main.css
                  └──────────┘
                  /Css/main.css

The request is therefore:

GET /Css/main.css HTTP/1.1
Host: <HOST>

The source and classpath locations remain internal to the application:

/static/Css/main.css
/src/main/resources/static/Css/main.css
/target/classes/static/Css/main.css

Spring Boot maps static resources to /** by default. In this URL pattern, /** means every request path. Spring Boot appends the requested path /Css/main.css to each configured static root until it finds a matching classpath resource. This behavior is defined by the Spring Boot 3.3 static-content mapping.

Source path, classpath, and URL

Maven is the build tool that compiles the Java project and assembles its runtime files. It treats src/main/resources as a source directory containing non-Java application resources. During the build, Maven copies those resources into target/classes, which becomes a classpath root used by the built application.

A Spring Boot project commonly stores a static file here:

src/main/resources/static/Css/main.css

After a Maven build, the runtime copy is commonly here:

target/classes/static/Css/main.css

The complete mapping is:

src/main/resources/static/Css/main.css
-> target/classes/static/Css/main.css
-> classpath:/static/Css/main.css
-> /Css/main.css

Each removed path component has a separate reason:

src/main/resources  -> Maven source location; copied into the build output
target/classes      -> runtime classpath root; not part of the resource name
static              -> Spring Boot static-content root; not part of the public URL
Css/main.css        -> relative resource path; becomes the public URL path

Writing to the source directory after the build does not necessarily change the already-built copy under target/classes. An output file intended for immediate retrieval must be written into the static directory used by the running application.

Files under src/main/resources/templates are different. They are view templates processed through a template engine and controller flow, not static files exposed directly by their filesystem path.

Check for custom mappings

The default relationship changes when the application configures a different URL pattern, static location, or resource handler:

spring.mvc.static-path-pattern=/assets/**
spring.web.resources.static-locations=classpath:/files/

With both settings present, this classpath resource:

classpath:/files/Css/main.css

maps to:

/assets/Css/main.css

Relevant configuration can be located with:

grep -RniE 'static-path-pattern|static-locations|addResourceHandlers' .

Locate the application root

The container build files establish where the application is copied and started:

COPY <SOURCE_DIRECTORY>/ <APPLICATION_ROOT>
WORKDIR <APPLICATION_ROOT>
RUN mvn clean package
CMD ["mvn", "spring-boot:run"]

<APPLICATION_ROOT> is the starting point for the source and build paths. A known static filename from the HTML can also locate both copies:

find / -type f -name '<KNOWN_STATIC_FILENAME>' 2>/dev/null

Example results:

<APPLICATION_ROOT>/src/main/resources/static/<RELATIVE_PATH>/<KNOWN_STATIC_FILENAME>
<APPLICATION_ROOT>/target/classes/static/<RELATIVE_PATH>/<KNOWN_STATIC_FILENAME>

The process command and build output determine which copy is active. A harmless marker written beside the active file and requested through the matching URL confirms the mapping:

printf 'static-path-test' > <APPLICATION_ROOT>/target/classes/static/<RELATIVE_PATH>/path-test.txt
curl http://127.0.0.1:<PORT>/<RELATIVE_PATH>/path-test.txt

Expected output:

static-path-test

Find by: spring boot, static resources, webroot, web root, classpath static, public url mapping, static directory disappears, source path url discrepancy, runtime static path, target classes static, src main resources static, maven build output, static path pattern, static locations, resource handler, find served directory, write command output · Source: HTB/PentestNotes