Spring Boot + Thymeleaf css 不适用于模板

Ege*_*men 0 css thymeleaf spring-boot

我正在评估 Thymeleaf 和 Flying Saucer 以从模板生成 pdf,我在将 css 应用到我的 Thymeleaf 模板时遇到了问题。我已经在这里这里这里阅读了相关的问题和答案;但没有一个建议的解决方案解决了我的问题。

这是我的资源文件夹的样子:

在此处输入图片说明

所以我使用的是 Spring 将寻找的默认目录。这就是我的 head 标签的样子template.html

<head>
    <title>Spring Boot and Thymeleaf Example</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <link rel="stylesheet" type="text/css" href="../static/css/style.css" th:href="@{/css/style.css}"/> 
</head>
Run Code Online (Sandbox Code Playgroud)

如果我内联我的 css,template.html那么生成的 pdf 文件的样式将正确(因此我生成 pdf 的方式应该没有问题)。但是,当我尝试链接到如上所示的 css 文件时,生成的 pdf 未设置样式(因此未应用 css)。

最后,我可以在 访问我的 css 文件http://localhost:8080/css/style.css,因此 Spring 提供静态内容似乎没有问题。

为了完整起见,这就是我生成 pdf 的方式:

private final SpringTemplateEngine templateEngine;
private final Log log;

@Autowired
public PdfGenerator(SpringTemplateEngine templateEngine) {
    this.templateEngine = templateEngine;
    log = LogFactory.getLog(getClass());
}

public void generate(HttpServletRequest servletRequest, HttpServletResponse servletResponse, ServletContext servletContext) {
    // Parse the pdf template with Thymeleaf
    Locale locale = getLocale(servletRequest);
    WebContext context = new WebContext(servletRequest, servletResponse, servletContext, locale);
    context.setVariable("user", buildDummyUser());
    context.setVariable("discounts", buildDummyDiscounts());
    String html = templateEngine.process("template", context);

    // Create the pdf with Flying Saucer
    try (OutputStream outputStream = new FileOutputStream("generated.pdf")) {
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(html);
        renderer.layout();
        renderer.createPDF(outputStream);
    } catch (IOException | DocumentException e) {
        log.error("Error while generating pdf", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用WebContext而不是Context因为我收到以下错误Context

org.thymeleaf.exceptions.TemplateProcessingException: Link base "/css/style.css" cannot be context relative (/...) unless the context used for executing the engine implements the org.thymeleaf.context.IWebContext interface
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么,为什么我的style.css不适用于template.html

Che*_*胡晨海 9

我遇到了同样的问题,我也在尝试使用 thymeleaf 模板解析器来生成 pdf。我对 thymeleaf 和 spring 框架做了很多研究,我尝试了 WebContext,我尝试了 HttpServletRequest,我尝试了一些 Spring Thymeleaf 集成解决方案,但它也不起作用。所以我认为这不是语法错误,我最终使用绝对路径而不是相对路径。 参考网址

这是我假设的原因,假设我们的资源是在localhost:8080/myapp/css/style.css. 请求资源的相对路径实际上取决于它相对于什么上下文。例如,一个普通的百里香模型 Veiw,它在客户端的浏览器上作为 html 页面返回,因此这种情况下的上下文将是请求主机名、端口和应用程序上下文(例如:localhost:8080/myapp)。相对路径将基于此。因此,如果相对路径是 /css/style.css,则上下文 + 相对路径将是localhost:8080/myapp/css/style.css

与 web 上下文不同,在我们的例子中,离线模板在服务器后端,所以我假设的上下文是服务器运行上下文,这将是本地服务器路径 + appcontext(例如:D:/myServer/apps/myapp),相对路径 /css/style.css 在这将是D:/myServer/apps/myapp/css/style.css,这是没有意义的。为了使用静态资源,我必须传递它的绝对路径。

我开始使用:

<link rel="stylesheet" type="text/css" th:href="@{http://localhost:8080/myapp/css/style.css}"/>
Run Code Online (Sandbox Code Playgroud)

它工作正常,但如果有多个主机名或服务器在代理上运行,那么这将是一个硬编码的解决方案。最好知道用户请求的真实基本 url 是什么。所以我们不能真正摆脱 HttpSevletRequest。

这是我的代码:

1.配置资源处理程序:

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/css/**")
    .addResourceLocations("classpath:/css/")
            .setCachePeriod(31556926);
}
Run Code Online (Sandbox Code Playgroud)
  1. 从 HttpServletRequest 获取基本 url,您可以将其注入方法或在您的服务类中自动装配,或者从 RequestContextHolder 获取。我在我的服务类中写了这个:

    private static String getCurrentBaseUrl() {
    ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
    HttpServletRequest req = sra.getRequest();
    return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath();
    } 
    
    Run Code Online (Sandbox Code Playgroud)
  2. 这是我在课堂上使用模板引擎的地方:

        Context context = new Context();
        context.setVariable("variales", variables);
        context.setVariable("baseUrl", getCurrentBaseUrl());
        String content = springTemplateEngine.process("myTemplate",context);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在我的模板中,我使用这样的绝对 css url:

    <link type="stylesheet" th:src="@{|${baseUrl}/css/style.css|}" />
    
    Run Code Online (Sandbox Code Playgroud)