Разработка на Groovy

В этой статье вы узнаете, как создавать и использовать Groovy-скрипты для различных задач в DC CMS.

DC CMS поддерживает серверную разработку с помощью Groovy. Использование Groovy позволяет создавать RESTful сервисы, контроллеры MVC, код, который выполняется перед отображением страницы или компонента,, сервлетные фильтры, запланированные задачи и полноценные бэкэнд приложения.

Groovy API Copy-icon

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]

Copy-icon

Скрипт не найден

Скрипты Rest будут возвращать страницу 404, если скрипт не найден. Разработчики по-прежнему смогут возвращать кастомные ответы 404 из скриптов REST. Например:

response.setStatus(404)
return 'This is the custom message'

Copy-icon

Они могут даже отправить страницу ответа по умолчанию, используя sendError:

response.sendError(404)

Copy-icon

Скрипты контроллера

Скрипты контроллера похожи на REST-скрипты. У них доступны те же переменные, но вместо возвращения объекта они возвращают строку с представлением для отображения. Чаще всего это просто путь к шаблону, как в следующем фрагменте кода:

return "/templates/web/registration.ftl"

Copy-icon

Функционируя подобно контроллеру в шаблоне 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"

Copy-icon

Одним из часто используемых скриптов контроллера является 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>

Copy-icon

Поисковые системы обычно находят карту сайта непосредственно после домена, так что 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

Copy-icon

Unit-тестирование кода на Groovy в DC CMS

Для крупных веб-сайтов, включающих сложные сервисы на основе Groovy, интеграция unit-тестов, совместимая с системами CI/CD, оказывается чрезвычайно полезной. В этом разделе предоставляется руководство по созданию unit-тестов для кода на Groovy в рамках DС CMS с использованием Gradle. Дополнительные сведения о типах переменных и классов, которые можно использовать для unit-тестирования, смотрите выше.

Создание unit-теста Groovy

Чтобы создать unit-тест:

  1. Определите папку для всех файлов, связанных с тестированием
  2. Напишите код unit-теста
  3. Настройте unit-тест для запуска с помощью Gradle
  4. Выполните unit-тест

Определение папки для файлов, связанных с тестированием

Укажите папку в репозитории сайта, в которой будут содержаться все файлы, связанные с тестированием. Например, CMS_HOME/data/repos/sites/SITENAME/sandbox.

/scripts
   /test
     /classes   (all packages & groovy classes for testing)
     /resources (all additional files required for testing)

Copy-icon

Эта структура является эквивалентом стандартных папок, используемых для проектов Java/Groovy:

/src/test/groovy
/src/test/resources

Copy-icon

Написание кода unit-теста

Нет ограничений или предварительных требований к коду unit-тестирования; разработчики могут выбрать любой тестовый фреймворк, совместимый с инструментом сборки. Например, spring-testjunittestng и spock.

При написании кода unit-тестов разработчики должны:

  • Выбрать и настроить тестовый фреймворк.
  • Обеспечить включение всех необходимых зависимостей, таких как внешние библиотеки (external jars).
  • Мокировать все классы CMS Engine, используемые классами, которые тестируются.

Связанные статьи

API