{"id":391548,"date":"2024-06-29T09:53:02","date_gmt":"2024-06-29T09:53:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=391548"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=391548","title":{"rendered":"<span>\u041c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u043a\u0440\u0430\u0441\u0442\u0438\u043d\u0430\u0446\u0438\u044f, \u0438\u043b\u0438 \u043a\u0430\u043a \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0427\u0430\u0441\u0442\u044c 2<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0430 \u0441\u0432\u044f\u0437\u0438 <a href=\"https:\/\/habr.com\/ru\/users\/Lavenge\/\">\u0421\u0435\u0440\u0433\u0435\u0439 \u041a\u043e\u043d\u0434\u0438\u0442\u0435\u0440\u043e\u0432<\/a> \u0438 <a href=\"https:\/\/habr.com\/ru\/users\/Serj96\/\">\u0421\u0435\u0440\u0433\u0435\u0439 \u0411\u0443\u0448\u043c\u0435\u043b\u0435\u0432<\/a>, \u0432\u0435\u0434\u0443\u0449\u0438\u0435 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b \u043f\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0420\u0422\u041b\u0430\u0431\u0441. \u042d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u00ab<a href=\"https:\/\/habr.com\/ru\/company\/rtlabs\/blog\/708052\/\">\u041c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u043a\u0440\u0430\u0441\u0442\u0438\u043d\u0430\u0446\u0438\u044f, \u0438\u043b\u0438 \u043a\u0430\u043a \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/a>\u00bb.\u00a0\u041a\u0430\u043a \u0438 \u043e\u0431\u0435\u0449\u0430\u043b\u0438, \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043a\u0430\u043a \u0432 \u0438\u0442\u043e\u0433\u0435 \u0432\u044b\u0448\u043b\u0438 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0440\u0442-\u0431\u043e\u0442\u0430.\u00a0<\/p>\n<p>\u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043d\u0430\u043c\u0438 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0431\u043e\u0442.\u00a0\u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u00a0\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u043e\u0442\u0447\u0451\u0442\u044b, \u043d\u043e \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u0438\u0448\u043b\u0430 \u043c\u044b\u0441\u043b\u044c, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0443. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c\u00a0\u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u00a0\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430\u043c\u0438. \u0412 \u0441\u0432\u044f\u0437\u0438\u00a0\u0441 \u044d\u0442\u0438\u043c \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043d\u0430\u0448 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0441\u0432\u043e\u0438\u0445 \u0443\u0437\u043a\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a95\/bd2\/24e\/a95bd224eddfe4caffca11f7bd6bfb26.png\" width=\"3120\" height=\"1760\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a95\/bd2\/24e\/a95bd224eddfe4caffca11f7bd6bfb26.png\"\/><\/figure>\n<ol>\n<li>\n<p><a href=\"#1\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#2\">\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/a>:<\/p>\n<p>2.1. <a href=\"#2_1\">\u041a\u043b\u0438\u0435\u043d\u0442\u044b<\/a><br \/>2.2. <a href=\"#2_2\">Async-server<\/a><br \/>2.3. <a href=\"#2_3\">User-manager<\/a><br \/>2.4. <a href=\"#2_4\">Jenkins-adapter<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#3\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#4\">\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#5\">\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438<\/a>:<\/p>\n<p>5.1. <a href=\"#5_1\">\u041e\u0442\u043f\u0443\u0441\u043a\u0430<\/a><br \/>5.2. <a href=\"#5_2\">\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Jira<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#6\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"1\" id=\"1\"><\/a><\/p>\n<h2>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 Java 17 + Spring Boot, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f\u00a0PostgreSQL. \u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Apache Kafka \u0438\u00a0REST API.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/409\/c2f\/a20\/409c2fa2059db3f5b0ceffbc0648c6a9.png\" alt=\"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\" title=\"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\" width=\"2998\" height=\"1954\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/409\/c2f\/a20\/409c2fa2059db3f5b0ceffbc0648c6a9.png\"\/><\/p>\n<div><figcaption>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u042f\u0434\u0440\u043e\u043c \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <strong>Async-server<\/strong>. \u041e\u043d \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434, \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0445 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c.\u00a0<\/p>\n<p><strong>User-manager<\/strong> \u0445\u0440\u0430\u043d\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0438 \u043e \u0442\u043e\u043c, \u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u043a\u0430\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f.\u00a0<\/p>\n<p>\u0410\u0434\u0430\u043f\u0442\u0435\u0440\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u043c \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438, \u043a\u0430\u043a Jenkins \u0438 Jira (<strong>Jenkins-adapter<\/strong>\u00a0\u0438\u00a0<strong>Jira-adapter)<\/strong>.\u00a0<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u043e\u0442\u0443, \u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u0437\u0430\u0442\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <strong>Async-server<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0432\u00a0<strong>User-manager<\/strong>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438\u043c\u0435\u0435\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u0440\u043e\u043b\u044c, \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e\u0439\u00a0\u00a0\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u043c \u043d\u0430\u0441 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u043c \u0438\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043b\u0438\u0448\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u00a0\u2014\u00a0\u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u043e\u0432\u044b\u043c \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u043c, \u0438\u043b\u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u00a0\u2014\u00a0\u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u043c \u043d\u0430\u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441 Jira.<\/p>\n<p><a class=\"anchor\" name=\"2\" id=\"2\"><\/a><\/p>\n<h2>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/h2>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p><a class=\"anchor\" name=\"2_1\" id=\"2_1\"><\/a><\/p>\n<h3>\u041a\u043b\u0438\u0435\u043d\u0442\u044b<\/h3>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0437\u0432\u0435\u043d\u043e\u043c \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u044b. \u042d\u0442\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0446\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u043c. \u041e\u043d\u0438 \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u0434\u0430\u0447:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438\u0451\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/p>\n<\/li>\n<li>\n<p>\u0441\u0431\u043e\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u0438\u0445 \u0432\u00a0<strong>Async-server<\/strong>.\u00a0\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"java\">@Getter @Setter public class UserMessage {     \/\/\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String text;     \/\/\u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435     private boolean callback;     \/\/id \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f     private String messageId     \/\/id \u0447\u0430\u0442\u0430      private String chatId;     \/\/\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435       private User originalUser;     \/\/\u0438\u0437 \u043a\u0430\u043a\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0431\u044b\u043b\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435     private Client client;     \/\/\u0431\u044b\u043b\u043e \u043b\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0433\u043e \u0447\u0430\u0442\u0430     private boolean isGroupChat;     \/\/\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0447\u0430\u0442\u0430      private String channelName; }  public enum Client {     TELEGRAM; }  @Getter @Setter public class User {     \/\/id \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0435     private String id;     \/\/\u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String firstName;     \/\/\u0444\u0430\u043c\u0438\u043b\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String lastName;     \/\/\u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String userName; }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0<strong>Async-server\u00a0<\/strong>\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043a\u043b\u0438\u0435\u043d\u0442 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"java\">@Getter @Setter public class Payload {      \/*     \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u043e \u0438\u0442\u043e\u0433\u0443     POST - \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f     EDIT - \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e     DELETE - \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435     \u0434\u043b\u044f edit \u0438 delete \u043d\u0430\u0434\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c originalId     *\/     private SendMethod sendMethod;     private String originalId;     \/\/id \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0438\u0441\u043b\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435     private String replyTo;     \/\/id \u0447\u0430\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435     private String chatId;     \/\/\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e     private String text;     \/\/\u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0430     private String keyboard;        \/*     \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0438\u043f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e     SIMPLE - \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442     DOCUMENT - \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430     *\/     private MediaType mediaType;     \/\/\u0438\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430     private String fileName;     \/\/\u0444\u0430\u0439\u043b         private byte[] data;     \/\/\u0432 \u043a\u0430\u043a\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443      private Client client; }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"2_2\" id=\"2_2\"><\/a><\/p>\n<h3>Async-server<\/h3>\n<p>\u041f\u0435\u0440\u0432\u043e\u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0439 \u0438 \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0445 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u043e\u043c\u0430\u043d\u0434. \u0422\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c switch-case \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a\u0443\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043b\u043e\u0445\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c. \u0412\u0441\u0435 \u043a\u043e\u0433\u0434\u0430-\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438 \u043a\u043e\u0434, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u043b\u043e\u043a case \u0440\u0430\u0441\u0441\u0442\u0438\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0438, \u0430 \u0442\u043e \u0438 \u0441\u043e\u0442\u043d\u0438 \u0441\u0442\u0440\u043e\u043a! \u042d\u0442\u043e \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043d\u0435\u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u0430\u0441.<\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u0435\u0439\u0441\u0435 \u043d\u0430\u043c \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b Spring Framework. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u043a\u043b\u0430\u0441\u0441\u044b-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u044b \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <code>@Component<\/code>. \u0421 \u0435\u0451 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u0434\u0430\u0451\u043c \u043f\u043e\u043d\u044f\u0442\u044c spring, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>bean<\/code> \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<pre><code class=\"java\">public abstract class AbstractBaseHandler {      protected List&lt;Payload> handle(UserMessage usermassage) ;   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430\u043c\u0438 <code>AbstractBaseHandler<\/code>, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:\u00a0<\/p>\n<pre><code class=\"java\">@Service public class HandlerProvider {  private List&lt;AbstractBaseHandler> handlers;  @Autowired public void setHandlers(List&lt;AbstractBaseHandler> handlers) {     this.handlers = handlers;  } }<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c\u00a0\u0434\u0435\u043b\u043e\u043c\u00a0spring\u00a0\u0431\u0443\u0434\u0435\u0442\u00a0\u0438\u0441\u043a\u0430\u0442\u044c\u00a0\u0432\u00a0\u0441\u0432\u043e\u0451\u043c\u00a0\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435\u00a0<code>bean\u00a0List&lt;AbstractBaseHandler><\/code>.\u00a0\u041d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432 \u0435\u0433\u043e, \u043e\u043d \u043d\u0430\u0439\u0434\u0451\u0442 \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432\u00a0<code>AbstractBaseHandler<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f <code>bean<\/code>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u00ab\u0437\u0430\u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u00bb \u0432 \u043d\u0430\u0448\u00a0<code>List<\/code>.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u043e\u0442\u0430 \u0437\u0430 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b \u043d\u0430\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438\u00a0\u2014\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 reflection api. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@Command<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043a\u043e\u043c\u0430\u043d\u0434. \u0418\u0445 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<pre><code class=\"java\">@Retention(RUNTIME) @Target(TYPE) public @interface Command {     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c      *      * @return \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c      *\/     String[] command(); }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430, \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<pre><code class=\"java\">@Service public class HandlerProvider {   private List&lt;AbstractBaseHandler> handlers;  @Autowired public void setHandlers(List&lt;AbstractBaseHandler> handlers) {      this.handlers = handlers;  }    public void process(UserMessage usermassage) {   AbstractBaseHandler =  getHandler(usermassage.getText()).handle(usermassage);   \u0414\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u2026  }    private AbstractBaseHandler getHandler(String text) {      return handlers.stream()              .filter(handler -> handler.getClass()                      .isAnnotationPresent(BotCommand.class))              .filter(handler -> Stream.of(handler.getClass()                              .getAnnotation(BotCommand.class)                              .command())                   .anyMatch(c -> text.toLowerCase().startsWith(c))))              .findAny()              .orElseThrow(UnsupportedOperationException::new);  } }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438: \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0431\u043e\u0442\u0443 \u0434\u043b\u044f \u043d\u0435\u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@BotRole<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u0442\u0438 \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u043e\u043b\u044c\u044e \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u043c\u043e\u0434\u0443\u043b\u044e:<\/p>\n<pre><code class=\"java\">@Retention(RUNTIME) @Target(METHOD) public @interface BotRole {       \/**  * @return \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u043e\u043b\u044c, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b  *\/ Role role();  \/**  * @return \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f  *\/ Module module();        }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u0437 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0443\u0437\u043d\u0430\u0451\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u0440\u043e\u043b\u044c \u043a \u043c\u043e\u0434\u0443\u043b\u044e, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u00a0<strong>User-manager<\/strong>\u00a0\u00a0\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u043e\u043b\u044c\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u0435.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c:\u00a0<\/p>\n<ul>\n<li>\n<p>\u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u0443\u044e \u0438 \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0445 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u043e\u043c\u0430\u043d\u0434<\/p>\n<\/li>\n<li>\n<p>\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e\u00a0<strong>user-manager<\/strong>\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u043d\u044e \u0441 \u043d\u0430\u0431\u043e\u0440\u0430\u043c\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0432\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430\u00a0\u2014 <code>AutoTestsMenuHandler<\/code> \u0438 <code>StartBuildHanlder<\/code><strong>, <\/strong>\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e:<\/p>\n<pre><code class=\"java\">@Component @Command(commandName = \"\/tests\", message = \"\u041c\u0435\u043d\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\") public class AutoTestsMenuHandler extends AbstractBaseHandler {      @BotRole(role = Role.USER, module = Module.JENKINS)     protected List&lt;Payload> handle(UserMessage usermassage) {         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043b\u043e\u0433\u0438\u043a\u0438     } }<\/code><\/pre>\n<pre><code class=\"java\">@Component @Command(commandName = \"\/start_build\", message = \"\u0417\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\") public class StartBuildHandler extends AbstractBaseHandler {       @BotRole(role = Role.USER, module = Module.JENKINS)      protected List&lt;Payload> handle(UserMessage usermassage) {         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043b\u043e\u0433\u0438\u043a\u0438     } }<\/code><\/pre>\n<p>\u0412\u0441\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043c\u0435\u043d\u044e, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0411\u0414. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e\u00a0PostgreSQL.<\/p>\n<pre><code class=\"java\">CREATE TABLE public.at_menu (  id int8 NOT NULL,  command varchar(255) NULL,  name varchar(255) NULL,  parent int8 NULL,  CONSTRAINT menu_pkey PRIMARY KEY (id),  CONSTRAINT menu_parent FOREIGN KEY (parent) REFERENCES public.at_menu (id) );<\/code><\/pre>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b:<\/p>\n<ul>\n<li>\n<p><code>command<\/code> \u2014 \u043a\u043e\u043c\u0430\u043d\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>name<\/code> \u2014 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code>parent<\/code> \u2014 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 parent \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0432\u044b\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443. \u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043d\u043e\u043f\u043e\u043a, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u044b \u0438 \u043f\u043e\u0434\u0440\u0430\u0437\u0434\u0435\u043b\u044b.<\/p>\n<p><a class=\"anchor\" name=\"2_3\" id=\"2_3\"><\/a><\/p>\n<h3>User-manager<\/h3>\n<p>\u041f\u0435\u0440\u0432\u043e\u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0431\u044b\u043b\u043e \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u043d\u0435\u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0435 \u0438\u043c\u0435\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443.\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0438\u043b\u0438 \u043e\u043d \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438, \u043e\u043d\u0438 \u043e\u0431\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0432 <strong>User-manager<\/strong> \u0437\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439:\u00a0<\/p>\n<ul>\n<li>\n<p>\u0440\u043e\u043b\u0438 \u0432 \u043c\u043e\u0434\u0443\u043b\u044f\u0445<\/p>\n<\/li>\n<li>\n<p>\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>ID \u0432 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430\u0445<\/p>\n<\/li>\n<li>\n<p>\u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c \u0432\u00a0\u00a0\u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430\u0445<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u043a\u0430 Module + Role. Module\u00a0\u2014\u00a0\u044d\u0442\u043e \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439\u00a0\u00a0\u043d\u0430\u0431\u043e\u0440 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0431\u043e\u0442\u0430. Role\u00a0\u2014\u00a0\u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u043d\u0438\u0436\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u0440\u043e\u043b\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 Module:<\/p>\n<ul>\n<li>\n<p><code>READER<\/code><\/p>\n<\/li>\n<li>\n<p><code>USER<\/code><\/p>\n<\/li>\n<li>\n<p><code>ADMIN<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432\u043e \u0432\u0441\u0435\u0445 \u043c\u043e\u0434\u0443\u043b\u044f\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<p><a class=\"anchor\" name=\"2_4\" id=\"2_4\"><\/a><\/p>\n<h3>Jenkins-adapter<\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u044b\u043b \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044e \u0441 Jenkins. \u041e\u043d \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u0434\u0436\u043e\u0431 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 API-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 Jenkins, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0436\u043e\u0431 \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u043e\u0442\u0447\u0451\u0442 \u043e\u0431 \u0438\u0442\u043e\u0433\u0430\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.\u00a0<\/p>\n<p>\u0412 \u0440\u0430\u043d\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u0431\u043e\u0442\u0430 \u0432\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0431\u0438\u043b\u0434\u043e\u0432 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u043b\u0430\u0441\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 API-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u043b\u043e Jenkins. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u043e\u0442\u0430\u00a0<strong>Jenkins-adapter\u00a0<\/strong>\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u043e\u0432\u044b\u0445 \u0431\u0438\u043b\u0434\u0430\u0445 \u0438\u0437 rss feed. \u042d\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u043d\u0438\u0437\u0438\u043b\u043e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 Jenkins.<\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0443\u0436\u0435 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u043f\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044e \u043e\u0442\u0447\u0451\u0442\u0430 \u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0445 \u0438\u0437 \u0431\u043e\u0442\u0430, \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043e\u0431\u0440\u043e\u0441\u043b\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0444\u0438\u0447\u0430\u043c\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043a\u0430\u0436\u0434\u0443\u044e \u0438\u0437 \u043d\u0438\u0445.<\/p>\n<h4>\u0422\u044d\u0433\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043b\u0438\u0446<\/h4>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/886\/b8c\/133\/886b8c133348e384fa5de3e3a990f57e.PNG\" alt=\"\u0422\u044d\u0433\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439\" title=\"\u0422\u044d\u0433\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439\" width=\"1438\" height=\"2889\"\/><\/p>\n<div><figcaption>\u0422\u044d\u0433\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u0440\u0430\u043d\u043d\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u043e\u0442\u0430 \u0431\u044b\u043b \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u043a: \u043f\u0440\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u044b\u0435 \u0447\u0430\u0442\u044b \u043e\u0442\u0447\u0451\u0442\u044b \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0441\u0440\u0435\u0434\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u041e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u0430 \u0442\u043e\u0442 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0442\u0435\u0441\u0442\u043e\u0432 \u043b\u0438\u0446\u0430 \u043c\u043e\u0433\u043b\u0438 \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0431\u044b\u043b\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u044b. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u043e\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a \u043e\u0442\u0447\u0451\u0442\u0443 \u0442\u044d\u0433\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h4>\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/h4>\n<p>\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043d\u0435\u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0434\u0436\u043e\u0431 \u0441 \u0443\u043f\u0430\u0432\u0448\u0438\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u043e \u0434\u043b\u044f UI-\u0442\u0435\u0441\u0442\u043e\u0432, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0435\u0432\u044b\u0441\u043e\u043a (\u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0438\u0445 \u043d\u0438\u0437\u043a\u043e\u0439 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438), \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441 API-\u0442\u0435\u0441\u0442\u0430\u043c\u0438. \u041d\u0430\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u044d\u0442\u0438\u0445 \u0440\u0443\u0442\u0438\u043d\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043a\u043d\u043e\u043f\u043a\u0438 \u0438\u0437 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0430 \u043d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u0430\u044f, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0430 \u0441 \u0434\u0432\u0443\u043c\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438: \u00ab\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0443\u043f\u0430\u0432\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432\u00bb \u0438 \u00ab\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0431\u043e\u0440\u043a\u0438\u00bb.<\/p>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/765\/80b\/548\/76580b548e54c5fb7b57b385b066d2dc.PNG\" alt=\"\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\" title=\"\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\" width=\"1438\" height=\"2889\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 \u0434\u0436\u043e\u0431 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 callback \u043a\u043d\u043e\u043f\u043a\u0435 (\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0435\u0451 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c\u00a0\u0432 \u0433\u043b\u0430\u0432\u0435\u00a0<a href=\"#4\"><em>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/em><\/a>). \u0422elegram \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0432 callback. \u041c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0434\u0430\u043d\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0441\u043e\u0437\u0434\u0430\u0432 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u044d\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0430 \u0432 callback \u00ab\u0437\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u00bb \u043b\u0438\u0448\u044c id \u044d\u0442\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<h4>\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/h4>\n<p>\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u0438\u0437 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0444\u0438\u0447\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438,\u00a0\u2014\u00a0\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043f\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/372\/0b0\/b47\/3720b0b47abed599d7870cb97b03c63d.png\" alt=\"\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\" title=\"\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\" width=\"1438\" height=\"2889\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/372\/0b0\/b47\/3720b0b47abed599d7870cb97b03c63d.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\u00a0<strong>Jenkins-adapter<\/strong>\u00a0\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0411\u0414. \u041f\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u00a0<strong>Async-server<\/strong>.\u00a0<strong>Async-server<\/strong>\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u0430 \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0432\u0448\u0435\u043c\u0443\u0441\u044f \u043d\u0430 \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438.<\/p>\n<p><a class=\"anchor\" name=\"3\" id=\"3\"><\/a><\/p>\n<h2>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/h2>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0431\u043e\u0442\u043e\u043c \u043c\u043e\u0433\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438, \u0431\u044b\u043b\u043e \u0432\u0430\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u043b \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0441\u0431\u043e\u0440 \u0432\u0441\u0435\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438\u00a0\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u0438\u0430\u043b\u043e\u0433\u0430 \u0441 \u0431\u043e\u0442\u043e\u043c. \u041a\u0430\u0436\u0434\u044b\u0439 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u0440\u043e\u0441\u0438\u0442 \u0441\u0432\u043e\u0435\u0433\u043e \u043a\u043e\u043b\u043b\u0435\u0433\u0443, \u0443\u0436\u0435 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f, \u0434\u0430\u0442\u044c \u0435\u043c\u0443 \u0440\u0435\u0444\u0435\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434. \u041e\u043d \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0434\u0438\u0430\u043b\u043e\u0433\u0430 \u0441 \u0431\u043e\u0442\u043e\u043c.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5c2\/9b6\/930\/5c29b69303256b0162b28dcae8325865.png\" alt=\"\u0414\u0438\u0430\u043b\u043e\u0433 \u0441 \u0431\u043e\u0442\u043e\u043c\" title=\"\u0414\u0438\u0430\u043b\u043e\u0433 \u0441 \u0431\u043e\u0442\u043e\u043c\" width=\"3544\" height=\"3228\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5c2\/9b6\/930\/5c29b69303256b0162b28dcae8325865.png\"\/><\/p>\n<div><figcaption>\u0414\u0438\u0430\u043b\u043e\u0433 \u0441 \u0431\u043e\u0442\u043e\u043c<\/figcaption><\/div>\n<\/figure>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cb7\/aad\/c2e\/cb7aadc2e22a6eaf0df251daeedc6ffc.png\" alt=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e\" title=\"\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e\" width=\"1438\" height=\"2889\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cb7\/aad\/c2e\/cb7aadc2e22a6eaf0df251daeedc6ffc.png\"\/><\/p>\n<div><figcaption>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e<\/figcaption><\/div>\n<\/figure>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430\u043c \u0431\u043e\u0442\u0430 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u0430.<\/p>\n<p>\u042d\u0442\u043e \u0432 \u0440\u0430\u0437\u044b \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043b\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043e\u043f\u0440\u043e\u0441 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0435\u043d\u0442\u0430 \u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f.<\/p>\n<p><a class=\"anchor\" name=\"4\" id=\"4\"><\/a><\/p>\n<h2>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/h2>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443\u00a0<code>at_menu<\/code>:<\/p>\n<pre><code class=\"java\">INSERT INTO public.at_menu (id,command,name,parent) VALUES                     (1,'\/tests 1','UI \u0442\u0435\u0441\u0442\u044b',NULL),                     (2,'\/tests 2','API \u0442\u0435\u0441\u0442\u044b',NULL),                     (3,'\/tests 3','\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b',NULL),                     (4,'\/start_build 4','\u041f\u043e\u0440\u0442\u0430\u043b',1),                     (5,'\/start_build 5', '\u041f\u043e\u0440\u0442\u0430\u043b',2),                     (6,'\/start_build 6','Android',3),                     (7,'\/start_build 6','IPhone',3);<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0441\u0435\u0431\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439: \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u0438\u0437 \u0431\u043e\u0442\u0430 \u0438 \u043f\u043e\u0441\u043b\u0435 \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442 \u043e\u0431 \u0438\u0442\u043e\u0433\u0430\u0445. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f.\u00a0<\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u0442\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u0443\u00a0<code>\/tests<\/code>. \u0414\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430\u00a0<code>handle<\/code><strong> <\/strong>\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u00a0<code>AutoTestsMenuHandler<\/code><strong>\u00a0<\/strong>\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 <strong>Async-serve<\/strong>r. \u041a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0<code>\/tests<\/code><strong>\u00a0<\/strong>\u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b\u044b \u043c\u0435\u043d\u044e, \u043d\u0435 \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.\u00a0\u00a0\u041a \u0411\u0414 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u0443\u0441\u043b\u043e\u0432\u0438\u0435\u043c\u00a0<code>parent = NULL<\/code><em>.\u00a0<\/em>\u0422\u0430\u043a\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u043c\u0435\u043d\u044e.\u00a0<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0411\u0414 \u043c\u044b \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0443 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438. \u041a\u0430\u0436\u0434\u0430\u044f \u043a\u043d\u043e\u043f\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0438\u043c\u044f<code>name<\/code><em>,\u00a0<\/em>\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0446\u0443\u00a0<code>name<\/code><em>,\u00a0<\/em>\u0438<code>callback<\/code><em> (\u043c\u0435\u0442\u0430-\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043a\u043d\u043e\u043f\u043a\u0430),\u00a0<\/em>\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0446\u0443<code>command<\/code><em>.\u00a0<\/em>\u041a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439:<\/p>\n<pre><code class=\"java\">@Getter @Setter public class Button {    \/\/\u0418\u043c\u044f \u043a\u043d\u043e\u043f\u043a\u0438     private String name;    \/\/Callback \u043a\u043d\u043e\u043f\u043a\u0438    privat String callback; }  @Getter @Setter public class Row {    \/\/\u0421\u043f\u0438\u0441\u043e\u043a \u043a\u043d\u043e\u043f\u043e\u043a \u0432 \u0440\u044f\u0434\u0443    private List&lt;Button> buttons; }  @Getter @Setter public class Keyboard {      \/\/\u0421\u043f\u0438\u0441\u043e\u043a \u0440\u044f\u0434\u043e\u0432 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438     private List&lt;Row> rows;    public String toString() {      try {        ObjectMapper objectMapper = new ObjectMapper();        return objectMapper.writeValueAsString(this);      } catch (JsonProcessingException e) {        \/\/\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430      }    } }<\/code><\/pre>\n<p>\u0421\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430<code>Payload<\/code> \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e:<\/p>\n<pre><code class=\"java\">\/\/\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0443 \u0434\u043b\u044f Telegram private InlineKeyboardMarkup setKeyboard(Payload payload) throws JsonProcessingException {     \/\/\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0443     ObjectMapper objectMapper = new ObjectMapper();     List&lt;List&lt;InlineKeyboardButton>> keyboard = new ArrayList&lt;>();     if (payload.getKeyboard() != null &amp;&amp; !payload.getKeyboard().isEmpty()) {         \/\/\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0443, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u0432 async-server         Keyboard additionalButtons = objectMapper.readValue(payload.getKeyboard(), Keyboard.class);         for (Row row : additionalButtons.getRows()) {             \/\/\u043d\u0430\u0434\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443             List&lt;InlineKeyboardButton> additionalRow = new ArrayList&lt;>();             for (Button button : row.getButtons()) {                 \/\/\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043d\u043e\u043f\u043a\u0443                 InlineKeyboardButton btn = new InlineKeyboardButton();                 btn.setText(button.getName());                 btn.setCallbackData(button.getCallback());                 \/\/\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0441\u0442\u0440\u043e\u043a\u0443                 additionalRow.add(btn);             }             \/\/\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0443             keyboard.add(additionalRow);         }     }          InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();     inlineKeyboardMarkup.setKeyboard(keyboard);     return inlineKeyboardMarkup; }   \/\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e private void sendMessage(Payload payload) throws TelegramApiException {     SendMessage sendMessage = new SendMessage();      sendMessage.setChatId(payload.getChatId());     try {        sendMessage.setReplyMarkup(setKeyboard(payload));     } catch (JsonProcessingException e) {         \/\/\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430     }     sendMessage.setParseMode(ParseMode.HTML);     sendMessage.setText(payload.getText());      \/\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e     execute(sendMessage);  }<\/code><\/pre>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u00abUI \u0442\u0435\u0441\u0442\u044b\u00bb<\/p>\n<\/li>\n<li>\n<p>\u00abAPI \u0442\u0435\u0441\u0442\u044b\u00bb<\/p>\n<\/li>\n<li>\n<p>\u00ab\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b\u00bb<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u043a \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0440\u0430\u043d\u0435\u0435, \u0432 \u043a\u0430\u0436\u0434\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u0437\u0430\u0448\u0438\u0442<code>callback<\/code>. \u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u0431\u043e\u0442\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432<code>callback<\/code>. \u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0438 \u00ab\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b\u00bb \u0431\u043e\u0442\u0443 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0<code>\/tests 3<\/code>. \u0426\u0438\u0444\u0440\u0430 \u0442\u0440\u0438\u00a0\u2014\u00a0\u044d\u0442\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f id \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435. \u041a \u0411\u0414 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u0443\u0441\u043b\u043e\u0432\u0438\u0435\u043c\u00a0<code>parent = 3<\/code><em>.\u00a0<\/em>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0430 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u00abAndroid\u00bb<\/p>\n<\/li>\n<li>\n<p>\u00abIPhone\u00bb<\/p>\n<\/li>\n<\/ul>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3a5\/213\/741\/3a52137417d3d4d70d8057903e73618b.png\" alt=\"\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u0441\u0442\u0430\u0440\u0442\u0435 \u0431\u0438\u043b\u0434\u0430\" title=\"\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u0441\u0442\u0430\u0440\u0442\u0435 \u0431\u0438\u043b\u0434\u0430\" width=\"1438\" height=\"2889\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3a5\/213\/741\/3a52137417d3d4d70d8057903e73618b.png\"\/><\/p>\n<div><figcaption>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u0441\u0442\u0430\u0440\u0442\u0435 \u0431\u0438\u043b\u0434\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0438 \u00abAndroid\u00bb \u0431\u043e\u0442\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0<code>\/start_build 6<\/code>. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u00a0\u2014\u00a0\u044d\u0442\u043e id \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0441\u0435\u0442\u0430<strong>\u00a0<\/strong>(\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438). \u0414\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u0430\u00a0 <code>handle<\/code><strong> <\/strong>\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 <code>StartBuildHandler<\/code>. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 REST API \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u00a0<strong>Jenkins-adapter<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0432\u00a0<strong>Jenkins<\/strong>. \u041f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u0437\u0430\u043f\u0443\u0441\u043a <code>build<\/code>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0435\u0433\u043e <code>build<\/code> \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c. <\/p>\n<figure class=\"float full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/24d\/555\/3f9\/24d5553f930c168f5d856f516695e430.png\" alt=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\" title=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\" width=\"1438\" height=\"2889\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/24d\/555\/3f9\/24d5553f930c168f5d856f516695e430.png\"\/><\/p>\n<div><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430\u00a0<strong>Jenkins-adapter\u00a0<\/strong>\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u043e\u0442\u0447\u0451\u0442 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u0440\u0438\u0434\u0451\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0441 \u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438.<\/p>\n<p><a class=\"anchor\" name=\"5\" id=\"5\"><\/a><\/p>\n<h2>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438<\/h2>\n<p>\u041e\u043f\u044b\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u0432 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u043d\u0430\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u0442\u0430\u043b \u043e\u0431\u0440\u0430\u0441\u0442\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c, \u0434\u0430\u043b\u0435\u043a\u043e \u0432\u044b\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p><a class=\"anchor\" name=\"5_1\" id=\"5_1\"><\/a><\/p>\n<h3>\u041e\u0442\u043f\u0443\u0441\u043a\u0430<\/h3>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u043c\u0438 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432. \u0412\u00a0<strong>User-manager\u00a0<\/strong>\u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0442\u044c \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435, \u0434\u0430\u0442\u044b \u0438 \u0432\u0438\u0434 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043f\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u0438 \u0441\u0432\u043e\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430\u0445. \u0418\u043c \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u0435\u0445 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430\u0445, \u043a\u043e\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043c\u0435\u0441\u0442\u0435 \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b00\/a06\/f9f\/b00a06f9f550c73868e790d8f92e8ad9.png\" alt=\"\u0421\u043f\u0438\u0441\u043a\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u043e\u0442\u043f\u0443\u0441\u043a\u043e\u0432\" title=\"\u0421\u043f\u0438\u0441\u043a\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u043e\u0442\u043f\u0443\u0441\u043a\u043e\u0432\" width=\"719\" height=\"1445\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b00\/a06\/f9f\/b00a06f9f550c73868e790d8f92e8ad9.png\"\/><\/p>\n<div><figcaption>\u0421\u043f\u0438\u0441\u043a\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u043e\u0442\u043f\u0443\u0441\u043a\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u0432\u043e\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439.<\/p>\n<p><a class=\"anchor\" name=\"5_2\" id=\"5_2\"><\/a><\/p>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Jira<\/h3>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c, \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u0441\u0442\u0430\u043b\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 Jira. \u0417\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0438 \u0437\u0430\u0431\u044b\u0432\u0430\u044e\u0442 \u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b \u043f\u0440\u0438\u0441\u044b\u043b\u0430\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0438\u043c \u0447\u0430\u0441\u043e\u0432 \u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0438.\u00a0<\/p>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441\u00a0<strong>Jenkins-adapter<\/strong>,<strong>\u00a0<\/strong>\u0432\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u00a0<strong>Jira\u00a0<\/strong>\u0431\u044b\u043b\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u00a0<strong>Jira-adapter<\/strong>. \u041f\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 REST API \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043a\u00a0<strong>Jira<\/strong>\u00a0\u0441 \u0446\u0435\u043b\u044c\u044e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0437\u0430\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0437\u0430 \u043f\u0440\u043e\u0448\u043b\u0443\u044e \u043d\u0435\u0434\u0435\u043b\u044e. \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u0447\u0451\u0442\u0430 \u0432 HTML-\u0444\u043e\u0440\u043c\u0430\u0442\u0435.\u00a0\u00a0<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/60a\/a79\/eb8\/60aa79eb8e4e2cc7a55efca9e8ed2f7a.png\" alt=\"\u041e\u0442\u0447\u0451\u0442 \u043f\u043e \u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0432\u0440\u0435\u043c\u0435\u043d\u0438\" title=\"\u041e\u0442\u0447\u0451\u0442 \u043f\u043e \u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0432\u0440\u0435\u043c\u0435\u043d\u0438\" width=\"2083\" height=\"884\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/60a\/a79\/eb8\/60aa79eb8e4e2cc7a55efca9e8ed2f7a.png\"\/><\/p>\n<div><figcaption>\u041e\u0442\u0447\u0451\u0442 \u043f\u043e \u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/figcaption><\/div>\n<\/figure>\n<p><a class=\"anchor\" name=\"6\" id=\"6\"><\/a><\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435, \u043f\u043e\u0441\u043b\u0435 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f, \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441\u043e \u0441\u0442\u0430\u0440\u043e\u0439, \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430:<\/p>\n<ul>\n<li>\n<p>\u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0432 \u043a\u0440\u0430\u0442\u0447\u0430\u0439\u0448\u0438\u0435 \u0441\u0440\u043e\u043a\u0438 \u043b\u044e\u0431\u044b\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438\u00a0\u2014\u00a0\u0432\u0441\u0451 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u043d\u0430\u0448\u0435\u0439 \u0444\u0430\u043d\u0442\u0430\u0437\u0438\u0435\u0439<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u0430\u043b \u043d\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u043e\u043f\u044b\u0442. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u043a\u0430\u0447\u0430\u043b\u0438 \u0441\u0432\u043e\u0438 \u043d\u0430\u0432\u044b\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 Spring Boot<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0447\u0430\u0442-\u0431\u043e\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/716694\/\"> https:\/\/habr.com\/ru\/articles\/716694\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0430 \u0441\u0432\u044f\u0437\u0438 <a href=\"https:\/\/habr.com\/ru\/users\/Lavenge\/\">\u0421\u0435\u0440\u0433\u0435\u0439 \u041a\u043e\u043d\u0434\u0438\u0442\u0435\u0440\u043e\u0432<\/a> \u0438 <a href=\"https:\/\/habr.com\/ru\/users\/Serj96\/\">\u0421\u0435\u0440\u0433\u0435\u0439 \u0411\u0443\u0448\u043c\u0435\u043b\u0435\u0432<\/a>, \u0432\u0435\u0434\u0443\u0449\u0438\u0435 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b \u043f\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0420\u0422\u041b\u0430\u0431\u0441. \u042d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u00ab<a href=\"https:\/\/habr.com\/ru\/company\/rtlabs\/blog\/708052\/\">\u041c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u043a\u0440\u0430\u0441\u0442\u0438\u043d\u0430\u0446\u0438\u044f, \u0438\u043b\u0438 \u043a\u0430\u043a \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/a>\u00bb.\u00a0\u041a\u0430\u043a \u0438 \u043e\u0431\u0435\u0449\u0430\u043b\u0438, \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043a\u0430\u043a \u0432 \u0438\u0442\u043e\u0433\u0435 \u0432\u044b\u0448\u043b\u0438 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0440\u0442-\u0431\u043e\u0442\u0430.\u00a0<\/p>\n<p>\u041d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043d\u0430\u043c\u0438 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0431\u043e\u0442.\u00a0\u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u00a0\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u043e\u0442\u0447\u0451\u0442\u044b, \u043d\u043e \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u0438\u0448\u043b\u0430 \u043c\u044b\u0441\u043b\u044c, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0443. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c\u00a0\u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u00a0\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430\u043c\u0438. \u0412 \u0441\u0432\u044f\u0437\u0438\u00a0\u0441 \u044d\u0442\u0438\u043c \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043d\u0430\u0448 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0441\u0432\u043e\u0438\u0445 \u0443\u0437\u043a\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<figure class=\"full-width\"><\/figure>\n<ol>\n<li>\n<p><a href=\"#1\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#2\">\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/a>:<\/p>\n<p>2.1. <a href=\"#2_1\">\u041a\u043b\u0438\u0435\u043d\u0442\u044b<\/a><br \/>2.2. <a href=\"#2_2\">Async-server<\/a><br \/>2.3. <a href=\"#2_3\">User-manager<\/a><br \/>2.4. <a href=\"#2_4\">Jenkins-adapter<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#3\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#4\">\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#5\">\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438<\/a>:<\/p>\n<p>5.1. <a href=\"#5_1\">\u041e\u0442\u043f\u0443\u0441\u043a\u0430<\/a><br \/>5.2. <a href=\"#5_2\">\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Jira<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#6\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a class=\"anchor\" name=\"1\" id=\"1\"><\/a><\/p>\n<h2>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 Java 17 + Spring Boot, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f\u00a0PostgreSQL. \u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Apache Kafka \u0438\u00a0REST API.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u042f\u0434\u0440\u043e\u043c \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <strong>Async-server<\/strong>. \u041e\u043d \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434, \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0445 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c.\u00a0<\/p>\n<p><strong>User-manager<\/strong> \u0445\u0440\u0430\u043d\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0438 \u043e \u0442\u043e\u043c, \u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u043a\u0430\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f.\u00a0<\/p>\n<p>\u0410\u0434\u0430\u043f\u0442\u0435\u0440\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u043c \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438, \u043a\u0430\u043a Jenkins \u0438 Jira (<strong>Jenkins-adapter<\/strong>\u00a0\u0438\u00a0<strong>Jira-adapter)<\/strong>.\u00a0<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u043e\u0442\u0443, \u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u0437\u0430\u0442\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <strong>Async-server<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0432\u00a0<strong>User-manager<\/strong>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438\u043c\u0435\u0435\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u0440\u043e\u043b\u044c, \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e\u0439\u00a0\u00a0\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u043c \u043d\u0430\u0441 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u043c \u0438\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043b\u0438\u0448\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u00a0\u2014\u00a0\u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u043e\u0432\u044b\u043c \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u043c, \u0438\u043b\u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u00a0\u2014\u00a0\u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u043c \u043d\u0430\u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441 Jira.<\/p>\n<p><a class=\"anchor\" name=\"2\" id=\"2\"><\/a><\/p>\n<h2>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/h2>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p><a class=\"anchor\" name=\"2_1\" id=\"2_1\"><\/a><\/p>\n<h3>\u041a\u043b\u0438\u0435\u043d\u0442\u044b<\/h3>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0437\u0432\u0435\u043d\u043e\u043c \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u044b. \u042d\u0442\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0446\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u043c. \u041e\u043d\u0438 \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u0434\u0430\u0447:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438\u0451\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/p>\n<\/li>\n<li>\n<p>\u0441\u0431\u043e\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u0438\u0445 \u0432\u00a0<strong>Async-server<\/strong>.\u00a0\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"java\">@Getter @Setter public class UserMessage {     \/\/\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String text;     \/\/\u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435     private boolean callback;     \/\/id \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f     private String messageId     \/\/id \u0447\u0430\u0442\u0430      private String chatId;     \/\/\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435       private User originalUser;     \/\/\u0438\u0437 \u043a\u0430\u043a\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0431\u044b\u043b\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435     private Client client;     \/\/\u0431\u044b\u043b\u043e \u043b\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0433\u043e \u0447\u0430\u0442\u0430     private boolean isGroupChat;     \/\/\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0447\u0430\u0442\u0430      private String channelName; }  public enum Client {     TELEGRAM; }  @Getter @Setter public class User {     \/\/id \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0435     private String id;     \/\/\u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String firstName;     \/\/\u0444\u0430\u043c\u0438\u043b\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String lastName;     \/\/\u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     private String userName; }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0<strong>Async-server\u00a0<\/strong>\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043a\u043b\u0438\u0435\u043d\u0442 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"java\">@Getter @Setter public class Payload {      \/*     \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u043e \u0438\u0442\u043e\u0433\u0443     POST - \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f     EDIT - \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e     DELETE - \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435     \u0434\u043b\u044f edit \u0438 delete \u043d\u0430\u0434\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c originalId     *\/     private SendMethod sendMethod;     private String originalId;     \/\/id \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0438\u0441\u043b\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435     private String replyTo;     \/\/id \u0447\u0430\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435     private String chatId;     \/\/\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e     private String text;     \/\/\u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u0430     private String keyboard;        \/*     \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0438\u043f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e     SIMPLE - \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442     DOCUMENT - \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430     *\/     private MediaType mediaType;     \/\/\u0438\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430     private String fileName;     \/\/\u0444\u0430\u0439\u043b         private byte[] data;     \/\/\u0432 \u043a\u0430\u043a\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443      private Client client; }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"2_2\" id=\"2_2\"><\/a><\/p>\n<h3>Async-server<\/h3>\n<p>\u041f\u0435\u0440\u0432\u043e\u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0439 \u0438 \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0445 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u043e\u043c\u0430\u043d\u0434. \u0422\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c switch-case \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a\u0443\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043b\u043e\u0445\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c. \u0412\u0441\u0435 \u043a\u043e\u0433\u0434\u0430-\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438 \u043a\u043e\u0434, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u043b\u043e\u043a case \u0440\u0430\u0441\u0441\u0442\u0438\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0438, \u0430 \u0442\u043e \u0438 \u0441\u043e\u0442\u043d\u0438 \u0441\u0442\u0440\u043e\u043a! \u042d\u0442\u043e \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043d\u0435\u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u0430\u0441.<\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u0435\u0439\u0441\u0435 \u043d\u0430\u043c \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b Spring Framework. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u043a\u043b\u0430\u0441\u0441\u044b-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u044b \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <code>@Component<\/code>. \u0421 \u0435\u0451 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u0434\u0430\u0451\u043c \u043f\u043e\u043d\u044f\u0442\u044c spring, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>bean<\/code> \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<pre><code class=\"java\">public abstract class AbstractBaseHandler {      protected List&lt;Payload> handle(UserMessage usermassage) ;   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430\u043c\u0438 <code>AbstractBaseHandler<\/code>, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:\u00a0<\/p>\n<pre><code class=\"java\">@Service public class HandlerProvider {  private List&lt;AbstractBaseHandler> handlers;  @Autowired public void setHandlers(List&lt;AbstractBaseHandler> handlers) {     this.handlers = handlers;  } }<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c\u00a0\u0434\u0435\u043b\u043e\u043c\u00a0spring\u00a0\u0431\u0443\u0434\u0435\u0442\u00a0\u0438\u0441\u043a\u0430\u0442\u044c\u00a0\u0432\u00a0\u0441\u0432\u043e\u0451\u043c\u00a0\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435\u00a0<code>bean\u00a0List&lt;AbstractBaseHandler><\/code>.\u00a0\u041d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432 \u0435\u0433\u043e, \u043e\u043d \u043d\u0430\u0439\u0434\u0451\u0442 \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432\u00a0<code>AbstractBaseHandler<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f <code>bean<\/code>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u00ab\u0437\u0430\u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u00bb \u0432 \u043d\u0430\u0448\u00a0<code>List<\/code>.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u043e\u0442\u0430 \u0437\u0430 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b \u043d\u0430\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438\u00a0\u2014\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 reflection api. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@Command<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043a\u043e\u043c\u0430\u043d\u0434. \u0418\u0445 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<pre><code class=\"java\">@Retention(RUNTIME) @Target(TYPE) public @interface Command {     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c      *      * @return \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c      *\/     String[] command(); }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430, \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<pre><code class=\"java\">@Service public class HandlerProvider {   private List&lt;AbstractBaseHandler> handlers;  @Autowired public void setHandlers(List&lt;AbstractBaseHandler> handlers) {      this.handlers = handlers;  }    public void process(UserMessage usermassage) {   AbstractBaseHandler =  getHandler(usermassage.getText()).handle(usermassage);   \u0414\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u2026  }    private AbstractBaseHandler getHandler(String text) {      return handlers.stream()              .filter(handler -> handler.getClass()                      .isAnnotationPresent(BotCommand.class))              .filter(handler -> Stream.of(handler.getClass()                              .getAnnotation(BotCommand.class)                              .command())                   .anyMatch(c -> text.toLowerCase().startsWith(c))))              .findAny()              .orElseThrow(UnsupportedOperationException::new);  } }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438: \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0431\u043e\u0442\u0443 \u0434\u043b\u044f \u043d\u0435\u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@BotRole<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u0442\u0438 \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u043e\u043b\u044c\u044e \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u043c\u043e\u0434\u0443\u043b\u044e:<\/p>\n<pre><code class=\"java\">@Retention(RUNTIME) @Target(METHOD) public @interface BotRole {       \/**  * @return \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u043e\u043b\u044c, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b  *\/ Role role();  \/**  * @return \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f  *\/ Module module();        }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u0437 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0443\u0437\u043d\u0430\u0451\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u0440\u043e\u043b\u044c \u043a \u043c\u043e\u0434\u0443\u043b\u044e, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u00a0<strong>User-manager<\/strong>\u00a0\u00a0\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u043e\u043b\u044c\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u0435.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c:\u00a0<\/p>\n<ul>\n<li>\n<p>\u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u0443\u044e \u0438 \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0445 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u043e\u043c\u0430\u043d\u0434<\/p>\n<\/li>\n<li>\n<p>\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0440\u043e\u043b\u0435\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e\u00a0<strong>user-manager<\/strong>\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u043d\u044e \u0441 \u043d\u0430\u0431\u043e\u0440\u0430\u043c\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0432\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430\u00a0\u2014 <code>AutoTestsMenuHandler<\/code> \u0438 <code>StartBuildHanlder<\/code><strong>, <\/strong>\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e:<\/p>\n<pre><code class=\"java\">@Component @Command(commandName = \"\/tests\", message = \"\u041c\u0435\u043d\u044e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\") public class AutoTestsMenuHandler extends AbstractBaseHandler {      @BotRole(role = Role.USER, module = Module.JENKINS)     protected List&lt;Payload> handle(UserMessage usermassage) {         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043b\u043e\u0433\u0438\u043a\u0438     } }<\/code><\/pre>\n<pre><code class=\"java\">@Component @Command(commandName = \"\/start_build\", message = \"\u0417\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432\") public class StartBuildHandler extends AbstractBaseHandler {       @BotRole(role = Role.USER, module = Module.JENKINS)      protected List&lt;Payload> handle(UserMessage usermassage) {         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043b\u043e\u0433\u0438\u043a\u0438     } }<\/code><\/pre>\n<p>\u0412\u0441\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043c\u0435\u043d\u044e, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0411\u0414. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e\u00a0PostgreSQL.<\/p>\n<pre><code class=\"java\">CREATE TABLE public.at_menu (  id int8 NOT NULL,  command varchar(255) NULL,  name varchar(255) NULL,  parent int8 NULL,  CONSTRAINT menu_pkey PRIMARY KEY (id),  CONSTRAINT menu_parent FOREIGN KEY (parent) REFERENCES public.at_menu (id) );<\/code><\/pre>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b:<\/p>\n<ul>\n<li>\n<p><code>command<\/code> \u2014 \u043a\u043e\u043c\u0430\u043d\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>name<\/code> \u2014 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code>parent<\/code> \u2014 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 parent \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c <\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-391548","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/391548","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=391548"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/391548\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=391548"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=391548"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=391548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}