Skip to content
TaeyoungKim.dev

Spring Boot static file vs controller: Which handles the same URL?

Java/SpringWritten 3 min readTaeyoungKim
LinkedInX

You edit /welcome.html, but the browser still shows the old message. Before assuming it is a cache issue, check whether a controller also handles that URL. Following the same request through controller mapping and static resource handling reveals which response wins.

A controller mapping takes precedence in this setup

In a typical Spring Boot MVC configuration, a matching controller method is selected before the static resource handler. Assume the app has src/main/resources/static/welcome.html and a controller responding to the exact same /welcome.html path.

The diagram compares the same request in two configurations. With the controller mapping, the response is controller page; without that mapping, the static file can answer with static page.

Give each source a distinct response to make the selection visible:

java
@Controller
class WelcomeController {
    @GetMapping("/welcome.html")
    @ResponseBody
    String welcome() {
        return "controller page";
    }
}

Because of @ResponseBody, this string is the HTTP response body, not a view name. With the mapping active, /welcome.html returns controller page even if the static file exists. Remove or change the controller mapping, then request the same URL again to see the static file. Spring Boot's servlet web application reference describes controller mappings and its default static resource locations.

The static file is a candidate when no mapping handles the path

Spring Boot serves files from default static locations when no higher-priority handler handles the request. A file under src/main/resources/static maps to a URL path:

text
src/main/resources/static/welcome.html
                 └── /welcome.html

Now remove only the controller mapping and repeat the same /welcome.html request. A static page response means the file was present but hidden behind the earlier mapping. /welcome is a different URL; this file does not automatically serve it.

Check the path and the response separately

First request /welcome.html with both controller and static file present. Then remove only the controller mapping and request the identical path. Changing the URL too would make it harder to identify which configuration changed the result.

Request: /welcome.htmlExpected bodyCheck first
Controller mapping presentcontroller pageMapping and @ResponseBody
Controller mapping removedstatic pageStatic file location and name

If neither outcome appears, inspect the requested path, active profile, and custom resource handler configuration. If a controller should return a view name instead of body text, remove @ResponseBody and check the template location. The same string has different meaning as a response body and as a view name.

Separate static and dynamic URL responsibilities

Keeping static files under a recognizable path such as assets/ or docs/ and dynamic screens under controller URLs avoids relying on handler-order trivia. A test should check more than status 200:

java
mockMvc.perform(get("/welcome.html"))
    .andExpect(status().isOk())
    .andExpect(content().string("controller page"));

This expectation applies with the controller mapping active. In a separate test without it, check for static page. Static resources suit file delivery; controllers suit decisions involving inputs, data, or authorization. Avoid assigning the same URL to both responsibilities.

Key takeaways

For the same /welcome.html request in this standard configuration, the matching controller responds first; without it, the static file can respond. Compare distinct bodies at the same URL. Treat /welcome as its own path and keep static and dynamic routes intentionally separate.

Author

TaeyoungKim

Connecting technical foundations with implementation, verification, and production decisions.

#Spring Boot#Controller#Static content#MVC

Read next