Разработка на Groovy
DC CMS поддерживает серверную разработку с помощью Groovy. Использование Groovy позволяет создавать RESTful сервисы, контроллеры MVC, код, который выполняется перед отображением страницы или компонента,, сервлетные фильтры, запланированные задачи и полноценные бэкэнд приложения.
Groovy API
DC CMS предоставляет ряд глобальных переменных, которые можно использовать во всех доступных типах скриптов:
Название | Описание | Тип |
---|---|---|
siteItemService | Предоставляет доступ к контенту сайта | SiteItemService |
urlTransformationService | Сервис для преобразования URL-адресов, например, для преобразования URL-адреса контента страницы в веб-URL или URL-адрес для рендеринга | UrlTransformationService |
search | Сервис, который можно использовать для выполнения запросов на поиск в ElasticSearch | ElasticSearchWrapper |
applicationContext | Предоставляет доступ к Spring-бинам (bean) CMS Engine и бинам сайта, определенным в файле config/spring/application-context.xml |
ApplicationContextAccessor |
globalProperties | Предоставляет доступ к свойствам глобальной конфигурации, определенным в server-config.properties |
PropertySourcesPropertyResolver |
navBreadcrumbBuilder | Вспомогательный класс, который возвращает список компонентов пути в URL для создания навигационных хлебных крошек (бредкрамбов) | BreadcrumbBuilder |
navTreeBuilder | Вспомогательный класс, который создает навигационные деревья для облегчения рендеринга | NavTreeBuilder |
tenantsResolver | Может использоваться для получения профилей арендаторов, связанных с текущим сайтом | TenantsResolver |
profileService | Предоставляет доступ к CMS Profile API для профилей | ProfileService |
tenantService | Предоставляет доступ к API CMS Profile для арендаторов | TenantService |
authenticationService | Предоставляет доступ к API CMS Profile для аутентификации | AuthenticationService |
authenticationManager | Управляет аутентификациями на основе CMS Security Provider | AuthenticationManager |
textEncryptor | Служебный класс для шифрования/дешифрования текста с помощью AES | См. TextEncryptor в разделе org.springframework.security.crypto.encrypt в Spring Security apidocs. |
modePreview | Флаг, указывающий, что CMS Engine выполняется в режиме предварительного просмотра (также значение свойства cms.engine.preview ) |
Boolean |
cmsEnv | Указывает значение свойства cms.engine.environment |
String |
logger | Логгер GroovyUtils SLF4J | Logger |
siteConfig | Текущая конфигурация сайта, загруженная из /config/site.xml |
См. XMLConfiguration в разделе org.apache.commons.configuration2 в Apache Commons apidocs. |
siteContext | Текущий SiteContext | SiteContext |
Есть несколько других переменных, доступных для скриптов, которые выполняются во время выполнения запроса (скрипты REST, скрипты контроллера, скрипты страниц/компонентов и скрипты фильтров:
Название | Описание | Тип |
---|---|---|
request | Текущий запрос | HttpServletRequest |
response | Текущий ответ | HttpServletResponse |
params | Значения параметров для текущего запроса | Map |
headers | Значения заголовка для текущего запроса | Map |
cookies | Значения файлов cookie для текущего запроса | Map |
session | Текущая сессия (если она была создана) | HttpSession |
locale | Текущий язык для текущего пользователя | Locale |
authToken | Текущая аутентификация (если пользователь вошел в систему), созданная Spring Security | Authentication |
Следующие переменные предоставляются для обеспечения обратной совместимости при использовании CMS Profile и, по возможности, должны быть заменены на authToken
:
Название | Описание | Тип |
---|---|---|
authentication | Текущая аутентификация (если пользователь вошел в систему), созданная CMS Security Provider | Authentication |
profile | Текущий профиль (если пользователь вошел в систему), созданная CMS Security Provider | Profile |
Переменные profile
и authentication
в большинстве случаев будут иметь значение null
и больше не должны использоваться.
Следующие переменные ограничены по умолчанию, их использование описано в статье “Конфигурация CMS Engine”:
Название | Описание | Тип |
---|---|---|
application | Контекст сервлета | ServletContextHashModel |
Все скрипты выполняются в песочнице (sandbox), чтобы предотвратить запуск небезопасного кода. Для изменения конфигурации обратитесь к разделу "Unit-тестирование кода на Groovy в DC CMS" ниже.
Типы скриптов
Существуют различные типы скриптов в зависимости от папки в разделе Скрипты, в которую они помещены.
Скрипты REST
Скрипты REST работают аналогично RESTful-сервисам. Их основная функция - возвращать объект, который можно сериализовать обратно вызывающему. Эти скрипты должны быть размещены в любой папке по пути scripts > rest.
Структура URL для REST-скрипта имеет следующий формат: он начинается с /api/1/services
, за которым следуют все папки в иерархии, ведущие к конкретному скрипту. Наконец, он заканчивается именем скрипта, соответствующим HTTP-методом и расширением .groovy
. Например, скрипт, расположенный по адресу scripts > rest > myfolder > myscript.get.groovy
, будет отвечать на GET-запросы по адресу http://mysite/api/1/services/myfolder/myscript.json
.
Ниже приведен простой пример скрипта, который извлекает атрибут даты, сохраненный в сессии. Если атрибут еще не установлен, текущая дата сохраняется в качестве значения атрибута. Предположим, что этот REST-скрипт существует по адресу scripts > rest > session_date.get.groovy
.
import java.util.Date
if (!session) {
session = request.getSession(true)
}
def date = session.getAttribute("date")
if (!date) {
date = new Date()
session.setAttribute("date", date)
}
return ["date": date]
Скрипт не найден
Скрипты Rest будут возвращать страницу 404, если скрипт не найден. Разработчики по-прежнему смогут возвращать кастомные ответы 404 из скриптов REST. Например:
response.setStatus(404)
return 'This is the custom message'
Они могут даже отправить страницу ответа по умолчанию, используя sendError
:
response.sendError(404)
Скрипты контроллера
Скрипты контроллера похожи на REST-скрипты. У них доступны те же переменные, но вместо возвращения объекта они возвращают строку с представлением для отображения. Чаще всего это просто путь к шаблону, как в следующем фрагменте кода:
return "/templates/web/registration.ftl"
Функционируя подобно контроллеру в шаблоне MVC, скрипты контроллера обычно находятся в папке scripts > controllers
. Подобно REST-скриптам, их URL состоит из иерархии директории, имени скрипта и HTTP-метода. Например, скрипт, расположенный в scripts > controllers > myfolder > mycontroller.get.groovy
, будет обрабатывать GET-запросы по адресу http://mysite/myfolder/mycontroller
.
Вот простой пример скрипта, который вычисляет сумму двух параметров, присваивает результат объекту templateModel
и указывает путь к FTL-шаблону, ответственному за отображение результата:
templateModel.result = Integer.parseInt(params.num1) + Integer.parseInt(params.num2)
return "/templates/web/sum.ftl"
Одним из часто используемых скриптов контроллера является sitemap.groovy
, который служит для предоставления поисковым системам структурированной карты сайта для эффективного индексирования. Карта сайта представляет собой XML-файл со ссылками на большинство страниц сайта и в основном выглядит следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.domain.com /</loc>
<lastmod>2008-01-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>http://www.domain.com/catalog?item=vacation_hawaii</loc>
<changefreq>weekly</changefreq>
</url>
<url>
<loc>http://www.domain.com/catalog?item=vacation_new_zealand</loc>
<lastmod>2008-12-23</lastmod>
<changefreq>weekly</changefreq>
</url>
<url>
<loc>http://www.domain.com/catalog?item=vacation_newfoundland</loc>
<lastmod>2008-12-23T18:00:15+00:00</lastmod>
<priority>0.3</priority>
</url>
<url>
<loc>http://www.domain.com/catalog?item=vacation_usa</loc>
<lastmod>2008-11-23</lastmod>
</url>
</urlset>
Поисковые системы обычно находят карту сайта непосредственно после домена, так что URL карты сайта будет напоминать www.domain.com/sitemap
. Следовательно, скрипт контроллера sitemap
должен быть размещен в scripts > controllers > sitemap.groovy
.
import groovy.xml.MarkupBuilder
import groovy.xml.MarkupBuilderHelper
def sitemap = []
def excludeContentTypes = ['/component/level-descriptor']
parseSiteItem = { siteItem ->
if (siteItem.isFolder()) {
def children = siteItem.childItems;
children.each { child ->
parseSiteItem(child);
}
} else {
def contentType = siteItem.queryValue('content-type')
if (!excludeContentTypes.contains(contentType)) {
def storeUrl = siteItem.getStoreUrl();
def location = urlTransformationService.transform('storeUrlToFullRenderUrl', storeUrl);
sitemap.add(location);
}
}
}
def siteTree = siteItemService.getSiteTree("/site/website", -1)
if (siteTree) {
def items = siteTree.childItems;
items.each { siteItem ->
parseSiteItem(siteItem);
}
}
response.setContentType("application/xml;charset=UTF-8")
def writer = response.getWriter()
def xml = new MarkupBuilder(writer)
def xmlHelper = new MarkupBuilderHelper(xml)
xmlHelper.xmlDeclaration(version:"1.0", encoding:"UTF-8")
xml.urlset(xmlns:"http://www.sitemaps.org/schemas/sitemap/0.9") {
sitemap.each { location ->
url {
loc(location)
changefreq("daily")
}
}
}
response.flushBuffer()
return null
Unit-тестирование кода на Groovy в DC CMS
Для крупных веб-сайтов, включающих сложные сервисы на основе Groovy, интеграция unit-тестов, совместимая с системами CI/CD, оказывается чрезвычайно полезной. В этом разделе предоставляется руководство по созданию unit-тестов для кода на Groovy в рамках DС CMS с использованием Gradle. Дополнительные сведения о типах переменных и классов, которые можно использовать для unit-тестирования, смотрите выше.
Создание unit-теста Groovy
Чтобы создать unit-тест:
- Определите папку для всех файлов, связанных с тестированием
- Напишите код unit-теста
- Настройте unit-тест для запуска с помощью Gradle
- Выполните unit-тест
Определение папки для файлов, связанных с тестированием
Укажите папку в репозитории сайта, в которой будут содержаться все файлы, связанные с тестированием. Например, CMS_HOME/data/repos/sites/SITENAME/sandbox
.
/scripts
/test
/classes (all packages & groovy classes for testing)
/resources (all additional files required for testing)
Эта структура является эквивалентом стандартных папок, используемых для проектов Java/Groovy:
/src/test/groovy
/src/test/resources
Написание кода unit-теста
Нет ограничений или предварительных требований к коду unit-тестирования; разработчики могут выбрать любой тестовый фреймворк, совместимый с инструментом сборки. Например, spring-test, junit, testng и spock.
При написании кода unit-тестов разработчики должны:
- Выбрать и настроить тестовый фреймворк.
- Обеспечить включение всех необходимых зависимостей, таких как внешние библиотеки (external jars).
- Мокировать все классы CMS Engine, используемые классами, которые тестируются.