{"id":292918,"date":"2019-08-02T15:00:28","date_gmt":"2019-08-02T15:00:28","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=292918"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=292918","title":{"rendered":"Spring Boot: \u0420\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f\u043c\u0438"},"content":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sl\/bo\/qo\/slboqopgn4vzsownqn48d4be7x8.jpeg\"><\/p>\n<p>  \u041a\u0443, \u0425\u0430\u0431\u0440! <\/p>\n<p>  \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u043e\u0432\u0435\u043d\u0438\u044f: \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u0430\u043f\u0438\u0441\u0430\u0432 if \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438 \u0438\u043b\u0438 switch \u0441 \u043f\u043e\u043b\u043e\u0442\u043d\u043e\u043c \u043a\u0435\u0439\u0441\u043e\u0432, \u0447\u0443\u0432\u0441\u0442\u0432\u0443\u044e, \u0447\u0442\u043e \u0433\u0434\u0435-\u0442\u043e \u043f\u043b\u0430\u0447\u0443\u0442 \u043a\u043e\u0442\u0438\u043a\u0438. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0439, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u0442\u0438\u043a\u043e\u0432. \u0420\u0443\u043a\u0430 \u0442\u044f\u043d\u0435\u0442\u0441\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c <s>\u0438 \u043d\u0430\u043a\u043e\u0440\u043c\u0438\u0442\u044c \u043a\u043e\u0442\u0438\u043a\u043e\u0432<\/s>.<\/p>\n<p>  \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u0438\u043d\u0434\u0443\u043b\u044c\u0433\u0435\u043d\u0446\u0438\u044f. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043a\u0435\u0439\u0441\u043e\u0432 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A0%D0%B5%D1%84%D0%BB%D0%B5%D0%BA%D1%81%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)\">\u0440\u0435\u0444\u043b\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/a>.<\/p>\n<p>  \u0420\u0430\u0431\u043e\u0442\u0430\u044e \u044f \u0432 <a href=\"https:\/\/beeline.kg\/\">Beeline \u041a\u044b\u0440\u0433\u044b\u0437\u0441\u0442\u0430\u043d<\/a>, \u0438 \u0443 \u0442\u0435\u043b\u0435\u043a\u043e\u043c\u0430 \u0447\u0430\u0441\u0442\u043e \u043d\u0430 \u043f\u043e\u0432\u0435\u0441\u0442\u043a\u0435 \u0434\u043d\u044f \u043a\u0435\u0439\u0441\u044b \u0441 \u0443\u0441\u043b\u043e\u0432\u0438\u0435\u043c \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0417\u0430\u0434\u0430\u0447\u0430 \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c application, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0435\u0433\u043e \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0432 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u2014 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0442\u0430\u043a \u0441\u0435\u0431\u0435, \u043a\u0430\u043a \u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u043c\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u0418 \u043e\u0431\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043b\u0438\u0448\u044c \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/302570\/\">\u0441\u043a\u043b\u043e\u043d\u043d\u043e\u043c\u0443 \u043a \u043d\u0430\u0441\u0438\u043b\u0438\u044e \u043f\u0441\u0438\u0445\u043e\u043f\u0430\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u043d\u0430\u0435\u0442, \u0433\u0434\u0435 \u044f \u0436\u0438\u0432\u0443<\/a>, \u0435\u0441\u043b\u0438 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 100 \u0438\u043b\u0438 1000 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440. <br \/>  \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u0438\u0432\u044b\u043a\u043b\u0438 \u0441\u0440\u0430\u0437\u0443 \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u0434, \u0442\u043e \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 <a href=\"https:\/\/github.com\/xeofus\/reflectiveapp\">\u0442\u0443\u0442<\/a>.<br \/>  <a name=\"habracut\"><\/a><br \/>  \u0418\u0434\u0435\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f: \u0434\u0432\u0438\u0433\u0430\u0435\u043c\u0441\u044f \u043f\u043e \u043f\u0443\u0442\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 Mediator (\u0438\u043b\u0438 Intermediary, \u00adController), \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0438 <abbr title=\"\u0438\u043d\u0432\u043e\u043a\u0430\u0442\u044c \u043a\u043e\u0440\u043e\u0447\u0435, \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u0432\u0443\u0447\u0438\u0442\">\u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c<\/abbr> \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0441 \u043b\u043e\u0433\u0438\u043a\u043e\u0439.<\/p>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 <u>\/command\/observeAllUserActions<\/u>. \u041f\u043e \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b <u>observeAllUserActions<\/u>, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u0443\u0448\u0430\u0435\u0442 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043b\u043e\u0433\u043e\u0432, \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u044e\u0437\u0435\u0440\u043e\u0432 \u0432 \u043e\u0434\u0438\u043d \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0442\u043e\u043f\u0438\u043a. \u041d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u0442 \u0442\u043e\u043f\u0438\u043a \u0438 \u0432\u0438\u0434\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0440\u0435\u0430\u043b\u0442\u0430\u0439\u043c\u0435.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u043d\u0430\u0447\u043d\u0435\u043c.<\/p>\n<p>  \u041f\u0430\u0440\u0430 \u0441\u043b\u043e\u0432 \u043e\u0431 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f\u0445 \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f. \u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u2014 \u044d\u0442\u043e \u043f\u043e \u0441\u0443\u0442\u0438 \u043c\u0435\u0442\u043a\u0430 \u0432 \u043a\u043e\u0434\u0435, \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u043f\u0430\u043a\u0435\u0442, \u043a\u043b\u0430\u0441\u0441, \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438 \u0442.\u0434). \u041f\u043e\u043c\u0435\u0442\u0438\u0432 \u043a\u043e\u0434, \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0432 \u043f\u043e \u044d\u0442\u043e\u0439 \u0441\u0430\u043c\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438.<\/p>\n<p>  \u041d\u0430\u0448\u0438 \u0434\u0432\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <b>CommandHandler<\/b> \u0438 <b>HandlerMethod<\/b>:<\/p>\n<pre><code class=\"java\">@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Component public @interface CommandHandler { } <\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"java\">@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface HandlerMethod {     AppEventsEnum value(); } <\/code><\/pre>\n<p>  <b>RetentionPolicy<\/b> \u2014 \u044d\u0442\u043e \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0438 \u0443 \u043d\u0430\u0441 \u0443\u043a\u0430\u0437\u0430\u043d <i>RUNTIME<\/i>, \u0435\u0449\u0435 \u0435\u0441\u0442\u044c <i>CLASS<\/i> \u0438 <i>SOURCE<\/i>. <\/p>\n<p>  <i>CLASS<\/i> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0435\u0441\u043b\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u043a\u043e\u0434\u0435, <i>SOURCE<\/i> \u0435\u0441\u043b\u0438 \u0432 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0438 <i>RUNTIME<\/i> \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u0435\u043d \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430.<\/p>\n<p>  <b>Target<\/b> \u2014 \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u043b\u0430\u0441\u0441, \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043f\u043e\u043b\u0435 \u0438 \u0442.\u0434.<\/p>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u0432\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/p>\n<pre><code class=\"xml\">&lt;dependency&gt;  &lt;groupId&gt;org.reflections&lt;\/groupId&gt;  &lt;artifactId&gt;reflections&lt;\/artifactId&gt;  &lt;version&gt;0.9.10&lt;\/version&gt; &lt;\/dependency&gt;  &lt;dependency&gt;  &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;  &lt;artifactId&gt;jackson-databind&lt;\/artifactId&gt; &lt;\/dependency&gt; <\/code><\/pre>\n<p>  \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <b>Reflections<\/b> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0441\u043a\u0430\u043d\u0435\u0440 <i>CLASSPATH<\/i>. \u0418\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u043e\u0442\u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0438\u0445 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f(\u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435). \u0422\u0430\u043a\u0436\u0435 \u0443\u043c\u0435\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <i>CLASSPATH<\/i>.<\/p>\n<p>  <b>Jackson Project<\/b> \u0432 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u0435 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430\/\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 JSON. <\/p>\n<p>  \u041e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0442\u0438\u043f\u044b \u0434\u043b\u044f \u0431\u0443\u0434\u0443\u0449\u0438\u0445 event handle \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Enum \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 event handle \u043a\u043b\u0430\u0441\u0441\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441<\/p>\n<pre><code class=\"java\">@Data @NoArgsConstructor @AllArgsConstructor public class AppCommand {     protected Map&lt;String, String&gt; arguments; } <\/code><\/pre>\n<p>  \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/p>\n<pre><code class=\"java\">public class Command1 extends AppCommand {     public Command1() {         super();     } } <\/code><\/pre>\n<p>  \u0418\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438<\/p>\n<pre><code class=\"java\">@Getter @Setter public class Command2 extends AppCommand {      private String someParams;      public Command2() {         super();     }      public Command2(String someParams) {         this.someParams = someParams;     }      public Command2(Map&lt;String, String&gt; arguments, String someParams) {         super(arguments);         this.someParams = someParams;     } } <\/code><\/pre>\n<p>  Enum \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043a \u043a\u043b\u0430\u0441\u0441\u0443, \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0430 getByClass()<\/p>\n<pre><code class=\"java\">public enum AppCommandsEnum {      COMMAND1(Command1.class),     COMMAND2(Command2.class);      private Class&lt;? extends AppCommand&gt; appCommandClass;      AppCommandsEnum(Class&lt;? extends AppCommand&gt; appCommandClass) {         this.appCommandClass = appCommandClass;     }      public static AppCommandsEnum getByClass(Class&lt;? extends AppCommand&gt; appCommandClass) {         for (AppCommandsEnum commandsEnum : AppCommandsEnum.values()) {             if (commandsEnum.appCommandClass.isAssignableFrom(appCommandClass))                 return commandsEnum;         }         return null;     }      public Class getAppCommandClass() {         return appCommandClass;     } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0443 \u043d\u0443\u0436\u0435\u043d \u0438\u043d\u0432\u043e\u043a\u0435\u0440 (\u043a\u043b\u0430\u0441\u0441, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434\u044b).<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f java.lang.reflect.Method.invoke()<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">class CommandInvoker {      private final Method method;     private final Object instance;      CommandInvoker(Method method, Object instance) {         this.method = method;         this.instance = instance;     }      void invoke(AppCommand command) {         try {              method.invoke(instance, command);          } catch (IllegalAccessException | InvocationTargetException e) {             throw new DispatchException(e);         } catch (IllegalArgumentException e) {             throw new MethodArgumentMismatchException(                     \"\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u0430: \"                             + this.method.getName()                             + \" :: \"                             + this.instance.getClass().getName(),                     e);         }     } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u043a\u043e\u0434 \u043f\u043e\u0434 \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u0441\u0442\u0430\u0442\u044c\u044f \u0432\u0441\u044f \u0438\u0437 \u043a\u043e\u0434\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">@Component public class CommandDispatcher {    private static Map&lt;AppCommandsEnum, CommandInvoker&gt; warehouse = new ConcurrentHashMap&lt;&gt;();    private final ApplicationContext context;    @Autowired  public CommandDispatcher(ApplicationContext context) {   this.context = context;   loadDispatchers();  }    private void loadDispatchers() {   Reflections reflections = new Reflections(\"com.xeofus.reflectiveapp.handler\");   Set&lt;Class&lt;?&gt;&gt; annotated = reflections.getTypesAnnotatedWith(CommandHandler.class);     for (Class clazz : annotated) {    for (Method method : clazz.getDeclaredMethods()) { \tHandlerMethod handlerMethod; \tif ((handlerMethod = method.getAnnotation(HandlerMethod.class)) != null) { \t Object beanObject = null; \t try { \t \tbeanObject = context.getBean(clazz); \t } catch (Exception e) { \t \tSystem.out.println(\"Bean not found \" + clazz); \t } \t if (beanObject != null) \t \twarehouse.put( \t\t handlerMethod.value(),  \t\t new CommandInvoker(method, beanObject) \t\t); \t }    }   }  }    public void dispatch(AppCommand command) {   try {    warehouse.get(AppCommandsEnum.getByClass(command.getClass())).invoke(command);   } catch (NullPointerException e) {    throw new MethodNotImplementedException(\"\u0414\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \"  \t+ AppCommandsEnum.getByClass(command.getClass())  \t+ \" \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430\",  \te    );   }  } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043e\u0441\u0442\u0440\u044e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0447\u0435\u043c \u0437\u0430\u043d\u044f\u0442 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440.<\/p>\n<pre><code class=\"java\">private static Map&lt;AppCommandsEnum, CommandInvoker&gt; warehouse = new ConcurrentHashMap&lt;&gt;(); <\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 ConcurrentHashMap, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0435\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/post\/132884\/\">\u0442\u0443\u0442<\/a>. \u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e \u0442\u043e, \u0443 HashMap syn\u0441hronized \u0431\u043b\u043e\u043a\u0438, \u0430 \u0443 ConcurrentHashMap \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0438 \u0440\u0430\u0437\u0431\u0438\u0442\u044b \u043f\u043e hash&#8217;\u0443 \u043a\u043b\u044e\u0447\u0430. \u042d\u0442\u043e \u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u0441 \u043b\u043e\u043a\u043e\u043c \u043f\u043e \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430\u043c, \u0430 \u043d\u0435 \u043f\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0443. \u0412 \u0438\u0442\u043e\u0433\u0435 \u0435\u0441\u0442\u044c \u043c\u0430\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043a\u043b\u0430\u0434 \u0441 \u0431\u0438\u043d\u0430\u043c\u0438 \u043f\u043e\u0441\u043b\u0435 \u0441\u043a\u0430\u043d\u0430 <i>CLASSPATH<\/i>.<\/p>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0435\u0442 DI \u0438 <abbr title=\"\u043f\u043b\u043e\u0445\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u043a\u0430\u044e\u0441\u044c\">\u0432\u044b\u0437\u043e\u0432 \u0438\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430<\/abbr> \u043c\u0435\u0442\u043e\u0434\u0430 loadDispatchers()<\/p>\n<pre><code class=\"java\">@Autowired public CommandDispatcher(ApplicationContext context) { \tthis.context = context; \tloadDispatchers(); } <\/code><\/pre>\n<p>  \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0430.<\/p>\n<p>  \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u0430\u043a\u0435\u0442 \u0434\u043b\u044f \u0441\u043a\u0430\u043d\u0430<\/p>\n<pre><code class=\"java\">Reflections reflections = new Reflections(\"com.xeofus.reflectiveapp.handler\");<\/code><\/pre>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 @CommandHandler<\/p>\n<pre><code class=\"java\">Set&lt;Class&lt;?&gt;&gt; annotated = reflections.getTypesAnnotatedWith(CommandHandler.class);<\/code><\/pre>\n<p>  \u0414\u0440\u0430\u043a\u0430\u0440\u0438\u0441<\/p>\n<pre><code class=\"java\">\/\/\u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443 for (Class clazz : annotated) {  \/\/\u0438\u0449\u0435\u043c \u0437\u0430\u0434\u0435\u043a\u043b\u0430\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b  for (Method method : clazz.getDeclaredMethods()) {   HandlerMethod handlerMethod;   \/\/\u0435\u0441\u043b\u0438 \u043c\u0435\u0442\u043e\u0434 \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430\u0448\u0435\u0439 @HandlerMethod   if ((handlerMethod = method.getAnnotation(HandlerMethod.class)) != null) {   \tObject beanObject = null;   \t\/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0431\u0438\u043d \u0432\u044b\u0442\u0430\u0449\u0438\u0432 \u0438\u0437 ApplicationContext   \t\/\/ \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441   \ttry {          \/\/\u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0441\u0430\u043c\u0430\u044f \u043b\u0443\u0447\u0448\u0430\u044f \u0438\u0434\u0435\u044f          \/\/\u043d\u0430\u0440\u0443\u0448\u0430\u0435\u0442 \u0444\u0438\u043b\u043e\u0441\u043e\u0444\u0438\u044e IoC   \t beanObject = context.getBean(clazz);   \t} catch (Exception e) {   \t System.out.println(\"Bean not found \" + clazz);   \t}   \t\/\/\u0414\u0430\u043b\u0435\u0435, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 ConcurrentHashMap   \tif (beanObject != null)   \t warehouse.put(   \t  handlerMethod.value(),   \t  new CommandInvoker(method, beanObject)   \t );   }  } } <\/code><\/pre>\n<p>  \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/p>\n<pre><code class=\"java\">public void dispatch(AppCommand command) {  try {   warehouse.get(AppCommandsEnum.getByClass(command.getClass())).invoke(command);  } catch (NullPointerException e) {  \tthrow new MethodNotImplementedException(\"\u0414\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \"  \t + AppCommandsEnum.getByClass(command.getClass())  \t + \" \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430\",  \t e  \t);  } } <\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0434\u043b\u044f WebSocket \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">@Controller public class WsController {   private final CommandDispatcher dispatcher;   private final ObjectMapper mapper;      @Autowired   public WsController(CommandDispatcher dispatcher, ObjectMapper mapper) {       this.dispatcher = dispatcher;       this.mapper = mapper;   }      @MessageMapping(\"\/command\/{commandName}\")   public void commandHandler(           @DestinationVariable String commandName,           Message message   ) {       try {        @SuppressWarnings(\"unchecked\")        AppCommand appCommand = (AppCommand) mapper.readValue(         new String((byte[]) message.getPayload()),         AppCommandsEnum.valueOf(commandName.toUpperCase()).getAppCommandClass()        );         dispatcher.dispatch(appCommand);       } catch (IOException e) {        e.printStackTrace();       }   } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432\u0438\u0434\u0430 <u>\/command\/command1<\/u>, \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043c <u>command1<\/u> \u0432 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440, \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u043c \u0438\u0437 <b>AppCommandsEnum<\/b> \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430<\/p>\n<pre><code class=\"java\">AppCommandsEnum.valueOf(commandName.toUpperCase())<\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u0432\u044b\u0448\u0435 \u0432\u0435\u0440\u043d\u0435\u0442 enum <b>COMMAND1<\/b>, \u0433\u0435\u0442\u0442\u0435\u0440\u043e\u043c <i>getAppCommandClass()<\/i> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 handler <u>Command1.class<\/u>.<\/p>\n<p>  \u041f\u043b\u044e\u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u0437 <i>message.getPayload()<\/i>. <\/p>\n<pre><code class=\"java\">new String((byte[]) message.getPayload())<\/code><\/pre>\n<p>  \u041a\u0430\u0441\u0442\u0438\u043c \u0432\u0441\u0435 \u0441 \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <i>ObjectMapper.readValue()<\/i> \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0430.<\/p>\n<p>  \u0418\u0442\u043e\u0433: \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e handler \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0438\u043c\u0435\u043d\u0443\u044f \u0438\u0445 \u043a\u0430\u043a \u0445\u043e\u0442\u0438\u043c, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u041f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f handler \u043a\u043b\u0430\u0441\u0441\u0430, \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 <b>AppCommandsEnum<\/b><\/p>\n<pre><code class=\"java\">MYNEWCOMMAND(MyNewCommand.class),<\/code><\/pre>\n<p>  \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0433\u043e\u0442\u043e\u0432 \u043d\u043e\u0432\u044b\u0439 endpoint <u>\/command\/mynewcommand<\/u><br \/>  \u041a\u0430\u043a \u0432\u044b \u0443\u0436\u0435 \u043f\u043e\u043d\u044f\u043b\u0438, endpoint \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u0441 enum, \u044d\u0442\u043e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>  \u0414\u0430\u043b\u0435\u0435, \u043d\u0443\u0436\u043d\u044b \u0445\u044d\u043d\u0434\u043b\u0435\u0440 \u043a\u043b\u0430\u0441\u0441\u044b \u0441 \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u043d\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c, \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u0439 \u0441\u0430\u043c\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438, \u0440\u0430\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0438\u0448\u0435\u0442\u0441\u044f app. \u041a\u043b\u0430\u0441\u0441\u044b \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448\u0435\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <b>CommandHandler<\/b>, \u043c\u0435\u0442\u043e\u0434\u044b \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <b>HandlerMethod<\/b><\/p>\n<pre><code class=\"java\">@CommandHandler public class MyCommand1 {      private final WsCallbackDispatcher dispatcher;     private final ObjectMapper mapper;      @Autowired     private MyCommand1(WsCallbackDispatcher dispatcher, ObjectMapper mapper) {         this.dispatcher = dispatcher;         this.mapper = mapper;     }      @HandlerMethod(AppCommandsEnum.COMMAND1)     public void runExecution(Command1 command1) {         \/\/\u0437\u0434\u0435\u0441\u044c \u0431\u043b\u043e\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0438         Runnable run = () -&gt; {             try {                 dispatcher.dispatch(mapper.writeValueAsString(command1));             } catch (JsonProcessingException e) {                 e.printStackTrace();             }         };          new Thread(run).start();     } } <\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c Runnable, \u0441 \u043c\u0438\u043d\u0438\u043c\u0443\u043c\u043e\u043c \u0442\u0440\u0443\u0434\u043e\u0437\u0430\u0442\u0440\u0430\u0442 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c ExecutorService.<\/p>\n<p>  \u041c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0442\u0440\u0443\u0434 \u0432\u044b\u0448\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u043c \u0438 \u043d\u0435 \u0441\u0430\u043c\u044b\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u043d\u0443 \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u043a\u0430, \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438. \u0412 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0445 \u0440\u043e\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u0438\u043d\u0430 \ud83d\ude42<\/p>\n<p>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435!<\/p>\n<p>  <a href=\"https:\/\/github.com\/xeofus\/reflectiveapp\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 Github<\/a><\/div>\n<p>               <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <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\/post\/460871\/\"> https:\/\/habr.com\/ru\/post\/460871\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sl\/bo\/qo\/slboqopgn4vzsownqn48d4be7x8.jpeg\"><\/p>\n<p>  \u041a\u0443, \u0425\u0430\u0431\u0440! <\/p>\n<p>  \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u043e\u0432\u0435\u043d\u0438\u044f: \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u0430\u043f\u0438\u0441\u0430\u0432 if \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438 \u0438\u043b\u0438 switch \u0441 \u043f\u043e\u043b\u043e\u0442\u043d\u043e\u043c \u043a\u0435\u0439\u0441\u043e\u0432, \u0447\u0443\u0432\u0441\u0442\u0432\u0443\u044e, \u0447\u0442\u043e \u0433\u0434\u0435-\u0442\u043e \u043f\u043b\u0430\u0447\u0443\u0442 \u043a\u043e\u0442\u0438\u043a\u0438. \u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0439, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u0442\u0438\u043a\u043e\u0432. \u0420\u0443\u043a\u0430 \u0442\u044f\u043d\u0435\u0442\u0441\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c <s>\u0438 \u043d\u0430\u043a\u043e\u0440\u043c\u0438\u0442\u044c \u043a\u043e\u0442\u0438\u043a\u043e\u0432<\/s>.<\/p>\n<p>  \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u0438\u043d\u0434\u0443\u043b\u044c\u0433\u0435\u043d\u0446\u0438\u044f. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043a\u0435\u0439\u0441\u043e\u0432 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A0%D0%B5%D1%84%D0%BB%D0%B5%D0%BA%D1%81%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)\">\u0440\u0435\u0444\u043b\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/a>.<\/p>\n<p>  \u0420\u0430\u0431\u043e\u0442\u0430\u044e \u044f \u0432 <a href=\"https:\/\/beeline.kg\/\">Beeline \u041a\u044b\u0440\u0433\u044b\u0437\u0441\u0442\u0430\u043d<\/a>, \u0438 \u0443 \u0442\u0435\u043b\u0435\u043a\u043e\u043c\u0430 \u0447\u0430\u0441\u0442\u043e \u043d\u0430 \u043f\u043e\u0432\u0435\u0441\u0442\u043a\u0435 \u0434\u043d\u044f \u043a\u0435\u0439\u0441\u044b \u0441 \u0443\u0441\u043b\u043e\u0432\u0438\u0435\u043c \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0417\u0430\u0434\u0430\u0447\u0430 \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c application, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0435\u0433\u043e \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0432 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u2014 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0442\u0430\u043a \u0441\u0435\u0431\u0435, \u043a\u0430\u043a \u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u043c\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u0418 \u043e\u0431\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043b\u0438\u0448\u044c \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/302570\/\">\u0441\u043a\u043b\u043e\u043d\u043d\u043e\u043c\u0443 \u043a \u043d\u0430\u0441\u0438\u043b\u0438\u044e \u043f\u0441\u0438\u0445\u043e\u043f\u0430\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u043d\u0430\u0435\u0442, \u0433\u0434\u0435 \u044f \u0436\u0438\u0432\u0443<\/a>, \u0435\u0441\u043b\u0438 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 100 \u0438\u043b\u0438 1000 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440. <br \/>  \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u0438\u0432\u044b\u043a\u043b\u0438 \u0441\u0440\u0430\u0437\u0443 \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u0434, \u0442\u043e \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 <a href=\"https:\/\/github.com\/xeofus\/reflectiveapp\">\u0442\u0443\u0442<\/a>.  <\/p>\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-292918","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/292918","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=292918"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/292918\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=292918"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=292918"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=292918"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}