Spring Boot + Thymeleaf css не применяется к шаблону - PullRequest
0 голосов
/ 08 ноября 2018

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

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

enter image description here

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

Если я вставлю свой 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?

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

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

Моя проблема была в том, что файл css был в формате css sass

.table
   margin: 0 0 40px 0

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

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

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

0 голосов
/ 12 декабря 2018

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

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

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

Работает нормально, но что, если на прокси работает несколько имен хостов или сервер работает, то это будет жестко запрограммированное решение. Лучше знать, какую реальную базовую ссылку запрашивает пользователь. Поэтому мы не можем избавиться от запроса 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|}" />
    
0 голосов
/ 08 ноября 2018

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...