paint-brush
Как выполнить рендеринг на стороне сервера с помощью Spring Bootк@nfrankel
321 чтения
321 чтения

Как выполнить рендеринг на стороне сервера с помощью Spring Boot

к Nicolas Fränkel8m2024/09/22
Read on Terminal Reader

Слишком долго; Читать

WebJars — это технология, разработанная Джеймсом Уордом для обработки именно этих требований. WebJars — это клиентские веб-библиотеки (например, jQuery и Bootstrap), упакованные в файлы JAR (Java Archive). Vaadin с его уникальной парадигмой действительно выделяется среди подходов.
featured image - Как выполнить рендеринг на стороне сервера с помощью Spring Boot
Nicolas Fränkel HackerNoon profile picture

Понимание общих шагов в настройке проекта имеет решающее значение перед погружением в специфику каждой технологии клиентского дополнения. Мои требования из последнего поста были довольно простыми:


  • Я приму точку зрения бэкэнд-разработчика.
  • Нет этапа сборки front-end: нет TypeScript, нет минификации и т. д.
  • Все зависимости управляются из внутреннего приложения, т.е. Maven.


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

WebJars

WebJars — это технология , разработанная в 2012 году Джеймсом Уордом именно для удовлетворения этих требований.


WebJars — это клиентские веб-библиотеки (например, jQuery и Bootstrap), упакованные в файлы JAR (Java Archive).


  • Явное и простое управление зависимостями на стороне клиента в веб-приложениях на базе JVM
  • Используйте инструменты сборки на основе JVM (например, Maven, Gradle, sbt, ...) для загрузки зависимостей на стороне клиента.
  • Знайте, какие клиентские зависимости вы используете
  • Транзитивные зависимости автоматически разрешаются и опционально загружаются через RequireJS
  • Развернуто на Maven Central
  • Публичный CDN, любезно предоставленный JSDelivr


-- Сайт Webjars


WebJar — это обычный JAR, содержащий веб-активы. Добавление WebJar к зависимостям проекта не представляет собой ничего особенного:


 <dependencies> <dependency> <groupId>org.webjars.npm</groupId> <artifactId>alpinejs</artifactId> <version>3.14.1</version> </dependency> </dependencies>


Ответственность фреймворка заключается в том, чтобы выставлять активы по URL. Например, Spring Boot делает это в классе WebMvcAutoConfiguration :


 public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(), //1 "classpath:/META-INF/resources/webjars/"); addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocations()); if (this.servletContext != null) { ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION); registration.addResourceLocations(resource); } }); }
  1. Значение по умолчанию: "/webjars/**"


Внутри JAR вы можете получить доступ к ресурсам по их соответствующему пути и имени. Согласованная структура заключается в том, чтобы хранить ресурсы внутри resources/webjars/<library>/<version> . Вот структура alpinejs-3.14.1.jar :


 META-INF |_ MANIFEST.MF |_ maven.org.webjars.npm.alpinejs |_ resources.webjars.alpinejs.3.14.1 |_ builds |_ dist |_ cdn.js |_ cdn.min.js |_ src |_ package.json


В Spring Boot вы можете получить доступ к неминифицированной версии с помощью /webjars/alpinejs/3.14.1/dist/cdn.js .


Разработчики выпускают клиентские библиотеки довольно часто. Когда вы меняете версию зависимости в POM, вы должны изменить путь к интерфейсу, возможно, в нескольких местах. Это скучно, не имеет никакой дополнительной ценности, и вы рискуете пропустить изменение.


Проект WebJars Locator направлен на то, чтобы избежать всех этих проблем, предоставляя путь без версии, т. е . /webjars/alpinejs/dist/cdn.js . Вы можете добиться этого, добавив JAR-файл webjars-locator в свои зависимости:


 <dependencies> <dependency> <groupId>org.webjars.npm</groupId> <artifactId>alpinejs</artifactId> <version>3.14.1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>0.52</version> </dependency> </dependencies>


Я буду использовать этот подход для каждой фронтенд-технологии. Я также добавлю библиотеку Bootstrap CSS, чтобы обеспечить более привлекательный пользовательский интерфейс.

Тимелист

Thymeleaf — это технология рендеринга на стороне сервера.


Thymeleaf — это современный серверный шаблонизатор Java для веб- и автономных сред.


Основная цель Thymeleaf — привнести в ваш рабочий процесс разработки элегантные естественные шаблоны — HTML, которые могут корректно отображаться в браузерах, а также работать в качестве статических прототипов, обеспечивая более тесное сотрудничество в группах разработчиков.


Благодаря модулям для Spring Framework, множеству интеграций с вашими любимыми инструментами и возможности подключать собственные функции Thymeleaf идеально подходит для современной веб-разработки на базе HTML5 JVM, хотя он может делать гораздо больше.


-- Тимелист


Я был еще консультантом, когда впервые узнал о Thymeleaf. В то время Java Server Pages были на закате своей жизни. Java Server Faces пытались заменить их; IMHO, они потерпели неудачу.


Я думал, что Thymeleaf — это фантастический подход: он позволяет вам видеть результаты в статической среде во время проектирования и в серверной среде во время разработки. Еще лучше, вы можете легко перемещаться между ними, используя один и тот же файл. Я никогда не видел, чтобы эта возможность использовалась.


Однако Spring Boot полностью поддерживает Thymeleaf. Вишенка на торте: последний доступен через пространство имен HTML на странице. Если вы не купили JSF (спойлер: я не купил), Thymeleaf — это сегодняшний язык шаблонизации SSR.


Вот демонстрационный пример с сайта:


 <table> <thead> <tr> <th th:text="#{msgs.headers.name}">Name</th> <th th:text="#{msgs.headers.price}">Price</th> </tr> </thead> <tbody> <tr th:each="prod: ${allProducts}"> <td th:text="${prod.name}">Oranges</td> <td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td> </tr> </tbody> </table>


Вот Thymeleaf 101, на случай, если вам нужно ознакомиться с технологией.


  • Когда вы открываете файл HTML, браузер отображает обычное значение внутри тегов, т. е . Name и Price . Когда вы используете его на сервере, Thymeleaf включается и отображает значение, вычисленное из th:text , #{msgs.headers.name} и #{msgs.headers.price} .
  • Оператор $ запрашивает компонент Spring с тем же именем, которое было передано в модель. ${prod.name} эквивалентно model.getBean("prod").getName()" .
  • Символ # вызывает функцию.
  • th:each допускает циклы.

Интеграция Thymeleaf с интерфейсной средой

Большинство, если не все, фронтенд-фреймворки работают с клиентской моделью. Нам нужно навести мост между серверной и клиентской моделями.


Я использую следующий код на стороне сервера:


 data class Todo(val id: Int, var label: String, var completed: Boolean = false) //1 fun config() = beans { bean { mutableListOf( //2 Todo(1, "Go to the groceries", false), Todo(2, "Walk the dog", false), Todo(3, "Take out the trash", false) ) } bean { router { GET("/") { ok().render( //3 "index", //4 mapOf("title" to "My Title", "todos" to ref<List<Todo>>()) //5 ) } } } }
  1. Определите класс Todo .


  2. Добавьте список в памяти к фабрике компонентов. В обычном приложении вы бы использовали Repository для чтения из базы данных.


  3. Создайте HTML-шаблон.


  4. Шаблон — src/main/resources/templates/index.html с атрибутами Thymeleaf.


  5. Поместите модель в контекст страницы.



Thymeleaf предлагает атрибут th:inline="javascript" в теге <script> . Он отображает данные на стороне сервера как переменные JavaScript. Документация объясняет это гораздо лучше, чем я когда-либо мог:


Первое, что мы можем сделать с помощью встраивания скриптов, — это записать значения выражений в наши скрипты, например:


 <script th:inline="javascript"> /*<![CDATA[*/ ... var username = /*[[${session.user.name}]]*/ 'Sebastian'; ... /*]]>*/ </script>


Синтаксис /*[[...]]*/ предписывает Thymeleaf оценить содержащееся выражение. Но здесь есть и другие последствия:


  • Поскольку наше выражение является комментарием JavaScript (/*...*/) , оно будет проигнорировано при статическом отображении страницы в браузере.

  • Код после встроенного выражения ( 'Sebastian' ) будет выполнен при статическом отображении страницы.

  • Thymeleaf выполнит выражение и вставит результат, но также удалит весь код в строке после самого встроенного выражения (часть, которая выполняется при статическом отображении).


-- Документация Thymeleaf


Если мы применим вышеизложенное к нашему коду, мы можем получить атрибуты модели, переданные Spring, как:


 <script th:inline="javascript"> /*<![CDATA[*/ window.title = /*[[${title}]]*/ 'A Title' window.todos = /*[[${todos}]]*/ [{ 'id': 1, 'label': 'Take out the trash', 'completed': false }] /*]]>*/ </script>


При рендеринге на стороне сервера результат будет следующим:


 <script> /*<![CDATA[*/ window.title = "My title"; window.todos: [{"id":1,"label":"Go to the groceries","completed":false},{"id":2,"label":"Walk the dog","completed":false},{"id":3,"label":"Take out the trash","completed":false}] /*]]>*/ </script>

Краткое содержание

В этом посте я описал два компонента, которые буду использовать на протяжении всей оставшейся части этой серии:


  • WebJar-файлы управляют зависимостями на стороне клиента в вашем Maven POM.


  • Thymeleaf — это механизм шаблонов, который хорошо интегрируется со Spring Boot.


Полный исходный код этой статьи можно найти на GitHub.


Идем дальше:


Первоначально опубликовано в A Java Geek 15 сентября 2024 г.