Spring Boot + Thymeleaf css не применяется к шаблону

Я оцениваю Thymeleaf и Flying Saucer для создания PDF-файлов из шаблонов, и у меня возникла проблема с применением css к моему шаблону Thymeleaf. Я уже читал соответствующие вопросы и ответы здесь, здесь и здесь; но ни одно из предложенных решений не устранило мою проблему.

Вот так выглядит моя папка с ресурсами:

Spring Boot + Thymeleaf css не применяется к шаблону

Поэтому я использую каталоги по умолчанию, которые будет искать Spring. А вот так заголовок выглядит в моем 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>

Если я встроу свой 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);
    }
}

Я использую 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

Что мне здесь не хватает, почему мой style.css не применяется к template.html?

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
0
0
7 280
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Синтаксис выглядит нормально, поэтому проблема не в синтаксисе.

Также вы не можете использовать синтаксис @{...} без интерфейса IWebContext, поэтому вы получаете это исключение.

Я также считаю, что синтаксис в порядке, как и структура ресурсов. Встраивание css тоже работает, поэтому я не думаю, что есть проблема с генерацией pdf. Вот почему я озадачен, не понимаю, в чем может быть проблема.

Egemen 09.11.2018 13:18

У меня была аналогичная проблема - мой CSS не был применен к моей странице шаблона.

Моя проблема заключалась в том, что файл css был в формате css sass

.table
   margin: 0 0 40px 0

когда я конвертирую его в обычный формат css, например

 .table {
  margin: 0 0 40px 0;
  }

это сработало

Ответ принят как подходящий

У меня были те же проблемы, и я также пытался использовать преобразователь шаблонов тимелеафа для генерации PDF. Я провел много исследований по тимелеафу и фреймворку Spring, я попробовал WebContext, я попробовал HttpServletRequest, я попробовал некоторые интеграционные решения Spring Thymeleaf, которые тоже не работали. Поэтому я думаю, что это не синтаксическая ошибка, и в итоге я использую абсолютный путь вместо относительного. URL для справки

Вот причина моего предположения, допустим, наши ресурсы обслуживаются на localhost:8080/myapp/css/style.css. И относительный путь к запросу ресурса действительно зависит от контекста, к которому он относится. Для eaxmple обычная модель тимелеафа Veiw, которая возвращается в виде HTML-страниц в браузере для клиента, поэтому контекстом в этом случае будет имя хоста запроса, порт и контекст приложения (например: localhost: 8080 / myapp). И относительный путь будет основан на этом. Поэтому, если относительный путь /css/style.css, контекст + относительный путь будет localhost:8080/myapp/css/style.css

В отличие от веб-контекста, в нашем случае офлайн-шаблон находится на серверной части, поэтому я предполагаю, что контекстом будет контекст запуска сервера, которым будет путь к локальному серверу + контекст приложения (например: 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}"/>

Он работает нормально, но что, если есть несколько имен хостов или сервер работает на прокси-сервере, тогда это будет жестко запрограммированное решение. Лучше знать, какой реальный базовый URL запрашивает пользователь. Таким образом, мы не можем избавиться от HttpSevletRequest.

Вот мой код:

Обработчик ресурсов 1.Config:

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/css/**")
    .addResourceLocations("classpath:/css/")
            .setCachePeriod(31556926);
}
  1. Получите базовый URL-адрес из HttpServletRequest, вы можете ввести его в метод или автоматически подключить в своем классе обслуживания или получить из RequestContextHolder. Я пишу это в своем классе обслуживания:

    private static String getCurrentBaseUrl() {
    ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
    HttpServletRequest req = sra.getRequest();
    return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath();
    } 
    
  2. Это то место, где я использую шаблонизатор в своем классе:

        Context context = new Context();
        context.setVariable("variales", variables);
        context.setVariable("baseUrl", getCurrentBaseUrl());
        String content = springTemplateEngine.process("myTemplate",context);
    
  3. В моем шаблоне я использую абсолютный URL-адрес css следующим образом:

    <link type = "stylesheet" th:src = "@{|${baseUrl}/css/style.css|}" />
    

Спасибо за ответ. Я мог бы заставить его работать и с абсолютным путем, хотя я не очень люблю использовать абсолютные пути. Одно замечание: я использовал th:href = "@{|${baseUrl}/css/style.css|}" в шаблоне, и мне не нужно было реализовывать addResourceHandlers.

Egemen 13.12.2018 10:08

Думаю, мы в такой же ситуации, мне тоже не нравится абсолютный путь. Но насколько я знаю, это единственный способ заставить его работать у меня. Что касается обработчика ресурсов, я просто хочу убедиться, что статический контент должен обслуживаться в Интернете. Это не так уж и плохо, потому что базовый URL полностью зависит от реального запроса пользователя, поэтому он по-прежнему гибкий. Если вы можете найти решение для относительного пути, пожалуйста, дайте мне знать. Спасибо

Chenhai-胡晨海 13.12.2018 15:37

Я решил эту проблему, изменив структуру пути в href. У меня была та же структура каталогов, что и у вас (файлы HTML находятся в документах шаблонов, файлы css находятся в статических документах).

<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 = "/css/style.css"/> 
</head>

Это может помочь вам применить css к вашей html-странице.

Другие вопросы по теме