javaspring-bootspring-mvcspring-securitystaticresource

Not able to map static resources i.e. JS, CSS, images in spring MVC


I'm not sure how these static resources were loading earlier but after I added one new controller mapping I see no mapping found for static resources warning message in logs.

No mapping for GET /testproject/org/css/style.css

Let me explain my project configuration first so that it will be easy to understand the problem.

All JSP location (view have different folders to separate JSP for different modules)

src/main/java/webapp/views/org/*.jsp  
src/main/java/webapp/views/*.jsp

Static resource location

src/main/java/resources/static/css/*.css  
src/main/java/resources/static/js/*.js  
src/main/java/resources/static/images/*.jpg  
src/main/java/resources/static/fonts/*.ttf

Application.properties

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
server.servlet.contextPath=/testproject

After adding last config in application.properties now my application URL for any view page will be like

http://localhost:8080/testproject/dashboard

Controller mapping for the above URL is:

@RequestMapping(value = "/dashboard", method = RequestMethod.GET)
    public String dashboard(ModelMap map) {return "org/dashboard";}

With the above configuration, the static resource path is getting formed as below

http://localhost:8080/testproject/css/style.css

With the above config, I was able to load CSS files using the below code

<%@ taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core"%>
<link href="<core:url value="css/style.css"/>" rel="stylesheet" type="text/css" media="all">

Now as I have dashboard page defined under separate folder org so I thought to change my controller mapping to match exactly as folder structure & also it will help me to assign different roles/Access_ROLE for diff modules in spring security.

Spring security config for defining USER_ROLE who can access org module pages

.antMatchers("/org/**").access("hasRole('ROLE_ORG')").anyRequest()

After changing my controller mapping (from /dashboard to /org/dashboard)

@RequestMapping(value = "/org/dashboard", method = RequestMethod.GET)
    public String dashboard(ModelMap map) {return "org/dashboard";}

Now spring security works fine. It is not allowing direct access of dashboard without login or if logged-in user is having different ROLE.

But now my static resource URL is changes now

http://localhost:8080/testproject/org/css/style.css

Earlier this URL was

http://localhost:8080/testproject/css/style.css (working)

Things I tried to fix this

WebMvcConfig.java

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // TODO Auto-generated method stub
        registry.addResourceHandler("/res/**").addResourceLocations("/resources/static/");
        WebMvcConfigurer.super.addResourceHandlers(registry);
    }
}

Added this property in application.properties

spring.mvc.static-path-pattern=/resources/**

Now in JSP, I'm trying to access CSS with below code, none of them worked

<%@ taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core"%>
<link href="<core:url value="css/style.css"/>" rel="stylesheet" type="text/css" media="all">
<link href="<core:url value="resources/css/style.css"/>" rel="stylesheet" type="text/css" media="all">
<link href="<core:url value="res/css/style.css"/>" rel="stylesheet" type="text/css" media="all">

So I checked in developer tool to see the path created for all above code PFB

<link href="<core:url value="css/style.css"/>" rel="stylesheet" type="text/css" media="all">

http://localhost:8080/testproject/org/css/style.css

<link href="<core:url value="resources/css/style.css"/>" rel="stylesheet" type="text/css" media="all">

http://localhost:8080/testproject/org/resources/css/style.css

<link href="<core:url value="res/css/style.css"/>" rel="stylesheet" type="text/css" media="all">

http://localhost:8080/testproject/org/res/css/style.css

Let me know what exactly I'm doing wrong here. I know above code will work but some configuration I'm missing or configured wrong.

I've tried to capture all possible details which may cause this issue. Let me know if need more details.

Update 2

I created simple spring MVC project which can be downloaded form below link

https://drive.google.com/file/d/1-WqLnuEH2BffvcwBil7QcKcxqPay214Y/view?usp=sharing

few doubts

static resource loads normally with below code, with or without resource handler mapping in MvcWebConfig.java just uncomment line 4 & comment line 5 in welcome.jsp css will load.

the only change i made is "/" in value parm before css/test.css.

<link href="<core:url value="/css/test.css"/>" rel="stylesheet" type="text/css" media="all">

but after adding resource handler , i see 404 error, help me to resolve this issue

@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // TODO Auto-generated method stub
        WebMvcConfigurer.super.addResourceHandlers(registry);
        
        registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/static/css");
    }

JSP CHANGES

<link href="<core:url value="/resources/test.css"/>" rel="stylesheet" type="text/css" media="all">

can any one please explain what is the difference between all these mapping or let me know if any of them are wrong.

assuming src/main/java/resources/static/css/*.css is static folder structure.

registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/static/css");

registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/");

registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");

below will work as i've changed handler mapping (myresources) other than folder structure

registry.addResourceHandler("/myresources/**").addResourceLocations("classpath:/resources/static/css");

when i should use classpath in locations ?

registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/static/css");

Solution

  • Folder Structure

    below code worked for me

    registry.addResourceHandler("/res/**").addResourceLocations("classpath:/static/");
    
    <link href="<core:url value="/res/css/test.css" />" rel="stylesheet" type="text/css">
    

    or

    registry.addResourceHandler("/resource/**").addResourceLocations("classpath:/static/");
    
    <link href="<core:url value="/resource/css/test.css" />" rel="stylesheet" type="text/css">
    

    none of them worked given below

    registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/static/css");
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    registry.addResourceHandler("/res/**").addResourceLocations("/static/");
    registry.addResourceHandler("/res/**").addResourceLocations("/resources/");