Thymeleaf无法加载静态资源

时间:2018-04-02 04:05:41

标签: spring thymeleaf

我有一个spring web应用程序可以正确加载模板,但不会加载CSS和图像等静态资源。我在src / main / resources / static目录中添加了我的静态资源,添加了thymeleaf注释,添加了配置并在StackOverflow上针对类似问题进行了检查,但我的CSS /图像文件都没有加载:

控制台错误

Refused to apply style from 'http://localhost:8080/login' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

目录结构

Directory Structure

TemplateConfig.java

package com.valencra.recipes.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;

@Configuration
public class TemplateConfig {
  @Bean
  public SpringResourceTemplateResolver templateResolver() {
    final SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
    templateResolver.setPrefix("classpath:/templates/");
    templateResolver.setSuffix(".html");
    templateResolver.setTemplateMode("LEGACYHTML5");
    return templateResolver;
  }

  @Bean
  public SpringTemplateEngine templateEngine() {
    final SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
    springTemplateEngine.addTemplateResolver(templateResolver());
    springTemplateEngine.addDialect(new SpringSecurityDialect());
    return springTemplateEngine;
  }

  @Bean
  public ThymeleafViewResolver viewResolver() {
    final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    viewResolver.setTemplateEngine(templateEngine());
    viewResolver.setOrder(1);
    return viewResolver;
  }
}

的layout.html

<!DOCTYPE html>
<html lang="en">

<head th:fragment="head">

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">

    <title>My Recipes</title>

    <link href='https://fonts.googleapis.com/css?family=Varela+Round' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" th:href="@{/css/unsemantic-grid-responsive.css}">
    <link rel="stylesheet" th:href="@{/css/styles.css}">

</head>

<body>

    <nav th:fragment="nav">
        <a th:href="@{|/profile|}" th:text="${currentUser.name}">
            Chandra S.
        </a>
        &bull;
        <form th:action="@{/logout}" method="post" style="display: inline">
            logout
        </form>
    </nav>

    <div th:fragment="home">
        <div class="grid-100">
            <a th:href="@{|/|}">
                <h1>
                    <img th:src="@{/images/chefbot.svg}" height="60px">
                    <br>
                    My Recipes
                </h1>
            </a>
        </div>
    </div>

    <div th:fragment="favorite">
        <form th:action="@{|/recipes/${recipe.id}/favorite|}" method="post" style="display:inline">
            <button type="submit">
                <img th:src="${recipe.isFavorite(currentUser)} ? @{/images/favorited.svg} : @{/images/favorite.svg}" style="height: 15px;">
            </button>
        </form>
    </div>

</body>

</html>

的login.html

<!doctype html>
<html lang="en">

<head th:replace="layout :: head"></head>

<body>

    <nav>
        <a th:href="@{/signup}">
            sign-up
        </a>
    </nav>

  <div class="grid-container">

    <div th:replace="layout :: home"></div>

    <div class="grid-100">
      <div class="recipes">

        <form th:action="@{|/login|}" method="post" th:object="${user}">
          <div class="prefix-20 grid-60 suffix-20">
            <p>
              <input placeholder="Username" th:field="*{username}"> </input>
            </p>
          </div> <div class="clear"></div>
          <div class="prefix-20 grid-60 suffix-20">
            <p>
              <input placeholder="Password" type="password" th:field="*{password}"> </input>
            </p>
          </div> <div class="clear"></div>
          <div class="prefix-20 grid-60 suffix-20">
            <p>
              <button>Login</button>
            </p>
          </div> <div class="clear"></div>
        </form>

      </div> <!-- recipes -->
    </div> <!-- grid-100 -->

  </div> <!-- grid-container -->

</body>

</html>

2 个答案:

答案 0 :(得分:3)

看起来您的CSS作为HTML提供。

由于您将样式表放在30x Spring中,因此应根据合理的默认值设置大多数内容,包括设置正确的内容类型标题。

我假设您使用的是Spring Security,因为您显示了登录表单。

可能是您的资源受Spring Security保护。因此,您可以使用text/html重定向到登录页面而不是样式表。这可以解释为什么您的浏览器抱怨HttpSecurity内容类型,这对于CSS而言是错误的,但登录页面的类型是正确的。

您是否在项目的某个位置配置@EnableWebSecurity(最有可能使用@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/css/**", "/images/**").permitAll() // rest of your code 进行注释)?

如果是这样,您需要允许匿名访问您的资源:

String filename = "config.json";
String fileContents = "Your config content..";
FileOutputStream outputStream;

try {
    outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
    outputStream.write(fileContents.getBytes());
    outputStream.close();
} catch (Exception e) {
    e.printStackTrace();
}

如果您切换到浏览器控制台中的网络选项卡,您应该能够检查重定向到登录页面。

答案 1 :(得分:0)

对我而言,帮助的是@phisch和以下代码的答案

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(
            "/webjars/**",
            "/img/**",
            "/css/**",
            "/js/**")
            .addResourceLocations(
                    "classpath:/META-INF/resources/webjars/",
                    "classpath:/static/img/",
                    "classpath:/static/css/",
                    "classpath:/static/js/");
     }

}