【问题标题】:Thymeleaf Template (Spring MVC) unable to locate static resourceThymeleaf 模板(Spring MVC)无法找到静态资源
【发布时间】:2015-11-13 03:17:08
【问题描述】:

Thymeleaf 模板定位放置在 Web 应用程序根目录中的静态文件(包括下面的 CSS 文件)的问题。我已经通过 addResourceHandlers() 方法添加了相关的映射(/resource)(参见下面的配置类)。

也许这与最近切换到 gradle(以前是 Maven)有关。我可能忽略了 build.gradle 文件中的某些内容?

 <link rel="stylesheet" th:href="@{'/resources/stylesheets/test.css'}" type="text/css" media="screen" />

浏览器控制台输出(页面加载时)

Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:8080/resources/stylesheets/test.css".

百里香

<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:tiles="http://www.thymeleaf.org">
<head>
    <!--Stylesheets -->
    <link rel="stylesheet" th:href="@{'/resources/stylesheets/test.css'}" type="text/css" media="screen" />

    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1"/>

</head>
...
</html>

.war 目录结构

- root/
 --stylesheets/
   --- test.css 
 --images/
 --META-INF/
 --WEB-INF/ 
 --...

配置类

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/resources/**").addResourceLocations("/")
                            .setCachePeriod(31556926);
        }
...
}

Gradle 构建文件

buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath 'com.bmuschko:gradle-tomcat-plugin:2.2.2'
    }
}

plugins {
    id "com.bmuschko.tomcat" version "2.2.2"
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'war'
apply plugin: 'com.bmuschko.tomcat-base'
version = '1.0'
group = 'com.project'

sourceCompatibility = 1.8
targetCompatibility = 1.8

war {
    baseName = '/'
    archiveName = "${project.name}.war"
}

war.doLast {
    ant.unzip(src: war.archivePath, dest: "$buildDir/$project.name")
}
sourceSets {
    main {
           java{
               srcDir 'src/main/java'
           }
            resources {
                srcDir 'src/main/resources'
            }
        }
    test {
          java {
             srcDir 'src/test/java'
         }
         resources {
            srcDir 'src/test/resources'
        }
    }
}

dependencies {
    modules {
            module("javassist:javassist") {
                replacedBy("org.javassist:javassist")
            }
        }

    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
            "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
    tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
        exclude group: "org.eclipse.jdt.core.compiler", module: "ecj"
    }
        ....               
}

repositories {
    jcenter()

        mavenCentral()
         mavenLocal()
 }

task wrapper(type: Wrapper) {
    gradleVersion = '2.6'
}


jar {
    manifest {
        attributes 'Implementation-Title': 'App',
                   'Implementation-Version': version
    }
}


test {
    systemProperties 'property': 'value'  
  testLogging {
        // Show that tests are run in the command-line output
        events 'started', 'passed'
        exceptionFormat "full"
        showStandardStreams = true
        showCauses = true
        showExceptions = true

        }
}

【问题讨论】:

  • 我记得,.addResourceLocations("/") 会尝试在类路径根目录中查找资源,例如在src/main/resources而不是war文件根目录?
  • "/" 确实指向部署根目录。

标签: spring spring-mvc gradle spring-boot


【解决方案1】:

事实证明,Controller 内部的类级别 RequestMapping 是原因。必须将其更改为方法级别(见下文)。

错误

@Controller("/register")
public class RegistrationController {    
   @RequestMapping(method = RequestMethod.GET)
    public String showRegistrationForm(WebRequest request, Model model) {
        return "...";
    }

正确

@Controller
public class RegistrationController {
   @RequestMapping(value="/register",method = RequestMethod.GET)
    public String showRegistrationForm(WebRequest request, Model model) {
        return "...";
    }

【讨论】:

  • 我也面临同样的问题。使用您提供的解决方案,我已经在方法级别而不是在类级别进行了请求映射。这仍然行不通。我有带有 thymeleaf 模板引擎的 Spring Boot Setup。 CSS 仍未解决。
  • 贴出问题的链接,我来看看。
【解决方案2】:
  1. 您必须将静态资源定位到“src/main/webapp/resources/static”文件夹中(而不是在“Java Resources/src/main/resources”中)。 (如果您在 Eclipse 上工作,您可能会多次看到“src”文件夹)。

  2. 在 MvcConfig.java 中,您应该添加静态资源的链接和接受的模式作为 belove。

     public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/","/resources/");
    }
    
  3. 在您的 html 页面中,使用带有 thymleaf 演示文稿的静态资源链接。

&lt;link th:href="@{./resources/static/css/bootstrap.min.css}"  type="text/css" rel="stylesheet" media="screen"&gt;&lt;/link&gt;

【讨论】:

    【解决方案3】:

    您为什么不尝试像下面这样附加上下文路径 (~)。

    符号“~”将被认为是相对于服务器根目录的。

    <link rel="stylesheet" th:href="@{'~/resources/stylesheets/test.css'}" type="text/css" media="screen" />
    

    我希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      您可以像这样将资源定位到类路径:

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

      我建议你应该添加目录名称:

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

      您不再需要修改其他文件。

      【讨论】:

        【解决方案5】:
        <link rel="stylesheet" th:href="@{/resources/stylesheets/test.css}" type="text/css" media="screen" />
        

        尝试不使用“”,因为您引用的是资源而不是字符串。同样为了做得更好,以防万一不是所有代码都是 Thymeleaf,您应该执行以下操作:

        <link rel="stylesheet" href="../resources/stylesheets/test.css" th:href="@{/resources/stylesheets/test.css}" type="text/css" media="screen" />
        

        【讨论】:

        • @JamieWhite 你还有同样的错误吗?还是错误发生了变化?