【问题标题】:Thymeleaf cannot resolve static ressources when using SpringMVC's @PathVariable使用 Spring MVC @PathVariable 时,Thymeleaf 无法解析静态资源
【发布时间】:2019-10-14 07:28:14
【问题描述】:

不知何故,我的 CSS 文件未包含在我的百里香模板中。

首先我需要解释一下工作流程:

  1. 用户点击表单-提交发送POST到/historyDe​​tails/{history_id}
  2. 将使用 history_id 从数据库中获取一些数据
  3. 数据将在 history-detail-view.html 上呈现

这是我的 DispatcherServlet:

@Configuration
@EnableWebMvc
@ComponentScan("*")
public class DispatcherServlet extends WebMvcConfigurerAdapter {
    @Autowired
    private WebApplicationContext ctx;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /*
         * resolve path to static ressources (images, stylesheets, javascript-files)
         */
        registry.addResourceHandler("img/**").addResourceLocations("/WEB-INF/static/img/");
        registry.addResourceHandler("css/**").addResourceLocations("/WEB-INF/static/css/");
        registry.addResourceHandler("js/**").addResourceLocations("/WEB-INF/static/js/");
    }

    @Bean
    public ThymeleafViewResolver getViewResolver() {
        ThymeleafViewResolver vr = new ThymeleafViewResolver();

        vr.setTemplateEngine(getTemplateEngine());

        return vr;
    }

    @Bean
    public SpringTemplateEngine getTemplateEngine() {
        SpringTemplateEngine te = new SpringTemplateEngine();

        te.setTemplateResolver(getTemplateResolver());
        te.setEnableSpringELCompiler(true);

        return te;
    }

    @Bean
    public SpringResourceTemplateResolver getTemplateResolver() {
        SpringResourceTemplateResolver tr = new SpringResourceTemplateResolver();

        tr.setApplicationContext(ctx);
        tr.setOrder(1);
        /*
         * resolve path to html to WEB-INF/<name>.html
         * 
         * name can be something like templates/xxx.html
         */
        tr.setPrefix("WEB-INF/");
        tr.setSuffix(".html");

        return tr;
    }
}

我的项目结构(来自根目录):

这是 htistory-detail-view.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>

        <link rel="stylesheet"
                type="text/css"
                th:href="@{css/style.css}"/>

        <script type="text/javascript"
                th:src="@{https://code.jquery.com/jquery-3.4.1.min.js}"></script>
        <script type="text/javascript"
                th:src="@{js/utilities.js}"></script>

    </head>

    <body>
        <div th:replace="fragments/grid :: grid(${grid}, 'HISTORY_DETAIL')"></div>
        <div th:replace="fragments/paging :: paging(${grid})"></div>
    </body>

    <div th:replace="fragments/general :: footer"></div>
</html>

虽然 index.html 是用 css 渲染的,但 history-detail-view.html 不是纯 html。

我从 Firefox 的网络选项卡中获取的唯一错误消息是:

Loading failed for the <script> with source “http://localhost:9080/MyProject/historyDetails/js/utilities.js”.

我将 DispatcherServlet 放入这个线程的原因是因为它负责解析静态资源的路径。将项目结构中的路径与错误消息中的路径进行比较时,DispatcherServlet 似乎无法正常工作,但我不知道如何使其解析正确的路径。

我在这里看到的唯一区别是 Pathvariable。

编辑:我提供了我的 index.html,因为它在这里可以正常工作:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>

        <link rel="stylesheet"
                type="text/css"
                th:href="@{css/style.css}"/>

        <script type="text/javascript"
                th:src="@{https://code.jquery.com/jquery-3.4.1.min.js}"></script>
        <script type="text/javascript"
                th:src="@{js/utilities.js}"></script>

    </head>

    <body>
        <div th:replace="fragments/grid :: grid(${grid}, 'HISTORY')"></div>
        <div th:replace="fragments/paging :: paging(${grid})"></div>
    </body>

    <div th:replace="fragments/general :: footer"></div>
</html>

【问题讨论】:

  • 使用"@{/js/utilities.js} 代替"@{js/utilities.js} 有效吗?
  • 不,不幸的是,在我的 DispatcherServlet 中,开头的 / 无论如何都已解决(在我的 index.html 中)

标签: html css spring-mvc thymeleaf


【解决方案1】:

问题可能是由于 spring 安全配置(如果有)。在 spring 安全配置中添加 CSS 静态文件的路径作为例外。

如果你没有使用 spring security 或者你提供了异常,请确保你遵循了标准的文件夹结构。

通过this link了解更多详情。

【讨论】:

  • 1.我没有提到任何关于 Spring Security 的内容,因此我没有使用它 2. 我截取了项目结构,这不是默认设置,但这就是为什么我提供了我的 DispatcherServlet 3. 正如我在 index.html 中提到的,我的静态资源是可解析的,但在我的history-detail-view.html 不是,因为我没有看到它们之间有任何区别(-section 相同)我无法解释为什么它无法解析静态资源 4. 我没有提到这是一个 springboot 项目,它是一个 JEE 项目,因此我需要将链接映射到调度程序 servlet 中的静态资源