middle
Как создать Servlet Module в плагине?
Servlet Module позволяет создавать веб-страницы внутри Jira с собственным UI, используется для административных панелей, конфигурационных страниц плагина, отчётов.
Объявление и реализация
Пример
<servlet key="config-servlet" class="com.example.plugin.servlet.ConfigServlet">
<url-pattern>/my-plugin/config</url-pattern>
</servlet>
Код ConfigServlet
@Named
public class ConfigServlet extends HttpServlet {
private final TemplateRenderer templateRenderer;
private final JiraAuthenticationContext authContext;
private final PermissionManager permissionManager;
private final TaskConfigService configService;
@Inject
public ConfigServlet(@ComponentImport TemplateRenderer templateRenderer,
@ComponentImport JiraAuthenticationContext authContext,
@ComponentImport PermissionManager permissionManager,
TaskConfigService configService) {
this.templateRenderer = templateRenderer;
this.authContext = authContext;
this.permissionManager = permissionManager;
this.configService = configService;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
ApplicationUser user = authContext.getLoggedInUser();
if (user == null) {
resp.sendRedirect("/login.jsp");
return;
}
if (!permissionManager.hasPermission(GlobalPermissionKey.ADMINISTER, user)) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Admin access required");
return;
}
Map<String, Object> context = new HashMap<>();
context.put("configs", configService.findAll());
context.put("currentUser", user.getDisplayName());
resp.setContentType("text/html;charset=UTF-8");
templateRenderer.render("templates/config-page.vm", context, resp.getWriter());
}
}
Velocity-шаблон
templates/config-page.vm
<html>
<head>
<title>Конфигурация плагина</title>
<meta name="decorator" content="atl.admin"/>
$webResourceManager.requireResource("com.example.my-plugin:my-resources")
</head>
<body>
<h2>Настройки плагина</h2>
<form method="post" class="aui">
<div class="field-group">
<label for="projectKey">Проект:</label>
<input type="text" id="projectKey" name="projectKey" class="text"/>
</div>
<div class="buttons-container">
<input type="submit" value="Сохранить" class="aui-button aui-button-primary"/>
</div>
</form>
<h3>Существующие конфигурации</h3>
<table class="aui">
<thead>
<tr><th>ID</th><th>Проект</th><th>Статус</th></tr>
</thead>
<tbody>
#foreach($config in $configs)
<tr>
<td>$config.getID()</td>
<td>$config.getProjectKey()</td>
<td>#if($config.isEnabled()) Активна #else Отключена #end</td>
</tr>
#end
</tbody>
</table>
</body>
</html>
URL доступа: https://jira.company.com/plugins/servlet/my-plugin/config
Частые ошибки
- Забыть декоратор
atl.admin— страница отображается без навигации Jira - XSS-уязвимости — не экранировать пользовательский ввод. Используйте
$!{htmlUtil.htmlEncode($value)} - Не проверять права доступа — сервлет доступен любому аутентифицированному пользователю
- Использование ComponentAccessor вместо DI — антипаттерн, затрудняет тестирование
Как используется в 2026
- Servlet Module остаётся актуальным для административных страниц плагинов
- Тренд: минимум серверного рендеринга, максимум SPA (React/Vue) + REST API плагина
- AUI (Atlassian UI) — по-прежнему рекомендованная UI-библиотека для DC
На собеседовании: покажите знание Velocity-шаблонов и декораторов (
atl.admin). Обязательно упомяните$webResourceManager.requireResource(...)для подключения CSS/JS. Главная ошибка — не проверять права и не экранировать вывод.