{"id":294612,"date":"2019-09-12T15:00:31","date_gmt":"2019-09-12T15:00:31","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=294612"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=294612","title":{"rendered":"\u0412\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Kotlin + Spring Boot + Vue.js"},"content":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c, \u0434\u043e\u0440\u043e\u0433\u0438\u0435 \u043e\u0431\u0438\u0442\u0430\u0442\u0435\u043b\u0438 \u0425\u0430\u0431\u0440\u0430\u0445\u0430\u0431\u0440\u0430!<\/p>\n<p>  \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u043c\u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u044b\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043f\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u0422\u043e \u0435\u0441\u0442\u044c, \u044f \u0431\u044b\u043b \u0432\u043e\u043b\u0435\u043d \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0435\u043a \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439 \u043d\u0430 \u0441\u0432\u043e\u0451 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435. \u041f\u043e\u0442\u043e\u043c\u0443 \u043d\u0435 \u043f\u0440\u0435\u043c\u0438\u043d\u0443\u043b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u00ab\u043f\u043e\u0449\u0443\u043f\u0430\u0442\u044c\u00bb <s>\u043c\u043e\u0434\u043d\u044b\u0435, \u043c\u043e\u043b\u043e\u0434\u0451\u0436\u043d\u044b\u0435<\/s> \u043c\u043d\u043e\u0433\u043e\u043e\u0431\u0435\u0449\u0430\u044e\u0449\u0438\u0435, \u043d\u043e \u043c\u0430\u043b\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u043c\u043d\u0435 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 <b>Kotlin<\/b> \u0438 <b>Vue.js<\/b>, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 <b>Spring Boot<\/b> \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0438\u0432 \u0432\u0441\u0451 \u044d\u0442\u043e \u043d\u0430 \u043d\u0435\u0437\u0430\u043c\u044b\u0441\u043b\u043e\u0432\u0430\u0442\u043e\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. <br \/>  <a name=\"habracut\"><\/a><br \/>  \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0432, \u044f \u043e\u043f\u0440\u043e\u043c\u0435\u0442\u0447\u0438\u0432\u043e \u043f\u043e\u043b\u0430\u0433\u0430\u043b, \u0447\u0442\u043e \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043d\u0430\u0439\u0434\u0451\u0442\u0441\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u0438 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432 \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443. \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0438 \u0432\u0441\u0435 \u043e\u043d\u0438 \u0445\u043e\u0440\u043e\u0448\u0438, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e REST-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430. \u0417\u0430\u0442\u0435\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u0440\u0435\u0447\u0438\u044f. \u0410 \u0432\u0435\u0434\u044c \u0434\u0430\u0436\u0435 \u0432 \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u0447\u0435\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0442\u0435\u043a\u0441\u0442\u0430, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.<\/p>\n<p>  \u041a\u043e\u0435-\u043a\u0430\u043a \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0432\u0448\u0438\u0441\u044c, \u044f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043c\u0443-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u043e.<\/p>\n<h3>\u041e \u0447\u0451\u043c \u0438 \u0434\u043b\u044f \u043a\u043e\u0433\u043e \u0441\u0442\u0430\u0442\u044c\u044f <\/h3>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u2014 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0434\u043b\u044f \u00ab\u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u0440\u0442\u0430\u00bb \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u043c \u043d\u0430 <b>Kotlin<\/b> + <b>Spring Boot<\/b> \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c \u043d\u0430 <b>Vue.js<\/b>. \u0421\u0440\u0430\u0437\u0443 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u044f \u043d\u0435 \u00ab\u0442\u043e\u043f\u043b\u044e\u00bb \u0437\u0430 \u043d\u0438\u0445 \u0438 \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u044e \u043e \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u044b\u0445 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430. \u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043e\u043f\u044b\u0442\u043e\u043c.<\/p>\n<p>  \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0438\u043c\u0435\u044e\u0449\u0438\u0445 \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Java, Spring Framework\/Spring Boot, React\/Angular \u0438\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u0447\u0438\u0441\u0442\u044b\u043c JavaScript. \u041f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 \u0438 \u0442\u0435\u043c, \u0443 \u043a\u043e\u0433\u043e \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c, \u043d\u043e, \u0431\u043e\u044e\u0441\u044c, \u0442\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0435\u0442\u0430\u043b\u044f\u0445 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e. \u0412\u043e\u043e\u0431\u0449\u0435, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u044d\u0442\u043e\u0433\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435, \u043d\u043e, \u0434\u0443\u043c\u0430\u044e, \u043b\u0443\u0447\u0448\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043b\u044c\u043d\u043e \u043d\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u0442\u044c\u0441\u044f \u043e\u0442 \u0442\u0435\u043c\u044b \u0438 \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u043e\u0439. <\/p>\n<p>  \u0411\u044b\u0442\u044c \u043c\u043e\u0436\u0435\u0442, \u043a\u043e\u043c\u0443 \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u0431\u044d\u043a\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0430 Kotlin \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0430\u043c\u043e\u043c\u0443 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0430\u043d\u043d\u0443\u044e \u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0443, \u0430 \u043a\u043e\u043c\u0443-\u0442\u043e \u2014 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b, \u0432\u0437\u044f\u0432 \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0441\u043a\u0435\u043b\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0448\u0430\u0433\u043e\u0432, \u0432 \u0446\u0435\u043b\u043e\u043c, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0441\u0442\u0430\u0442\u044c\u044f \u0438\u043c\u0435\u0435\u0442 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e-\u043e\u0431\u0437\u043e\u0440\u043d\u044b\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440. \u0421\u0435\u0439\u0447\u0430\u0441 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u0434\u0430 \u0438 \u0441\u0430\u043c\u0430 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430 \u0432\u0438\u0434\u0438\u0442\u0441\u044f, \u0441\u043a\u043e\u0440\u0435\u0435, \u043a\u0430\u043a \u0445\u0438\u043f\u0441\u0442\u0435\u0440\u0441\u043a\u0430\u044f \u0437\u0430\u0442\u0435\u044f \u2014 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043c\u043e\u0434\u043d\u044b\u0445 \u0441\u043b\u043e\u0432 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435. \u041d\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0438 \u0437\u0430\u0439\u043c\u0451\u0442 \u0441\u0432\u043e\u044e \u043d\u0438\u0448\u0443 \u0432 \u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u0411\u044b\u0442\u044c \u043c\u043e\u0436\u0435\u0442, \u0441\u0440\u0435\u0434\u0438 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435 (\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0449\u0438\u0435) \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u0436\u0438\u0442\u044c \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430, \u043a\u043e\u0433\u0434\u0430 Kotlin \u0438 Vue.js \u0431\u0443\u0434\u0443\u0442 \u0442\u0430\u043a \u0436\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b \u0438 \u0432\u043e\u0441\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u044b, \u043a\u0430\u043a \u0441\u0435\u0439\u0447\u0430\u0441 Java \u0438 React. \u0412\u0435\u0434\u044c Kotlin \u0438 Vue.js \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0430\u044e\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043d\u0430\u0434\u0435\u0436\u0434\u044b.<\/p>\n<p>  \u0417\u0430 \u0442\u043e \u0432\u0440\u0435\u043c\u044f, \u043f\u043e\u043a\u0430 \u044f \u043f\u0438\u0441\u0430\u043b \u044d\u0442\u043e \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e, \u0432 \u0441\u0435\u0442\u0438 \u0443\u0436\u0435 \u0441\u0442\u0430\u043b\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u043a\u0430\u043a, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/auth0.com\/blog\/vuejs-spring-boot-kotlin-and-graphql-building-modern-apps-part-1\/\">\u044d\u0442\u0430<\/a>. \u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c, \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u0433\u0434\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0434\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e REST-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u0440\u043e\u043b\u044f\u043c, \u0447\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438\u043c \u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u043b \u0441\u0432\u043e\u0451 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e. <\/p>\n<h3>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<p>  <\/p>\n<ul>\n<li><a href=\"#Reference\">\u041a\u0440\u0430\u0442\u043a\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430<\/a><\/li>\n<li><a href=\"#Instruments\">\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/a><\/li>\n<li><a href=\"#Initialization\">\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/li>\n<li><a href=\"#RESTAPI\">REST API<\/a><\/li>\n<li><a href=\"#DB\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/li>\n<li><a href=\"#Authentication\">\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/a><\/li>\n<li><a href=\"#WaysToImprove\">\u041f\u0443\u0442\u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f<\/a><\/li>\n<li><a href=\"#Links\">\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/a><\/li>\n<\/ul>\n<p>  <a name=\"Reference\"><\/a>  <\/p>\n<h2>\u041a\u0440\u0430\u0442\u043a\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430<\/h2>\n<p>  <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Kotlin\"><b>Kotlin<\/b><\/a> \u2014 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0432\u0435\u0440\u0445 <b>JVM<\/b> \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043c\u0435\u0436\u0434\u0443\u043d\u0430\u0440\u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0435\u0439 <b>JetBrains<\/b>.<br \/>  <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Vue.js\"><b>Vue.js <\/b><\/a> \u2014 <b>JavaScript<\/b> -\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u0442\u0438\u043b\u0435.<\/p>\n<p>  <a name=\"Instruments\"><\/a>  <\/p>\n<h2>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/h2>\n<p>  \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0440\u0435\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u044f \u0431\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <b>IntelliJ IDEA<\/b> \u2014 \u0441\u0440\u0435\u0434\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442 <b>JetBrains<\/b>, \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0443\u044e \u0448\u0438\u0440\u043e\u043a\u0443\u044e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c \u0432 Java-\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d\u0430 \u0438\u043c\u0435\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0444\u0438\u0447\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Kotlin \u0432\u043f\u043b\u043e\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f Java-\u043a\u043e\u0434\u0430 \u0432 \u043a\u043e\u0434 \u043d\u0430 Kotlin. \u041e\u0434\u043d\u0430\u043a\u043e, \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043c\u0438\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0446\u0435\u043b\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0438 \u0432\u0441\u0451 \u0432\u0434\u0440\u0443\u0433 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439.<\/p>\n<p>  \u0421\u0447\u0430\u0441\u0442\u043b\u0438\u0432\u044b\u0435 \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u0435\u043b\u0438 <b>IntelliJ IDEA Ultimate Edition<\/b> \u043c\u043e\u0433\u0443\u0442 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Vue.js \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/9442-vue-js\">\u043f\u043b\u0430\u0433\u0438\u043d<\/a>. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0432\u044b \u0438\u0449\u0435\u0442\u0435 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441 \u043c\u0435\u0436\u0434\u0443 <s>\u0445\u0430\u043b\u044f\u0432\u043e\u0439<\/s> \u0446\u0435\u043d\u043e\u0439 \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e\u043c, \u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <b>Microsoft Visual Code<\/b> \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=octref.vetur\">Vetur<\/a>.<\/p>\n<p>  \u041f\u043e\u043b\u0430\u0433\u0430\u044e, \u0434\u043b\u044f \u043c\u043d\u043e\u0433\u0438\u0445 \u044d\u0442\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043d\u043e \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u043d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b c Vue.js \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 <a href=\"https:\/\/www.npmjs.com\">npm<\/a>. \u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e \u043f\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 Vue.js \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 <a href=\"https:\/\/cli.vuejs.org\/guide\/installation.html\">Vue CLI<\/a>.<\/p>\n<p>  \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043d\u0430 Java \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/maven.apache.org\">Maven<\/a>, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 <a href=\"https:\/\/www.postgresql.org\">PostgreSQL<\/a>.<\/p>\n<p>  <a name=\"Initialization\"><\/a>  <\/p>\n<h2>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u0430\u0437\u0432\u0430\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <i>kotlin-spring-vue<\/i>. \u041d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u0432\u0430 \u043c\u043e\u0434\u0443\u043b\u044f \u2014 <b>backend<\/b> \u0438 <b>frontend<\/b>. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434. \u0417\u0430\u0442\u0435\u043c, \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0431\u044d\u043a\u0435\u043d\u0434 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u0435 index.hmtl, favicon.ico \u0438 \u0432\u0441\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b (*.js, *.css, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u0442.\u0434.). <\/p>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u0432\u0435 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0438 \u2014 <i>\/backend<\/i> \u0438 <i>\/frontend<\/i>. \u041e\u0434\u043d\u0430\u043a\u043e, \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0442\u043e\u0440\u043e\u043f\u0438\u0442\u044c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u0445 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>  \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0443\u0442\u044f\u043c\u0438:<\/p>\n<ul>\n<li>\u0432\u0440\u0443\u0447\u043d\u0443\u044e (\u043f\u0443\u0442\u044c \u0441\u0430\u043c\u0443\u0440\u0430\u044f)<\/li>\n<li>\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u043e\u0435\u043a\u0442 Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 <b>Spring Tool Suite<\/b> \u0438\u043b\u0438 <b>IntelliJ IDEA Ultimate Edition<\/b><\/li>\n<li>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/start.spring.io\"><b>Spring Initializr<\/b><\/a>, \u0443\u043a\u0430\u0437\u0430\u0432 \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u2014 \u044d\u0442\u043e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439, \u0441\u0430\u043c\u044b\u0439 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431<\/li>\n<\/ul>\n<p>  \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0442\u0430\u043a\u043e\u0432\u0430:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0430\u0440\u0446\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<ul>\n<li>Project: Maven Project<\/li>\n<li>Language: Kotlin<\/li>\n<li>Spring Boot: 2.1.6<\/li>\n<li>Project Metadata: Java 8, JAR packaging<\/li>\n<li>Dependencies: Spring Web Starter, Spring Boot Actuator, Spring Boot DevTools<\/li>\n<\/ul>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/rm\/vy\/ox\/rmvyoxpbqjjaajjcfbvdpe5ams0.png\"\/>  <\/div>\n<\/div>\n<p>  <i>pom.xml<\/i> \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">pom.xml &#8212; backend<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;project xmlns=&quot;http:\/\/maven.apache.org\/POM\/4.0.0&quot; xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; \txsi:schemaLocation=&quot;http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd&quot;&gt; \t&lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt; \t \t&lt;parent&gt; \t\t&lt;groupId&gt;com.kotlin-spring-vue&lt;\/groupId&gt; \t\t&lt;artifactId&gt;demo&lt;\/artifactId&gt; \t\t&lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt; \t&lt;\/parent&gt; \t \t&lt;groupId&gt;com.kotlin-spring-vue&lt;\/groupId&gt; \t&lt;artifactId&gt;backend&lt;\/artifactId&gt; \t&lt;version&gt;0.0.1-SNAPSHOT&lt;\/version&gt; \t&lt;name&gt;backend&lt;\/name&gt; \t&lt;description&gt;Backend module for Kotlin + Spring Boot + Vue.js&lt;\/description&gt;  \t&lt;properties&gt; \t\t&lt;java.version&gt;1.8&lt;\/java.version&gt; \t\t&lt;kotlin.version&gt;1.2.71&lt;\/kotlin.version&gt; \t\t&lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt; \t\t&lt;project.reporting.outputEncoding&gt;UTF-8&lt;\/project.reporting.outputEncoding&gt; \t\t&lt;rest-assured.version&gt;3.3.0&lt;\/rest-assured.version&gt; \t\t&lt;start-class&gt;com.kotlinspringvue.backend.BackendApplicationKt&lt;\/start-class&gt; \t&lt;\/properties&gt;  \t&lt;dependencies&gt; \t\t&lt;dependency&gt; \t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; \t\t\t&lt;artifactId&gt;spring-boot-starter-actuator&lt;\/artifactId&gt; \t\t&lt;\/dependency&gt; \t\t&lt;dependency&gt; \t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; \t\t\t&lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt; \t\t&lt;\/dependency&gt; \t\t&lt;dependency&gt; \t\t\t&lt;groupId&gt;com.fasterxml.jackson.module&lt;\/groupId&gt; \t\t\t&lt;artifactId&gt;jackson-module-kotlin&lt;\/artifactId&gt; \t\t&lt;\/dependency&gt; \t\t&lt;dependency&gt; \t\t\t&lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt; \t\t\t&lt;artifactId&gt;kotlin-reflect&lt;\/artifactId&gt; \t\t&lt;\/dependency&gt; \t\t&lt;dependency&gt; \t\t\t&lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt; \t\t\t&lt;artifactId&gt;kotlin-stdlib-jdk8&lt;\/artifactId&gt; \t\t&lt;\/dependency&gt;  \t\t&lt;dependency&gt; \t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; \t\t\t&lt;artifactId&gt;spring-boot-devtools&lt;\/artifactId&gt; \t\t\t&lt;scope&gt;runtime&lt;\/scope&gt; \t\t\t&lt;optional&gt;true&lt;\/optional&gt; \t\t&lt;\/dependency&gt; \t\t&lt;dependency&gt; \t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; \t\t\t&lt;artifactId&gt;spring-boot-starter-test&lt;\/artifactId&gt; \t\t\t&lt;scope&gt;test&lt;\/scope&gt; \t\t&lt;\/dependency&gt; \t&lt;\/dependencies&gt;  \t&lt;build&gt; \t\t&lt;sourceDirectory&gt;${project.basedir}\/src\/main\/kotlin&lt;\/sourceDirectory&gt; \t\t&lt;testSourceDirectory&gt;${project.basedir}\/src\/test\/kotlin&lt;\/testSourceDirectory&gt; \t\t&lt;plugins&gt; \t\t\t&lt;plugin&gt; \t\t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; \t\t\t\t&lt;artifactId&gt;spring-boot-maven-plugin&lt;\/artifactId&gt; \t\t\t\t&lt;configuration&gt; \t\t\t\t\t&lt;mainClass&gt;com.kotlinspringvue.backend.BackendApplicationKt&lt;\/mainClass&gt; \t\t\t\t&lt;\/configuration&gt; \t\t\t&lt;\/plugin&gt; \t\t\t&lt;plugin&gt; \t\t\t\t&lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt; \t\t\t\t&lt;artifactId&gt;kotlin-maven-plugin&lt;\/artifactId&gt; \t\t\t\t&lt;configuration&gt; \t\t\t\t\t&lt;args&gt; \t\t\t\t\t\t&lt;arg&gt;-Xjsr305=strict&lt;\/arg&gt; \t\t\t\t\t&lt;\/args&gt; \t\t\t\t\t&lt;compilerPlugins&gt; \t\t\t\t\t\t&lt;plugin&gt;spring&lt;\/plugin&gt; \t\t\t\t\t&lt;\/compilerPlugins&gt; \t\t\t\t&lt;\/configuration&gt; \t\t\t\t&lt;dependencies&gt; \t\t\t\t\t&lt;dependency&gt; \t\t\t\t\t\t&lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt; \t\t\t\t\t\t&lt;artifactId&gt;kotlin-maven-allopen&lt;\/artifactId&gt; \t\t\t\t\t\t&lt;version&gt;${kotlin.version}&lt;\/version&gt; \t\t\t\t\t&lt;\/dependency&gt; \t\t\t\t&lt;\/dependencies&gt; \t\t\t&lt;\/plugin&gt; \t\t\t&lt;plugin&gt; \t\t\t\t&lt;artifactId&gt;maven-resources-plugin&lt;\/artifactId&gt; \t\t\t\t&lt;executions&gt; \t\t\t\t\t&lt;execution&gt; \t\t\t\t\t\t&lt;id&gt;copy Vue.js frontend content&lt;\/id&gt; \t\t\t\t\t\t&lt;phase&gt;generate-resources&lt;\/phase&gt; \t\t\t\t\t\t&lt;goals&gt; \t\t\t\t\t\t\t&lt;goal&gt;copy-resources&lt;\/goal&gt; \t\t\t\t\t\t&lt;\/goals&gt; \t\t\t\t\t\t&lt;configuration&gt; \t\t\t\t\t\t\t&lt;outputDirectory&gt;src\/main\/resources\/public&lt;\/outputDirectory&gt; \t\t\t\t\t\t\t&lt;overwrite&gt;true&lt;\/overwrite&gt; \t\t\t\t\t\t\t&lt;resources&gt; \t\t\t\t\t\t\t\t&lt;resource&gt; \t\t\t\t\t\t\t\t\t&lt;directory&gt;${project.parent.basedir}\/frontend\/target\/dist&lt;\/directory&gt; \t\t\t\t\t\t\t\t\t&lt;includes&gt; \t\t\t\t\t\t\t\t\t\t&lt;include&gt;static\/&lt;\/include&gt; \t\t\t\t\t\t\t\t\t\t&lt;include&gt;index.html&lt;\/include&gt; \t\t\t\t\t\t\t\t\t\t&lt;include&gt;favicon.ico&lt;\/include&gt; \t\t\t\t\t\t\t\t\t&lt;\/includes&gt; \t\t\t\t\t\t\t\t&lt;\/resource&gt; \t\t\t\t\t\t\t&lt;\/resources&gt; \t\t\t\t\t\t&lt;\/configuration&gt; \t\t\t\t\t&lt;\/execution&gt; \t\t\t\t&lt;\/executions&gt; \t\t\t&lt;\/plugin&gt; \t\t&lt;\/plugins&gt; \t&lt;\/build&gt; &lt;\/project&gt; <\/code><\/pre>\n<p>  \u041e\u0431\u0440\u0430\u0449\u0430\u044e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435:<\/p>\n<ul>\n<li>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <i>Kt<\/i><\/li>\n<li>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438\u0437 <i>\u043a\u043e\u0440\u043d\u0435\u0432\u0430\u044f_\u043f\u0430\u043f\u043a\u0430_\u043f\u0440\u043e\u0435\u043a\u0442\u0430\/frontend\/target\/dist<\/i> \u0432 <i>src\/main\/resources\/public<\/i><\/li>\n<li>\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 (parent) \u0432 \u043b\u0438\u0446\u0435 <i>spring-boot-starter-parent<\/i> \u043f\u0440\u0435\u043d\u0435\u0441\u0451\u043d \u043d\u0430 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e <i>pom.xml<\/i><\/li>\n<\/ul>\n<p>  <\/div>\n<\/div>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"plaintext\">$ vue create frontend<\/code><\/pre>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u2014 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<p>  \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043c\u043e\u0434\u0443\u043b\u044c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443 <i>\/dist<\/i>, \u043e\u0434\u043d\u0430\u043a\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u043f\u0430\u043f\u043a\u0435 \/target. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <i>vue.config.js<\/i> \u043f\u0440\u044f\u043c\u043e \u0432 <i>\/frontend<\/i> \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438:<\/p>\n<pre><code class=\"javascript\">module.exports = {       outputDir: 'target\/dist',      assetsDir: 'static' } <\/code><\/pre>\n<p>  \u041f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0432 \u043c\u043e\u0434\u0443\u043b\u044c <i>frontend<\/i> \u0444\u0430\u0439\u043b <i>pom.xml<\/i> \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">pom.xml &#8212; frontend<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;project xmlns=&quot;http:\/\/maven.apache.org\/POM\/4.0.0&quot; xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd&quot;&gt;   &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;   &lt;artifactId&gt;frontend&lt;\/artifactId&gt;    &lt;parent&gt;      &lt;groupId&gt;com.kotlin-spring-vue&lt;\/groupId&gt;      &lt;artifactId&gt;demo&lt;\/artifactId&gt;      &lt;version&gt;0.0.1-SNAPSHOT&lt;\/version&gt;   &lt;\/parent&gt;    &lt;properties&gt;      &lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;      &lt;project.reporting.outputEncoding&gt;UTF-8&lt;\/project.reporting.outputEncoding&gt;      &lt;java.version&gt;1.8&lt;\/java.version&gt;       &lt;frontend-maven-plugin.version&gt;1.6&lt;\/frontend-maven-plugin.version&gt;   &lt;\/properties&gt;    &lt;build&gt;      &lt;plugins&gt;         &lt;plugin&gt;            &lt;groupId&gt;com.github.eirslett&lt;\/groupId&gt;            &lt;artifactId&gt;frontend-maven-plugin&lt;\/artifactId&gt;            &lt;version&gt;${frontend-maven-plugin.version}&lt;\/version&gt;            &lt;executions&gt;               &lt;!-- Install our node and npm version to run npm\/node scripts--&gt;               &lt;execution&gt;                  &lt;id&gt;install node and npm&lt;\/id&gt;                  &lt;goals&gt;                     &lt;goal&gt;install-node-and-npm&lt;\/goal&gt;                  &lt;\/goals&gt;                  &lt;configuration&gt;                     &lt;nodeVersion&gt;v11.8.0&lt;\/nodeVersion&gt;                  &lt;\/configuration&gt;               &lt;\/execution&gt;               &lt;!-- Install all project dependencies --&gt;               &lt;execution&gt;                  &lt;id&gt;npm install&lt;\/id&gt;                  &lt;goals&gt;                     &lt;goal&gt;npm&lt;\/goal&gt;                  &lt;\/goals&gt;                  &lt;!-- optional: default phase is &quot;generate-resources&quot; --&gt;                  &lt;phase&gt;generate-resources&lt;\/phase&gt;                  &lt;!-- Optional configuration which provides for running any npm command --&gt;                  &lt;configuration&gt;                     &lt;arguments&gt;install&lt;\/arguments&gt;                  &lt;\/configuration&gt;               &lt;\/execution&gt;               &lt;!-- Build and minify static files --&gt;               &lt;execution&gt;                  &lt;id&gt;npm run build&lt;\/id&gt;                  &lt;goals&gt;                     &lt;goal&gt;npm&lt;\/goal&gt;                  &lt;\/goals&gt;                  &lt;configuration&gt;                     &lt;arguments&gt;run build&lt;\/arguments&gt;                     &lt;\/configuration&gt;               &lt;\/execution&gt;            &lt;\/executions&gt;         &lt;\/plugin&gt;      &lt;\/plugins&gt;   &lt;\/build&gt; &lt;\/project&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c <i>pom.xml<\/i> \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">pom.xml<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;project xmlns=&quot;http:\/\/maven.apache.org\/POM\/4.0.0&quot;          xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot;          xsi:schemaLocation=&quot;http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd&quot;&gt;     &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;      &lt;groupId&gt;com.kotlin-spring-vue&lt;\/groupId&gt;     &lt;artifactId&gt;demo&lt;\/artifactId&gt;     &lt;packaging&gt;pom&lt;\/packaging&gt;     &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;     &lt;modules&gt;         &lt;module&gt;backend&lt;\/module&gt;         &lt;module&gt;frontend&lt;\/module&gt;     &lt;\/modules&gt;      &lt;name&gt;kotlin-spring-vue&lt;\/name&gt;     &lt;description&gt;Kotlin + Spring Boot + Vue.js&lt;\/description&gt;      &lt;parent&gt;         &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;         &lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;         &lt;version&gt;2.1.3.RELEASE&lt;\/version&gt;         &lt;relativePath\/&gt; &lt;!-- lookup parent from repository --&gt;     &lt;\/parent&gt;      &lt;properties&gt;         &lt;main.basedir&gt;${project.basedir}&lt;\/main.basedir&gt;         &lt;!-- Analysis Tools for CI --&gt;         &lt;build-plugin.jacoco.version&gt;0.8.2&lt;\/build-plugin.jacoco.version&gt;         &lt;build-plugin.coveralls.version&gt;4.3.0&lt;\/build-plugin.coveralls.version&gt;         &lt;kotlin.version&gt;1.2.71&lt;\/kotlin.version&gt;     &lt;\/properties&gt;      &lt;dependencies&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt;             &lt;artifactId&gt;kotlin-stdlib-jdk8&lt;\/artifactId&gt;             &lt;version&gt;${kotlin.version}&lt;\/version&gt;         &lt;\/dependency&gt;         &lt;dependency&gt;             &lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt;             &lt;artifactId&gt;kotlin-test&lt;\/artifactId&gt;             &lt;version&gt;${kotlin.version}&lt;\/version&gt;             &lt;scope&gt;test&lt;\/scope&gt;         &lt;\/dependency&gt;     &lt;\/dependencies&gt;      &lt;build&gt;         &lt;plugins&gt;             &lt;plugin&gt;                 &lt;groupId&gt;org.jacoco&lt;\/groupId&gt;                 &lt;artifactId&gt;jacoco-maven-plugin&lt;\/artifactId&gt;                 &lt;version&gt;${build-plugin.jacoco.version}&lt;\/version&gt;                 &lt;executions&gt;                     &lt;!-- Prepares the property pointing to the JaCoCo                     runtime agent which is passed as VM argument when Maven the Surefire plugin                     is executed. --&gt;                     &lt;execution&gt;                         &lt;id&gt;pre-unit-test&lt;\/id&gt;                         &lt;goals&gt;                             &lt;goal&gt;prepare-agent&lt;\/goal&gt;                         &lt;\/goals&gt;                     &lt;\/execution&gt;                     &lt;!-- Ensures that the code coverage report for                     unit tests is created after unit tests have been run. --&gt;                     &lt;execution&gt;                         &lt;id&gt;post-unit-test&lt;\/id&gt;                         &lt;phase&gt;test&lt;\/phase&gt;                         &lt;goals&gt;                             &lt;goal&gt;report&lt;\/goal&gt;                         &lt;\/goals&gt;                     &lt;\/execution&gt;                 &lt;\/executions&gt;             &lt;\/plugin&gt;             &lt;plugin&gt;                 &lt;groupId&gt;org.eluder.coveralls&lt;\/groupId&gt;                 &lt;artifactId&gt;coveralls-maven-plugin&lt;\/artifactId&gt;                 &lt;version&gt;${build-plugin.coveralls.version}&lt;\/version&gt;             &lt;\/plugin&gt;             &lt;plugin&gt;                 &lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt;                 &lt;artifactId&gt;kotlin-maven-plugin&lt;\/artifactId&gt;                 &lt;version&gt;${kotlin.version}&lt;\/version&gt;                 &lt;executions&gt;                     &lt;execution&gt;                         &lt;id&gt;compile&lt;\/id&gt;                         &lt;phase&gt;compile&lt;\/phase&gt;                         &lt;goals&gt;                             &lt;goal&gt;compile&lt;\/goal&gt;                         &lt;\/goals&gt;                     &lt;\/execution&gt;                     &lt;execution&gt;                         &lt;id&gt;test-compile&lt;\/id&gt;                         &lt;phase&gt;test-compile&lt;\/phase&gt;                         &lt;goals&gt;                             &lt;goal&gt;test-compile&lt;\/goal&gt;                         &lt;\/goals&gt;                     &lt;\/execution&gt;                 &lt;\/executions&gt;                 &lt;configuration&gt;                     &lt;jvmTarget&gt;1.8&lt;\/jvmTarget&gt;                 &lt;\/configuration&gt;             &lt;\/plugin&gt;         &lt;\/plugins&gt;     &lt;\/build&gt; &lt;\/project&gt; <\/code><\/pre>\n<p>  \u0433\u0434\u0435 \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0434\u0432\u0430 \u043d\u0430\u0448\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u044f \u2014 <i>frontend<\/i> \u0438 <i>backend<\/i>, \u0430 \u0442\u0430\u043a\u0436\u0435 parent \u2014 <i>spring-boot-starter-parent<\/i>.  <\/div>\n<\/div>\n<p>  <b>\u0412\u0430\u0436\u043d\u043e:<\/b> \u043c\u043e\u0434\u0443\u043b\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u0442\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u2014 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u043f\u043e\u0442\u043e\u043c \u0431\u044d\u043a\u0435\u043d\u0434.<\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"plaintext\">$ mvn install<\/code><\/pre>\n<p>  \u0418, \u0435\u0441\u043b\u0438 \u0432\u0441\u0451 \u0441\u043e\u0431\u0440\u0430\u043b\u043e\u0441\u044c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"plaintext\">$ mvn --project backend spring-boot:run<\/code><\/pre>\n<p>  \u041f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <a href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a> \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0430 Vue.js \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/uj\/ro\/2m\/ujro2mhzhzdj77-krllhk2vthwg.png\"\/><\/p>\n<p>  <a name=\"RESTAPI\"><\/a>  <\/p>\n<h2>REST API<\/h2>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 REST-\u0441\u0435\u0440\u0432\u0438\u0441. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u00abHello, [\u0438\u043c\u044f_\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f]!\u00bb (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u2014 World), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043c\u044b \u0435\u0433\u043e \u0434\u0451\u0440\u043d\u0443\u043b\u0438.<br \/>  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u0438\u0437 \u0447\u0438\u0441\u043b\u0430 \u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u2014 \u043a\u043b\u0430\u0441\u0441, \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 Kotlin \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 <a href=\"https:\/\/kotlinlang.ru\/docs\/reference\/data-classes.html\">\u043a\u043b\u0430\u0441\u0441\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/a>. \u0418 \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"kotlin\">data class Greeting(val id: Long, val content: String)<\/code><\/pre>\n<p>  \u0412\u0441\u0451. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: <\/b>\u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043d\u0435\u0441\u0438\u0442\u044c \u0432\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 <i>\/api<\/i> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <i>@RequestMapping<\/i> \u043f\u0435\u0440\u0435\u0434 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"kotlin\"> import org.springframework.web.bind.annotation.* import com.kotlinspringvue.backend.model.Greeting import java.util.concurrent.atomic.AtomicLong  @RestController @RequestMapping(&quot;\/api&quot;) class BackendController() {       val counter = AtomicLong()       @GetMapping(&quot;\/greeting&quot;)      fun greeting(@RequestParam(value = &quot;name&quot;, defaultValue = &quot;World&quot;) name: String) =      Greeting(counter.incrementAndGet(), &quot;Hello, $name&quot;)  } <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <a href=\"http:\/\/localhost:8080\/api\/greeting?name=Vadim\">http:\/\/localhost:8080\/api\/greeting?name=Vadim<\/a>:<\/p>\n<pre><code class=\"plaintext\">{&quot;id&quot;:1,&quot;content&quot;:&quot;Hello, Vadim&quot;}<\/code><\/pre>\n<p>  \u041e\u0431\u043d\u043e\u0432\u0438\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0443 \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"plaintext\">{&quot;id&quot;:2,&quot;content&quot;:&quot;Hello, Vadim&quot;}<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<br \/>  \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c <i>vue-router<\/i> \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e \u043f\u043e \u00ab\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u00bb (\u043f\u043e \u0444\u0430\u043a\u0442\u0443 \u2014 \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430\u043c \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0443 \u043d\u0430\u0441 \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u0430) \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438:<\/p>\n<pre><code class=\"plaintext\">$ npm install --save vue-router <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c <i>router.js<\/i> \u0432 <i>\/src<\/i> \u2014 \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">router.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@\/components\/HelloWorld' import Greeting from '@\/components\/Greeting'  Vue.use(Router)  export default new Router({    mode: 'history',    routes: [      {        path: '\/',        name: 'Greeting',        component: Greeting      },      {        path: '\/hello-world',        name: 'HelloWorld',        component: HelloWorld      }    ] }) <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b> \u043f\u043e \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c\u0443 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443 (&quot;\/&quot;) \u043d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Greeting.vue, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>  \u0421\u0435\u0439\u0447\u0430\u0441 \u0436\u0435 \u0437\u0430\u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 \u0440\u043e\u0443\u0442\u0435\u0440. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043d\u0435\u0441\u0451\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">main.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import Vue from 'vue' import App from '.\/App.vue' import router from '.\/router'  Vue.config.productionTip = false  new Vue({       router,      render: h =&gt; h(App), }).$mount('#app')  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0417\u0430\u0442\u0435\u043c <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">App.vue<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;      &lt;div id=&quot;app&quot;&gt;            &lt;router-view&gt;&lt;\/router-view&gt;      &lt;\/div&gt; &lt;\/template&gt;  &lt;script&gt; export default {      name: 'app' } &lt;\/script&gt;  &lt;style&gt; &lt;\/style&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f HTTP-\u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c AXIOS:<\/p>\n<pre><code class=\"plaintext\">$ npm install --save axios<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u2014 &quot;\/api&quot;) \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435, \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0438\u0445 \u0432 \u043e\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <i>http-commons.js<\/i>:<\/p>\n<pre><code class=\"javascript\">import axios from 'axios'  export const AXIOS = axios.create({       baseURL: `\/api`  }) <\/code><\/pre>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b> \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439 \u043f\u0440\u0438 \u0432 \u0432\u044b\u0432\u043e\u0434\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c (<i>console.log()<\/i>), \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 <i>package.json<\/i>:<\/p>\n<pre><code class=\"javascript\">&quot;rules&quot;: {       &quot;no-console&quot;: &quot;off&quot; } <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 (\u0432 <i>\/src\/components<\/i>)<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Greeting.vue<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">import {AXIOS} from '.\/http-common'  &lt;template&gt;    &lt;div id=&quot;greeting&quot;&gt;        &lt;h3&gt;Greeting component&lt;\/h3&gt;        &lt;p&gt;Counter: {{ counter }}&lt;\/p&gt;        &lt;p&gt;Username: {{ username }}&lt;\/p&gt;    &lt;\/div&gt; &lt;\/template&gt;  export default {    name: 'Greeting',    data() {        return {            counter: 0,            username: ''        }    },    methods: {        loadGreeting() {            AXIOS.get('\/greeting', { params: { name: 'Vadim' } })            .then(response =&gt; {                this.$data.counter = response.data.id;                this.$data.username = response.data.content;            })            .catch(error =&gt; {                console.log('ERROR: ' + error.response.data);            })        }    },    mounted() {        this.loadGreeting();    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b><\/p>\n<ul>\n<li>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0436\u0435\u043d\u044b \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434<\/li>\n<li>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 (<code>loadGreeting()<\/code>) \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (<i>mounted()<\/i>)<\/li>\n<li>\u043c\u044b \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 AXIOS \u0443\u0436\u0435 \u0441 \u043d\u0430\u0448\u0438\u043c\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0438\u0437 <i>http-common<\/i><\/li>\n<\/ul>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/hb\/7p\/2p\/hb7p2pksym25ceozocomrxo0-fu.png\"\/><br \/>  <a name=\"DB\"><\/a>  <\/p>\n<h2>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 <b>PostgreSQL<\/b> \u0438 <b>Spring Data<\/b>.<\/p>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443:<\/p>\n<pre><code class=\"sql\">CREATE TABLE public.&quot;person&quot;      (           id serial NOT NULL,           name character varying,           PRIMARY KEY (id)      );  <\/code><\/pre>\n<p>  \u0438 \u043d\u0430\u043f\u043e\u043b\u043d\u0438\u043c \u0435\u0451 \u0434\u0430\u043d\u043d\u044b\u043c\u0438:<\/p>\n<pre><code class=\"sql\">INSERT INTO person (name) VALUES ('John'), ('Griselda'), ('Bobby');<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u043c pom.xml \u043c\u043e\u0434\u0443\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430:<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;properties&gt; ... &lt;postgresql.version&gt;42.2.5&lt;\/postgresql.version&gt; ... &lt;\/properties&gt; ... &lt;dependency&gt;      &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;      &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;\/artifactId&gt; &lt;\/dependency&gt; &lt;dependency&gt;      &lt;groupId&gt;org.postgresql&lt;\/groupId&gt;      &lt;artifactId&gt;postgresql&lt;\/artifactId&gt;      &lt;version&gt;${postgresql.version}&lt;\/version&gt; &lt;\/dependency&gt; ... &lt;plugin&gt; &lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt; &lt;artifactId&gt;kotlin-maven-plugin&lt;\/artifactId&gt; &lt;configuration&gt;      &lt;args&gt;           &lt;arg&gt;-Xjsr305=strict&lt;\/arg&gt;      &lt;\/args&gt;      &lt;compilerPlugins&gt;           &lt;plugin&gt;spring&lt;\/plugin&gt;           &lt;plugin&gt;jpa&lt;\/plugin&gt;      &lt;\/compilerPlugins&gt; &lt;\/configuration&gt;  ... &lt;dependency&gt;      &lt;groupId&gt;org.jetbrains.kotlin&lt;\/groupId&gt;      &lt;artifactId&gt;kotlin-maven-noarg&lt;\/artifactId&gt;      &lt;version&gt;${kotlin.version}&lt;\/version&gt; &lt;\/dependency&gt;  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u0444\u0430\u0439\u043b <i>application.properties<\/i> \u043c\u043e\u0434\u0443\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0411\u0414:<\/p>\n<pre><code class=\"plaintext\">spring.datasource.url=${SPRING_DATASOURCE_URL} spring.datasource.username=${SPRING_DATASOURCE_USERNAME} spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}  spring.jpa.generate-ddl=true spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true <\/code><\/pre>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b> \u0432 \u0442\u0430\u043a\u043e\u043c \u0432\u0438\u0434\u0435 \u043f\u0435\u0440\u0432\u044b\u0435 \u0442\u0440\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u044b. \u042f \u043d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0434\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u044b \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430. \u041d\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u0447\u043d\u043e \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u043e\u043d\u0438 \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0443\u0442 \u0432 \u0440\u0443\u043a\u0438 \u043a\u043e\u0432\u0430\u0440\u043d\u044b\u0445 \u0437\u043b\u043e\u0443\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u0438\u043a\u043e\u0432, \u0442\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0434\u0430\u0442\u044c \u0438\u0445 \u044f\u0432\u043d\u043e. <\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c (entity-\u043a\u043b\u0430\u0441\u0441) \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Person.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import javax.persistence.Column import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.GenerationType import javax.persistence.Id import javax.persistence.Table  @Entity @Table (name=&quot;person&quot;) data class Person(         @Id        @GeneratedValue(strategy = GenerationType.AUTO)        val id: Long,         @Column(nullable = false)        val name: String ) <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418 CRUD-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0430\u0448\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Repository.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import com.kotlinspringvue.backend.jpa.Person import org.springframework.stereotype.Repository import org.springframework.data.repository.CrudRepository import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.repository.query.Param  @Repository interface PersonRepository: CrudRepository&lt;Person, Long&gt; {} <\/code><\/pre>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b> \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>findAll()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0435\u043b\u043e \u043f\u0443\u0441\u0442\u044b\u043c.  <\/div>\n<\/div>\n<p>  \u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u043d\u0430\u0448 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">BackendController.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import com.kotlinspringvue.backend.repository.PersonRepository import org.springframework.beans.factory.annotation.Autowired  \u2026   @Autowired lateinit var personRepository: PersonRepository  \u2026   @GetMapping(&quot;\/persons&quot;) fun getPersons() = personRepository.findAll()  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 <a href=\"https:\/\/localhost:8080\/api\/persons\">https:\/\/localhost:8080\/api\/persons<\/a>, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"plaintext\">[{&quot;id&quot;:1,&quot;name&quot;:&quot;John&quot;},{&quot;id&quot;:2,&quot;name&quot;:&quot;Griselda&quot;},{&quot;id&quot;:3,&quot;name&quot;:&quot;Bobby&quot;}]<\/code><\/pre>\n<p>  <a name=\"Authentication\"><\/a>  <\/p>\n<h2>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h2>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u2014 \u0442\u0430\u043a\u0436\u0435 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0433\u0434\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c.<\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/ru.wikipedia.org\/wiki\/JSON_Web_Token\">JWT<\/a> (JSON Web Token).<\/p>\n<p>  <b>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 Basic Authentication?<\/b><\/p>\n<ul>\n<li>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, Basic Authentication \u043d\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u0432\u044b\u0437\u043e\u0432\u0443 \u0443\u0433\u0440\u043e\u0437 \u0434\u0430\u0436\u0435 \u0432 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/li>\n<li>\u041d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432.<\/li>\n<\/ul>\n<p>  <b>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 OAuth \u0438\u0437 <s>\u043a\u043e\u0440\u043e\u0431\u043a\u0438<\/s> Spring Security OAuth?<\/b>  <\/p>\n<ul>\n<li>\u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e OAuth \u0431\u043e\u043b\u044c\u0448\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432.<\/li>\n<li>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0434\u0438\u043a\u0442\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u043e\u0431\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430\u043c\u0438: \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u0430, \u043f\u0440\u0438\u0445\u043e\u0442\u044c\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u043e\u0440\u0430 \u0438 \u0442.\u0434.<\/li>\n<li>\u0415\u0441\u043b\u0438 \u0412\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0442\u043e \u0432 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u043e\u043a\u043e\u0432\u044b\u0440\u044f\u0442\u044c\u0441\u044f \u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e.<\/li>\n<\/ul>\n<p>  <\/p>\n<h3>\u0411\u044d\u043a\u0435\u043d\u0434<\/h3>\n<p>  \u041f\u0443\u0441\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043f\u043e\u043c\u0438\u043c\u043e \u0433\u043e\u0441\u0442\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u0432\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u2014 \u0440\u044f\u0434\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0440\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b: <i>users<\/i> \u2014 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, <i>roles<\/i> \u2014 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0440\u043e\u043b\u044f\u0445 \u0438 <i>users_roles<\/i> \u2014 \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0432\u0443\u0445 \u0442\u0430\u0431\u043b\u0438\u0446.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 roles<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"sql\">CREATE TABLE public.users (      id serial NOT NULL,      username character varying,      first_name character varying,      last_name character varying,      email character varying,      password character varying,      enabled boolean,      PRIMARY KEY (id) );  CREATE TABLE public.roles (      id serial NOT NULL,      name character varying,      PRIMARY KEY (id) );   CREATE TABLE public.users_roles (      id serial NOT NULL,      user_id integer,      role_id integer,      PRIMARY KEY (id) );  ALTER TABLE public.users_roles      ADD CONSTRAINT users_roles_users_fk FOREIGN KEY (user_id)      REFERENCES public.users (id) MATCH SIMPLE      ON UPDATE CASCADE      ON DELETE CASCADE;  ALTER TABLE public.users_roles      ADD CONSTRAINT users_roles_roles_fk FOREIGN KEY (role_id)      REFERENCES public.roles (id) MATCH SIMPLE      ON UPDATE CASCADE      ON DELETE CASCADE;  INSERT INTO roles (name) VALUES ('ROLE_USER'), ('ROLE_ADMIN'); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>   \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Entity-\u043a\u043b\u0430\u0441\u0441\u044b:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">User.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import javax.persistence.*  @Entity @Table(name = &quot;users&quot;) data class User (         @Id        @GeneratedValue(strategy = GenerationType.AUTO)        val id: Long? = 0,         @Column(name=&quot;username&quot;)        var username: String?=null,         @Column(name=&quot;first_name&quot;)        var firstName: String?=null,         @Column(name=&quot;last_name&quot;)        var lastName: String?=null,         @Column(name=&quot;email&quot;)        var email: String?=null,         @Column(name=&quot;password&quot;)        var password: String?=null,         @Column(name=&quot;enabled&quot;)        var enabled: Boolean = false,         @ManyToMany(fetch = FetchType.EAGER)        @JoinTable(                name = &quot;users_roles&quot;,                joinColumns = [JoinColumn(name = &quot;user_id&quot;, referencedColumnName = &quot;id&quot;)],                inverseJoinColumns = [JoinColumn(name = &quot;role_id&quot;, referencedColumnName = &quot;id&quot;)]        )        var roles: Collection&lt;Role&gt;? = null ) <\/code><\/pre>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b> \u0442\u0430\u0431\u043b\u0438\u0446\u044b <i>users<\/i> \u0438 <i>roles<\/i> \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 \u00ab\u043c\u043d\u043e\u0433\u0438\u0435-\u043a\u043e-\u043c\u043d\u043e\u0433\u0438\u043c\u00bb \u2014 \u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u043e\u043b\u0435\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u044f\u0434\u043e\u0432\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440), \u0438 \u043e\u0434\u043d\u043e\u0439 \u0440\u043e\u043b\u044c\u044e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0434\u0435\u043b\u0435\u043d\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. <\/p>\n<p>  <b>\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043a \u0440\u0430\u0437\u043c\u044b\u0448\u043b\u0435\u043d\u0438\u044e:<\/b> \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u0434\u0445\u043e\u0434, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430\u0434\u0435\u043b\u044f\u044e\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f\u043c\u0438 (authorities), \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0440\u043e\u043b\u044c \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u0439. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0435 \u043c\u0435\u0436\u0434\u0443 \u0440\u043e\u043b\u044f\u043c\u0438 \u0438 \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c: <a href=\"https:\/\/www.baeldung.com\/spring-security-granted-authority-vs-role\">Granted Authority Versus Role in Spring Security<\/a>.  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Role.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import javax.persistence.*  @Entity @Table(name = &quot;roles&quot;) data class Role (         @Id        @GeneratedValue(strategy = GenerationType.AUTO)        val id: Long,         @Column(name=&quot;name&quot;)        val name: String  ) <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">UsersRepository.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import java.util.Optional import com.kotlinspringvue.backend.jpa.User import org.springframework.data.repository.CrudRepository import org.springframework.data.repository.query.Param import org.springframework.data.jpa.repository.JpaRepository import javax.transaction.Transactional  interface UserRepository: JpaRepository&lt;User, Long&gt; {     fun existsByUsername(@Param(&quot;username&quot;) username: String): Boolean     fun findByUsername(@Param(&quot;username&quot;) username: String): Optional&lt;User&gt;     fun findByEmail(@Param(&quot;email&quot;) email: String): Optional&lt;User&gt;     @Transactional    fun deleteByUsername(@Param(&quot;username&quot;) username: String)  } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">RolesRepository.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import com.kotlinspringvue.backend.jpa.Role import org.springframework.data.repository.CrudRepository import org.springframework.data.repository.query.Param import org.springframework.data.jpa.repository.JpaRepository  interface RoleRepository : JpaRepository&lt;Role, Long&gt; {     fun findByName(@Param(&quot;name&quot;) name: String): Role } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">pom.xml \u043c\u043e\u0434\u0443\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;dependency&gt;      &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;      &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt; &lt;\/dependency&gt; &lt;dependency&gt;      &lt;groupId&gt;com.fasterxml.jackson.module&lt;\/groupId&gt;      &lt;artifactId&gt;jackson-module-kotlin&lt;\/artifactId&gt; &lt;\/dependency&gt; &lt;dependency&gt;      &lt;groupId&gt;io.jsonwebtoken&lt;\/groupId&gt;      &lt;artifactId&gt;jjwt&lt;\/artifactId&gt;      &lt;version&gt;0.9.0&lt;\/version&gt; &lt;\/dependency&gt; &lt;dependency&gt;      &lt;groupId&gt;io.jsonwebtoken&lt;\/groupId&gt;      &lt;artifactId&gt;jjwt-api&lt;\/artifactId&gt;      &lt;version&gt;0.10.6&lt;\/version&gt; &lt;\/dependency&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438 \u0432 <i>application.properties<\/i>:  <\/p>\n<pre><code class=\"plaintext\">assm.app.jwtSecret=jwtAssmSecretKey assm.app.jwtExpiration=86400 <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441 \u0444\u043e\u0440\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">LoginUser.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> class LoginUser : Serializable {     @JsonProperty(&quot;username&quot;)    var username: String? = null     @JsonProperty(&quot;password&quot;)    var password: String? = null     constructor() {}     constructor(username: String, password: String) {        this.username = username        this.password = password    }     companion object {        private const val serialVersionUID = -1764970284520387975L    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">NewUser.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import com.fasterxml.jackson.annotation.JsonProperty import java.io.Serializable  class NewUser : Serializable {     @JsonProperty(&quot;username&quot;)    var username: String? = null     @JsonProperty(&quot;firstName&quot;)    var firstName: String? = null     @JsonProperty(&quot;lastName&quot;)    var lastName: String? = null     @JsonProperty(&quot;email&quot;)    var email: String? = null     @JsonProperty(&quot;password&quot;)    var password: String? = null     constructor() {}     constructor(username: String, firstName: String, lastName: String, email: String, password: String, recaptchaToken: String) {        this.username = username        this.firstName = firstName        this.lastName = lastName        this.email = email        this.password = password    }     companion object {        private const val serialVersionUID = -1764970284520387975L    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 (\u0441\u0442\u0440\u043e\u043a\u0430):<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">JwtRespons.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import org.springframework.security.core.GrantedAuthority  class JwtResponse(var accessToken: String?, var username: String?, val authorities:      Collection&lt;GrantedAuthority&gt;) {      var type = &quot;Bearer&quot; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">ResponseMessage.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> class ResponseMessage(var message: String?) <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u00abUser Already Exists\u00bb  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">UserAlreadyExistException.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> class UserAlreadyExistException : RuntimeException {       constructor() : super() {}       constructor(message: String, cause: Throwable) : super(message, cause) {}       constructor(message: String) : super(message) {}       constructor(cause: Throwable) : super(cause) {}       companion object {            private val serialVersionUID = 5861310537366287163L       } }  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0440\u043e\u043b\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <i>UserDetailsService<\/i>:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">UserDetailsServiceImpl.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\">  import com.kotlinspringvue.backend.repository.UserRepository  import org.springframework.beans.factory.annotation.Autowired import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.core.userdetails.UsernameNotFoundException import org.springframework.stereotype.Service import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.authority.SimpleGrantedAuthority import java.util.stream.Collectors  @Service class UserDetailsServiceImpl: UserDetailsService {     @Autowired    lateinit var userRepository: UserRepository     @Throws(UsernameNotFoundException::class)    override fun loadUserByUsername(username: String): UserDetails {        val user = userRepository.findByUsername(username).get()                ?: throw UsernameNotFoundException(&quot;User '$username' not found&quot;)         val authorities: List&lt;GrantedAuthority&gt; = user.roles!!.stream().map({ role -&gt; SimpleGrantedAuthority(role.name)}).collect(Collectors.toList&lt;GrantedAuthority&gt;())         return org.springframework.security.core.userdetails.User                .withUsername(username)                .password(user.password)                .authorities(authorities)                .accountExpired(false)                .accountLocked(false)                .credentialsExpired(false)                .disabled(false)                .build()    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 JWT \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430:<br \/>  <b>JwtAuthEntryPoint<\/b> \u2014 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0432\u0435\u0431-\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">JwtAuthEntryPoint.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import javax.servlet.ServletException import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse  import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.security.core.AuthenticationException import org.springframework.security.web.AuthenticationEntryPoint import org.springframework.stereotype.Component  @Component class JwtAuthEntryPoint : AuthenticationEntryPoint {     @Throws(IOException::class, ServletException::class)    override fun commence(request: HttpServletRequest,                          response: HttpServletResponse,                          e: AuthenticationException) {         logger.error(&quot;Unauthorized error. Message - {}&quot;, e!!.message)        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, &quot;Invalid credentials&quot;)    }     companion object {        private val logger = LoggerFactory.getLogger(JwtAuthEntryPoint::class.java)    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <b>JwtProvider<\/b> \u2014 \u0447\u0442\u043e\u0431\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0443:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">JwtProvider.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import io.jsonwebtoken.* import org.springframework.beans.factory.annotation.Autowired import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Value import org.springframework.security.core.Authentication import org.springframework.stereotype.Component import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.authority.SimpleGrantedAuthority import com.kotlinspringvue.backend.repository.UserRepository import java.util.Date   @Component public class JwtProvider {     private val logger: Logger = LoggerFactory.getLogger(JwtProvider::class.java)     @Autowired    lateinit var userRepository: UserRepository     @Value(&quot;\\${assm.app.jwtSecret}&quot;)    lateinit var jwtSecret: String     @Value(&quot;\\${assm.app.jwtExpiration}&quot;)    var jwtExpiration:Int?=0     fun generateJwtToken(username: String): String {        return Jwts.builder()                .setSubject(username)                .setIssuedAt(Date())                .setExpiration(Date((Date()).getTime() + jwtExpiration!! * 1000))                .signWith(SignatureAlgorithm.HS512, jwtSecret)                .compact()    }     fun validateJwtToken(authToken: String): Boolean {        try {            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken)            return true        } catch (e: SignatureException) {            logger.error(&quot;Invalid JWT signature -&gt; Message: {} &quot;, e)        } catch (e: MalformedJwtException) {            logger.error(&quot;Invalid JWT token -&gt; Message: {}&quot;, e)        } catch (e: ExpiredJwtException) {            logger.error(&quot;Expired JWT token -&gt; Message: {}&quot;, e)        } catch (e: UnsupportedJwtException) {            logger.error(&quot;Unsupported JWT token -&gt; Message: {}&quot;, e)        } catch (e: IllegalArgumentException) {            logger.error(&quot;JWT claims string is empty -&gt; Message: {}&quot;, e)        }         return false    }     fun getUserNameFromJwtToken(token: String): String {        return Jwts.parser()                .setSigningKey(jwtSecret)                .parseClaimsJws(token)                .getBody().getSubject()    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <b>JwtAuthTokenFilter<\/b> \u2014 \u0447\u0442\u043e\u0431\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">JwtAuthTokenFilter.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import java.io.IOException  import javax.servlet.FilterChain import javax.servlet.ServletException import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse  import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.web.authentication.WebAuthenticationDetailsSource import org.springframework.web.filter.OncePerRequestFilter  import com.kotlinspringvue.backend.service.UserDetailsServiceImpl  class JwtAuthTokenFilter : OncePerRequestFilter() {     @Autowired    private val tokenProvider: JwtProvider? = null     @Autowired    private val userDetailsService: UserDetailsServiceImpl? = null     @Throws(ServletException::class, IOException::class)    override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {        try {             val jwt = getJwt(request)            if (jwt != null && tokenProvider!!.validateJwtToken(jwt)) {                val username = tokenProvider.getUserNameFromJwtToken(jwt)                 val userDetails = userDetailsService!!.loadUserByUsername(username)                val authentication = UsernamePasswordAuthenticationToken(                        userDetails, null, userDetails.getAuthorities())                authentication.setDetails(WebAuthenticationDetailsSource().buildDetails(request))                 SecurityContextHolder.getContext().setAuthentication(authentication)            }        } catch (e: Exception) {            logger.error(&quot;Can NOT set user authentication -&gt; Message: {}&quot;, e)        }         filterChain.doFilter(request, response)    }     private fun getJwt(request: HttpServletRequest): String? {        val authHeader = request.getHeader(&quot;Authorization&quot;)         return if (authHeader != null && authHeader.startsWith(&quot;Bearer &quot;)) {            authHeader.replace(&quot;Bearer &quot;, &quot;&quot;)        } else null    }     companion object {        private val logger = LoggerFactory.getLogger(JwtAuthTokenFilter::class.java)    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u043d, \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0437\u0430 \u0432\u0435\u0431-\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">WebSecurityConfig.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.beans.factory.annotation.Autowired import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter import org.springframework.security.config.http.SessionCreationPolicy import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder  import com.kotlinspringvue.backend.jwt.JwtAuthEntryPoint import com.kotlinspringvue.backend.jwt.JwtAuthTokenFilter import com.kotlinspringvue.backend.service.UserDetailsServiceImpl   @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) class WebSecurityConfig : WebSecurityConfigurerAdapter() {     @Autowired    internal var userDetailsService: UserDetailsServiceImpl? = null     @Autowired    private val unauthorizedHandler: JwtAuthEntryPoint? = null     @Bean    fun bCryptPasswordEncoder(): BCryptPasswordEncoder {        return BCryptPasswordEncoder()    }     @Bean    fun authenticationJwtTokenFilter(): JwtAuthTokenFilter {        return JwtAuthTokenFilter()    }     @Throws(Exception::class)    override fun configure(authenticationManagerBuilder: AuthenticationManagerBuilder) {        authenticationManagerBuilder                .userDetailsService(userDetailsService)                .passwordEncoder(bCryptPasswordEncoder())    }     @Bean    @Throws(Exception::class)    override fun authenticationManagerBean(): AuthenticationManager {        return super.authenticationManagerBean()    }     @Throws(Exception::class)    override protected fun configure(http: HttpSecurity) {        http.csrf().disable().authorizeRequests()                .antMatchers(&quot;\/**&quot;).permitAll()                .anyRequest().authenticated()                .and()                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)         http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter::class.java)    } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">AuthController.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import javax.validation.Valid import java.util.* import java.util.stream.Collectors  import org.springframework.security.core.Authentication import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.access.prepost.PreAuthorize import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.web.bind.annotation.CrossOrigin import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController  import com.kotlinspringvue.backend.model.LoginUser import com.kotlinspringvue.backend.model.NewUser import com.kotlinspringvue.backend.web.response.JwtResponse import com.kotlinspringvue.backend.web.response.ResponseMessage import com.kotlinspringvue.backend.jpa.User import com.kotlinspringvue.backend.repository.UserRepository import com.kotlinspringvue.backend.repository.RoleRepository import com.kotlinspringvue.backend.jwt.JwtProvider  @CrossOrigin(origins = [&quot;*&quot;], maxAge = 3600) @RestController @RequestMapping(&quot;\/api\/auth&quot;) class AuthController() {     @Autowired    lateinit var authenticationManager: AuthenticationManager     @Autowired    lateinit var userRepository: UserRepository     @Autowired    lateinit var roleRepository: RoleRepository     @Autowired    lateinit var encoder: PasswordEncoder     @Autowired    lateinit var jwtProvider: JwtProvider      @PostMapping(&quot;\/signin&quot;)    fun authenticateUser(@Valid @RequestBody loginRequest: LoginUser): ResponseEntity&lt;*&gt; {         val userCandidate: Optional &lt;User&gt; = userRepository.findByUsername(loginRequest.username!!)         if (userCandidate.isPresent) {            val user: User = userCandidate.get()            val authentication = authenticationManager.authenticate(                    UsernamePasswordAuthenticationToken(loginRequest.username, loginRequest.password))            SecurityContextHolder.getContext().setAuthentication(authentication)            val jwt: String = jwtProvider.generateJwtToken(user.username!!)            val authorities: List&lt;GrantedAuthority&gt; = user.roles!!.stream().map({ role -&gt; SimpleGrantedAuthority(role.name)}).collect(Collectors.toList&lt;GrantedAuthority&gt;())            return ResponseEntity.ok(JwtResponse(jwt, user.username, authorities))        } else {            return ResponseEntity(ResponseMessage(&quot;User not found!&quot;),                    HttpStatus.BAD_REQUEST)        }    }     @PostMapping(&quot;\/signup&quot;)    fun registerUser(@Valid @RequestBody newUser: NewUser): ResponseEntity&lt;*&gt; {         val userCandidate: Optional &lt;User&gt; = userRepository.findByUsername(newUser.username!!)         if (!userCandidate.isPresent) {            if (usernameExists(newUser.username!!)) {                return ResponseEntity(ResponseMessage(&quot;Username is already taken!&quot;),                        HttpStatus.BAD_REQUEST)            } else if (emailExists(newUser.email!!)) {                return ResponseEntity(ResponseMessage(&quot;Email is already in use!&quot;),                        HttpStatus.BAD_REQUEST)            }             \/\/ Creating user's account            val user = User(                    0,                    newUser.username!!,                    newUser.firstName!!,                    newUser.lastName!!,                    newUser.email!!,                    encoder.encode(newUser.password),                    true            )            user!!.roles = Arrays.asList(roleRepository.findByName(&quot;ROLE_USER&quot;))             userRepository.save(user)             return ResponseEntity(ResponseMessage(&quot;User registered successfully!&quot;), HttpStatus.OK)        } else {            return ResponseEntity(ResponseMessage(&quot;User already exists!&quot;),                    HttpStatus.BAD_REQUEST)        }    }     private fun emailExists(email: String): Boolean {        return userRepository.findByUsername(email).isPresent    }     private fun usernameExists(username: String): Boolean {        return userRepository.findByUsername(username).isPresent    }  } <\/code><\/pre>\n<p>  \u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ul>\n<li><b>signin<\/b> \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438, \u0435\u0441\u043b\u0438 \u0434\u0430, \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0435\u0433\u043e \u0440\u043e\u043b\u0438 (\u0432\u0435\u0440\u043d\u0435\u0435, <i>authorities<\/i> \u2014 \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f)<\/li>\n<li>signup \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442, \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 <i>users<\/i> \u0441 \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u043d\u0430 \u0440\u043e\u043b\u044c <i>ROLE_USER<\/i><\/li>\n<\/ul>\n<p>  <\/div>\n<\/div>\n<p>  \u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u043c <i>BackendController<\/i> \u0434\u0432\u0443\u043c\u044f \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438: \u043e\u0434\u0438\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 (\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441 \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f\u043c\u0438 ROLE_USER \u0438 ROLE_ADMIN) \u0438 \u0440\u044f\u0434\u043e\u0432\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e (ROLE_USER).<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">BackendController.kt<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"kotlin\"> import org.springframework.security.access.prepost.PreAuthorize import org.springframework.security.core.Authentication import com.kotlinspringvue.backend.repository.UserRepository import com.kotlinspringvue.backend.jpa.User  \u2026   @Autowired lateinit var userRepository: UserRepository  \u2026   @GetMapping(&quot;\/usercontent&quot;) @PreAuthorize(&quot;hasRole('USER') or hasRole('ADMIN')&quot;) @ResponseBody      fun getUserContent(authentication: Authentication): String {      val user: User = userRepository.findByUsername(authentication.name).get()      return &quot;Hello &quot; + user.firstName + &quot; &quot; + user.lastName + &quot;!&quot; }   @GetMapping(&quot;\/admincontent&quot;) @PreAuthorize(&quot;hasRole('ADMIN')&quot;) @ResponseBody      fun getAdminContent(): String {      return &quot;Admin's content&quot; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<h3>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434<\/h3>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>Home<\/li>\n<li>SignIn<\/li>\n<li>SignUp<\/li>\n<li>AdminPage<\/li>\n<li>UserPage<\/li>\n<\/ul>\n<p>  \u0421 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c (\u0434\u043b\u044f <s>\u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0430<\/s> \u043d\u0430\u0447\u0430\u043b\u0430):<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0428\u0430\u0431\u043b\u043e\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;      &lt;div&gt;      &lt;\/div&gt; &lt;\/template&gt;  &lt;script&gt; &lt;\/script&gt;  &lt;style&gt; &lt;\/style&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c <i>id=\u00ab\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u00bb<\/i> \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 <i>div<\/i> \u0432\u043d\u0443\u0442\u0440\u0438 <i>template<\/i> \u0438 <i>export default {name: \u2018[component_name]\u2019}<\/i> \u0432 <i>script<\/i>.<\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">router.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import Vue from 'vue' import Router from 'vue-router' import Home from '@\/components\/Home' import SignIn from '@\/components\/SignIn' import SignUp from '@\/components\/SignUp' import AdminPage from '@\/components\/AdminPage' import UserPage from '@\/components\/UserPage'  Vue.use(Router)  export default new Router({    mode: 'history',    routes: [      {        path: '\/',        name: 'Home',        component: Home      },      {        path: '\/home',        name: 'Home',        component: Home      },      {        path: '\/login',        name: 'SignIn',        component: SignIn      },      {        path: '\/register',        name: 'SignUp',        component: SignUp      },      {        path: '\/user',        name: 'UserPage',        component: UserPage      },      {        path: '\/admin',        name: 'AdminPage',        component: AdminPage      }    ] }) <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0445 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f <a href=\"https:\/\/vuex.vuejs.org\">Vuex<\/a>. <b>Vuex<\/b> \u2014 \u044d\u0442\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c + \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Vue.js. \u041e\u043d \u0441\u043b\u0443\u0436\u0438\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438, \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u043c\u0438, \u0447\u0442\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<pre><code class=\"plaintext\">$ npm install --save vuex<\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c <i>store<\/i> \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0432 <i>src\/store<\/i>:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">index.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import Vue from 'vue'; import Vuex from 'vuex';  Vue.use(Vuex);  const state = {  token: localStorage.getItem('user-token') || '',  role: localStorage.getItem('user-role') || '',  username: localStorage.getItem('user-name') || '',  authorities: localStorage.getItem('authorities') || '', };  const getters = {  isAuthenticated: state =&gt; {    if (state.token != null && state.token != '') {      return true;    } else {      return false;    }  },  isAdmin: state =&gt; {    if (state.role === 'admin') {      return true;    } else {      return false;    }  },  getUsername: state =&gt; {    return state.username;  },  getAuthorities: state =&gt; {    return state.authorities;  },  getToken: state =&gt; {    return state.token;  } };  const mutations = {  auth_login: (state, user) =&gt; {    localStorage.setItem('user-token', user.token);    localStorage.setItem('user-name', user.name);    localStorage.setItem('user-authorities', user.roles);    state.token = user.token;    state.username = user.username;    state.authorities = user.roles;    var isUser = false;    var isAdmin = false;    for (var i = 0; i &lt; user.roles.length; i++) {      if (user.roles[i].authority === 'ROLE_USER') {        isUser = true;      } else if (user.roles[i].authority === 'ROLE_ADMIN') {        isAdmin = true;      }    }    if (isUser) {      localStorage.setItem('user-role', 'user');      state.role = 'user';    }    if (isAdmin) {      localStorage.setItem('user-role', 'admin');      state.role = 'admin';    }  },  auth_logout: () =&gt; {    state.token = '';    state.role = '';    state.username = '';    state.authorities = [];    localStorage.removeItem('user-token');    localStorage.removeItem('user-role');    localStorage.removeItem('user-name');    localStorage.removeItem('user-authorities');  } };  const actions = {  login: (context, user) =&gt; {    context.commit('auth_login', user)  },  logout: (context) =&gt; {    context.commit('auth_logout');  } };  export const store = new Vuex.Store({  state,  getters,  mutations,  actions }); <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0442\u0443\u0442 \u0435\u0441\u0442\u044c:<\/p>\n<ul>\n<li><b>store<\/b> \u2014 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u2014 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0442\u043e\u043a\u0435\u043d, \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f \u0438 \u0440\u043e\u043b\u044c (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0440\u043e\u043b\u044c \u2014 \u043e\u0431\u0435\u0449\u0430\u044e\u0449\u0430\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u0439 (authorities): \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u2014 \u044d\u0442\u043e \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u0439 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441 \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f\u043c\u0438 <i>admin<\/i> \u0438 <i>user<\/i> \u2014 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440<\/li>\n<li><b>getters<\/b> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0441\u043e\u0431\u044b\u0445 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/li>\n<li><b>mutations<\/b> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/li>\n<li><b>actions<\/b> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0444\u0438\u043a\u0441\u0430\u0446\u0438\u0438 \u043c\u0443\u0442\u0430\u0446\u0438\u0439, \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438<\/li>\n<\/ul>\n<p>  <b>\u0412\u0430\u0436\u043d\u043e:<\/b> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0443\u0442\u0430\u0446\u0438\u0439 (mutations) \u2014 \u044d\u0442\u043e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.  <\/div>\n<\/div>\n<p>  \u0412\u043d\u0435\u0441\u0451\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">main.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import { store } from '.\/store';  ...  new Vue({      router,      store,      render: h =&gt; h(App) }).$mount('#app') <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u0440\u0430\u0437\u0443 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438 \u043e\u043f\u0440\u044f\u0442\u043d\u043e \u0434\u0430\u0436\u0435 \u0432 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e . \u041d\u043e \u044d\u0442\u043e, \u043a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f, \u0434\u0435\u043b\u043e \u0432\u043a\u0443\u0441\u0430, \u0438 \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442:<\/p>\n<pre><code class=\"plaintext\">$ npm install --save bootstrap bootstrap-vue<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Bootstrap \u0432 main.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import BootstrapVue from 'bootstrap-vue' import 'bootstrap\/dist\/css\/bootstrap.css' import 'bootstrap-vue\/dist\/bootstrap-vue.css'  \u2026   Vue.use(BootstrapVue)  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c App:<\/p>\n<ul>\n<li>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u00ab\u0440\u0430\u0437\u043b\u043e\u0433\u0438\u043d\u0438\u0432\u0430\u043d\u0438\u044f\u00bb \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/li>\n<li>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044e \u043d\u0430 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0445\u043e\u0434\u0430 (logout)<\/li>\n<li>\u0411\u0443\u0434\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0438 \u043c\u0435\u043d\u044e \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u00abUser\u00bb \u0438 \u00abLogout\u00bb \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u00abLogin\u00bb \u2014 \u0434\u043b\u044f \u043d\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445<\/li>\n<li>\u0411\u0443\u0434\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 \u00abAdmin\u00bb \u043c\u0435\u043d\u044e \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430\u043c<\/li>\n<\/ul>\n<p>  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 logout()<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">methods: {      logout() {           this.$store.dispatch('logout');           this.$router.push('\/')      } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0438 \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d (template)<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;      &lt;div id=&quot;app&quot;&gt;           &lt;b-navbar style=&quot;width: 100%&quot; type=&quot;dark&quot; variant=&quot;dark&quot;&gt;                &lt;b-navbar-brand id=&quot;nav-brand&quot; href=&quot;#&quot;&gt;Kotlin+Spring+Vue&lt;\/b-navbar-brand&gt;                &lt;router-link to=&quot;\/&quot;&gt;&lt;img height=&quot;30px&quot; src=&quot;.\/assets\/img\/kotlin-logo.png&quot; alt=&quot;Kotlin+Spring+Vue&quot;\/&gt;&lt;\/router-link&gt;                &lt;router-link to=&quot;\/&quot;&gt;&lt;img height=&quot;30px&quot; src=&quot;.\/assets\/img\/spring-boot-logo.png&quot; alt=&quot;Kotlin+Spring+Vue&quot;\/&gt;&lt;\/router-link&gt;                &lt;router-link to=&quot;\/&quot;&gt;&lt;img height=&quot;30px&quot; src=&quot;.\/assets\/img\/vuejs-logo.png&quot; alt=&quot;Kotlin+Spring+Vue&quot;\/&gt;&lt;\/router-link&gt;                &lt;router-link to=&quot;\/user&quot; class=&quot;nav-link text-light&quot; v-if=&quot;this.$store.getters.isAuthenticated&quot;&gt;User&lt;\/router-link&gt;                &lt;router-link to=&quot;\/admin&quot; class=&quot;nav-link text-light&quot; v-if=&quot;this.$store.getters.isAuthenticated && this.$store.getters.isAdmin&quot;&gt;Admin&lt;\/router-link&gt;                &lt;router-link to=&quot;\/register&quot; class=&quot;nav-link text-light&quot; v-if=&quot;!this.$store.getters.isAuthenticated&quot;&gt;Register&lt;\/router-link&gt;                &lt;router-link to=&quot;\/login&quot; class=&quot;nav-link text-light&quot; v-if=&quot;!this.$store.getters.isAuthenticated&quot;&gt;Login&lt;\/router-link&gt;                &lt;a href=&quot;#&quot; class=&quot;nav-link text-light&quot; v-if=&quot;this.$store.getters.isAuthenticated&quot; v-on:click=&quot;logout&quot;&gt;Logout &lt;\/a&gt;           &lt;\/b-navbar&gt;           &lt;router-view&gt;&lt;\/router-view&gt;      &lt;\/div&gt; &lt;\/template&gt;  <\/code><\/pre>\n<p>  <b>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/b> <\/p>\n<ul>\n<li>\u0427\u0435\u0440\u0435\u0437 store \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043e \u0442\u043e\u043c, \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d \u043b\u0438 \u043e\u043d. \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u0430\u043a\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c, \u0430 \u043a\u0430\u043a\u0438\u0435 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c (\u00abv-if\u00bb)<\/li>\n<li>\u0412 \u043f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043b\u043e\u0433\u043e\u0442\u0438\u043f\u044b Kotlin, Spring Boot \u0438 Vue.js, \u043b\u0435\u0436\u0430\u0449\u0438\u0435 \u0432 <i>\/assets\/img\/<\/i>. \u0418\u0445 \u043c\u043e\u0436\u043d\u043e \u043b\u0438\u0431\u043e \u0443\u0431\u0440\u0430\u0442\u044c \u0441\u043e\u0432\u0441\u0435\u043c, \u043b\u0438\u0431\u043e \u0432\u0437\u044f\u0442\u044c \u0438\u0437 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u043c\u043e\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u0441\u0441\u044b\u043b\u043a\u0430 \u0435\u0441\u0442\u044c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438)<\/li>\n<\/ul>\n<p>  <\/div>\n<\/div>\n<p>  \u041e\u0431\u043d\u043e\u0432\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Home.vue<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;    &lt;div div=&quot;home&quot;&gt;        &lt;b-jumbotron&gt;        &lt;template slot=&quot;header&quot;&gt;Kotlin + Spring Boot + Vue.js&lt;\/template&gt;         &lt;template slot=&quot;lead&quot;&gt;          This is the demo web-application written in Kotlin using Spring Boot and Vue.js for frontend        &lt;\/template&gt;         &lt;hr class=&quot;my-4&quot; \/&gt;         &lt;p v-if=&quot;!this.$store.getters.isAuthenticated&quot;&gt;          Login and start        &lt;\/p&gt;         &lt;router-link to=&quot;\/login&quot; v-if=&quot;!this.$store.getters.isAuthenticated&quot;&gt;            &lt;b-button variant=&quot;primary&quot;&gt;Login&lt;\/b-button&gt;        &lt;\/router-link&gt;       &lt;\/b-jumbotron&gt;    &lt;\/div&gt; &lt;\/template&gt;  &lt;script&gt; &lt;\/script&gt;  &lt;style&gt; &lt;\/style&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">SignIn.vue<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;    &lt;div div=&quot;signin&quot;&gt;        &lt;div class=&quot;login-form&quot;&gt;            &lt;b-card              title=&quot;Login&quot;              tag=&quot;article&quot;              style=&quot;max-width: 20rem;&quot;              class=&quot;mb-2&quot;            &gt;            &lt;div&gt;                &lt;b-alert                      :show=&quot;dismissCountDown&quot;                      dismissible                      variant=&quot;danger&quot;                      @dismissed=&quot;dismissCountDown=0&quot;                      @dismiss-count-down=&quot;countDownChanged&quot;                    &gt; {{ alertMessage }}                    &lt;\/b-alert&gt;            &lt;\/div&gt;              &lt;div&gt;                 &lt;b-form-input type=&quot;text&quot; placeholder=&quot;Username&quot; v-model=&quot;username&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;                  &lt;b-form-input type=&quot;password&quot; placeholder=&quot;Password&quot; v-model=&quot;password&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;              &lt;\/div&gt;               &lt;b-button v-on:click=&quot;login&quot; variant=&quot;primary&quot;&gt;Login&lt;\/b-button&gt;               &lt;hr class=&quot;my-4&quot; \/&gt;               &lt;b-button variant=&quot;link&quot;&gt;Forget password?&lt;\/b-button&gt;            &lt;\/b-card&gt;          &lt;\/div&gt;    &lt;\/div&gt; &lt;\/template&gt;  &lt;script&gt; import {AXIOS} from '.\/http-common' export default {    name: 'SignIn',    data() {          return {          username: '',          password: '',          dismissSecs: 5,          dismissCountDown: 0,          alertMessage: 'Request error',      }    },    methods: {      login() {        AXIOS.post(`\/auth\/signin`, {'username': this.$data.username, 'password': this.$data.password})          .then(response =&gt; {            this.$store.dispatch('login', {'token': response.data.accessToken, 'roles': response.data.authorities, 'username': response.data.username});            this.$router.push('\/home')          }, error =&gt; {            this.$data.alertMessage = (error.response.data.message.length &lt; 150) ? error.response.data.message : 'Request error. Please, report this error website owners';            console.log(error)          })          .catch(e =&gt; {            console.log(e);            this.showAlert();          })      },      countDownChanged(dismissCountDown) {          this.dismissCountDown = dismissCountDown      },      showAlert() {          this.dismissCountDown = this.dismissSecs      },    }  } &lt;\/script&gt;  &lt;style&gt; .login-form {    margin-left: 38%;    margin-top: 50px; } &lt;\/style&gt; <\/code><\/pre>\n<p>  \u0427\u0442\u043e \u0442\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:<\/p>\n<ul>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/li>\n<li>\u041e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0435\u0433\u043e \u0432 storage<\/li>\n<li>\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u00ab\u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0435\u00bb \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 Bootstrap \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0448\u0438\u0431\u043a\u0438<\/li>\n<li>\u0415\u0441\u043b\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 <i>\/home<\/i><\/li>\n<\/ul>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">SignUp.vue<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;    &lt;div div=&quot;signup&quot;&gt;        &lt;div class=&quot;login-form&quot;&gt;        &lt;b-card              title=&quot;Register&quot;              tag=&quot;article&quot;              style=&quot;max-width: 20rem;&quot;              class=&quot;mb-2&quot;            &gt;            &lt;div&gt;                &lt;b-alert                      :show=&quot;dismissCountDown&quot;                      dismissible                      variant=&quot;danger&quot;                      @dismissed=&quot;dismissCountDown=0&quot;                      @dismiss-count-down=&quot;countDownChanged&quot;                    &gt; {{ alertMessage }}                    &lt;\/b-alert&gt;            &lt;\/div&gt;            &lt;div&gt;              &lt;b-alert variant=&quot;success&quot; :show=&quot;successfullyRegistered&quot;&gt;                You have been successfully registered! Now you can login with your credentials                &lt;hr \/&gt;                &lt;router-link to=&quot;\/login&quot;&gt;                     &lt;b-button variant=&quot;primary&quot;&gt;Login&lt;\/b-button&gt;                &lt;\/router-link&gt;              &lt;\/b-alert&gt;            &lt;\/div&gt;              &lt;div&gt;                 &lt;b-form-input type=&quot;text&quot; placeholder=&quot;Username&quot; v-model=&quot;username&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;                  &lt;b-form-input type=&quot;text&quot; placeholder=&quot;First Name&quot; v-model=&quot;firstname&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;                  &lt;b-form-input type=&quot;text&quot; placeholder=&quot;Last name&quot; v-model=&quot;lastname&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;                  &lt;b-form-input type=&quot;text&quot; placeholder=&quot;Email&quot; v-model=&quot;email&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;                  &lt;b-form-input type=&quot;password&quot; placeholder=&quot;Password&quot; v-model=&quot;password&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;                 &lt;b-form-input type=&quot;password&quot; placeholder=&quot;Confirm Password&quot; v-model=&quot;confirmpassword&quot; \/&gt;                 &lt;div class=&quot;mt-2&quot;&gt;&lt;\/div&gt;              &lt;\/div&gt;               &lt;b-button v-on:click=&quot;register&quot; variant=&quot;primary&quot;&gt;Register&lt;\/b-button&gt;             &lt;\/b-card&gt;        &lt;\/div&gt;    &lt;\/div&gt; &lt;\/template&gt;  &lt;script&gt; import {AXIOS} from '.\/http-common' export default {    name: 'SignUp',    data () {        return {            username: '',            firstname: '',            lastname: '',            email: '',            password: '',            confirmpassword: '',            dismissSecs: 5,            dismissCountDown: 0,            alertMessage: '',            successfullyRegistered: false        }    },    methods: {        register: function () {            if (this.$data.username === '' || this.$data.username == null) {                this.$data.alertMessage = 'Please, fill &quot;Username&quot; field';                this.showAlert();            } else if (this.$data.firstname === '' || this.$data.firstname == null) {                this.$data.alertMessage = 'Please, fill &quot;First name&quot; field';                this.showAlert();            } else if (this.$data.lastname === '' || this.$data.lastname == null) {                this.$data.alertMessage = 'Please, fill &quot;Last name&quot; field';                this.showAlert();            } else if (this.$data.email === '' || this.$data.email == null) {                this.$data.alertMessage = 'Please, fill &quot;Email&quot; field';                this.showAlert();            } else if (!this.$data.email.includes('@')) {                this.$data.alertMessage = 'Email is incorrect';                this.showAlert();            } else if (this.$data.password === '' || this.$data.password == null) {                this.$data.alertMessage = 'Please, fill &quot;Password&quot; field';                this.showAlert();            } else if (this.$data.confirmpassword === '' || this.$data.confirmpassword == null) {                this.$data.alertMessage = 'Please, confirm password';                this.showAlert();            } else if (this.$data.confirmpassword !== this.$data.password) {                this.$data.alertMessage = 'Passwords are not match';                this.showAlert();            } else {                var newUser = {                    'username': this.$data.username,                    'firstName': this.$data.firstname,                    'lastName': this.$data.lastname,                    'email': this.$data.email,                    'password': this.$data.password                };                AXIOS.post('\/auth\/signup', newUser)                .then(response =&gt; {                    console.log(response);                    this.successAlert();                }, error =&gt; {                    this.$data.alertMessage = (error.response.data.message.length &lt; 150) ? error.response.data.message : 'Request error. Please, report this error website owners'                    this.showAlert();                })                 .catch(error =&gt; {                    console.log(error);                    this.$data.alertMessage = 'Request error. Please, report this error website owners';                    this.showAlert();                 });            }        },        countDownChanged(dismissCountDown) {            this.dismissCountDown = dismissCountDown        },        showAlert() {            this.dismissCountDown = this.dismissSecs        },        successAlert() {            this.username = '';            this.firstname = '';            this.lastname = '';            this.email = '';            this.password = '';            this.confirmpassword = '';            this.successfullyRegistered = true;        }    } } &lt;\/script&gt;  &lt;style&gt; .login-form {    margin-left: 38%;    margin-top: 50px; } &lt;\/style&gt; <\/code><\/pre>\n<p>  \u0427\u0442\u043e \u0442\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:<\/p>\n<ul>\n<li>\u0414\u0430\u043d\u043d\u044b\u0435 \u0441 \u0444\u043e\u0440\u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/li>\n<li>\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u043e\u0442 Bootstrap \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 <\/li>\n<li>\u0415\u0441\u043b\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0448\u043b\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u0432\u044b\u0432\u043e\u0434\u0438\u043c Bootstrap-\u043e\u0432\u0441\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f<\/li>\n<li>\u041f\u0435\u0440\u0435\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u0435\u0439<\/li>\n<\/ul>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">UserPage.vue<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;    &lt;div div=&quot;userpage&quot;&gt;        &lt;h2&gt;{{ pageContent }}&lt;\/h2&gt;    &lt;\/div&gt; &lt;\/template&gt;  &lt;script&gt; import {AXIOS} from '.\/http-common' export default {    name: 'UserPage',    data() {        return {            pageContent: ''        }    },    methods: {        loadUserContent() {            const header = {'Authorization': 'Bearer ' + this.$store.getters.getToken};            AXIOS.get('\/usercontent', { headers: header })            .then(response =&gt; {                this.$data.pageContent = response.data;            })            .catch(error =&gt; {                console.log('ERROR: ' + error.response.data);            })        }    },    mounted() {        this.loadUserContent();    } } &lt;\/script&gt;  &lt;style&gt; &lt;\/style&gt; <\/code><\/pre>\n<p>  \u0427\u0442\u043e \u0442\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:  <\/p>\n<ul>\n<li>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b<\/li>\n<li>\u0412\u043c\u0435\u0441\u0442\u0435 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0442\u043e\u043a\u0435\u043d, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u0439\u0441\u044f \u0432 storage<\/li>\n<li>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u044b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435<\/li>\n<\/ul>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Admin.vue<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"xml\">&lt;template&gt;    &lt;div div=&quot;adminpage&quot;&gt;        &lt;h2&gt;{{ pageContent }}&lt;\/h2&gt;    &lt;\/div&gt; &lt;\/template&gt;  &lt;script&gt; import {AXIOS} from '.\/http-common' export default {    name: 'AdminPage',    data() {        return {            pageContent: ''        }    },    methods: {        loadUserContent() {            const header = {'Authorization': 'Bearer ' + this.$store.getters.getToken};            AXIOS.get('\/admincontent', { headers: header })            .then(response =&gt; {                this.$data.pageContent = response.data;            })            .catch(error =&gt; {                console.log('ERROR: ' + error.response.data);            })        }    },    mounted() {        this.loadUserContent();    } } &lt;\/script&gt;  &lt;style&gt; &lt;\/style&gt; <\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0451 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u0438 \u0432 <i>UserPage<\/i>.  <\/div>\n<\/div>\n<p>  <\/p>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>  \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/vj\/n1\/sx\/vjn1sxqgh21twatqxdnwdsax-da.png\"\/><\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ty\/xq\/rd\/tyxqrdt_bdanmy9ughcq050i5q8.png\"\/><\/p>\n<p>  <b>\u0412\u0430\u0436\u043d\u043e:<\/b> \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u0441\u0435 \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u2014 \u043e\u0431\u044b\u0447\u043d\u044b\u0435. \u0414\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u043e\u043c\u0443 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 \u0435\u0433\u043e \u043f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f:<\/p>\n<pre><code class=\"sql\">INSERT INTO users_roles (user_id, role_id) VALUES (1, 2); <\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c:<\/p>\n<ol>\n<li>\u0417\u0430\u0439\u0434\u0451\u043c \u043f\u043e\u0434 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 User:\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/7-\/hl\/tu\/7-hltu0rtm5vigbfhq3hmhin0ri.png\"\/><\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 Admin:\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/se\/hr\/lu\/sehrlu8m5npgbdf1dtotvukfk-g.png\"\/><\/li>\n<li>\u0412\u044b\u0439\u0434\u0435\u043c \u0438\u0437 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0441\u043a\u043e\u0439 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438<\/li>\n<li>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b User<\/li>\n<li>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f REST API: <a href=\"http:\/\/localhost:8080\/api\/admincontent\">http:\/\/localhost:8080\/api\/admincontent<\/a><\/li>\n<\/ol>\n<p>  <\/p>\n<pre><code class=\"plaintext\">ERROR 77100 --- [nio-8080-exec-2] c.k.backend.jwt.JwtAuthEntryPoint : Unauthorized error. Message - Full authentication is required to access this resource <\/code><\/pre>\n<p>  <a name=\"WaysToImprove\"><\/a>  <\/p>\n<h2>\u041f\u0443\u0442\u0438 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f<\/h2>\n<p>  \u0412\u043e\u043e\u0431\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u0438\u0445 \u0432 \u043b\u044e\u0431\u043e\u043c \u0434\u0435\u043b\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e. \u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044e \u0441\u0430\u043c\u044b\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435:<\/p>\n<ul>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 Gradle (\u0435\u0441\u043b\u0438 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u043e \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435\u043c)<\/li>\n<li>\u0421\u0440\u0430\u0437\u0443 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 (\u044d\u0442\u043e \u0443\u0436\u0435, \u0431\u0435\u0437 \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u044f, \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430)<\/li>\n<li>\u0421 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c CI\/CD Pipeline: \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0442\u044c \u043a\u043e\u0434 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u0438 \u0434\u0435\u043f\u043b\u043e\u0439<\/li>\n<li>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c PUT \u0438 DELETE \u0437\u0430\u043f\u0440\u043e\u0441\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0443\u0447\u0451\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439)<\/li>\n<li>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044e\/\u0434\u0435\u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044e \u0443\u0447\u0430 \u044e\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439<\/li>\n<li>\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c local storage \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u2014 \u044d\u0442\u043e \u043d\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e<\/li>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c OAuth<\/li>\n<li>\u0412\u0435\u0440\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u0440\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0442\u0443 \u043e\u0442 \u0441\u043f\u0430\u043c\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, reCAPTCHA<\/li>\n<\/ul>\n<p>  <a name=\"Links\"><\/a>  <\/p>\n<h2>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h2>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/vaadimblog.blogspot.com\/p\/kotlin-spring-boot-vuejs.html\">\u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e<\/a>, \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435, \u0433\u0434\u0435 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Heroku, reCAPTCHA \u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043f\u043e\u0447\u0442\u043e\u0439. \u041d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u0437\u0430\u0442\u043e \u0441 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u043c\u0438<\/li>\n<li><a href=\"https:\/\/github.com\/DrLeprechaun\/kotlin-spring-vue\">GitHub \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a><\/li>\n<li><a href=\"https:\/\/kotlin-spring-vue-demo.herokuapp.com\">\u0413\u043e\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/jonashackt\/spring-boot-vuejs\">\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u043f\u0430\u0441\u0438\u0431\u043e<\/a> \u2014 \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u043b \u043c\u0435\u043d\u044f \u043d\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/li>\n<li><a href=\"https:\/\/auth0.com\/blog\/vuejs-spring-boot-kotlin-and-graphql-building-modern-apps-part-1\/\">Vue.js, Spring Boot, Kotlin, and GraphQL: Building Modern Apps<\/a><\/li>\n<li><a href=\"https:\/\/www.baeldung.com\">Baeldung \u2014 Java, Spring and Web Development tutorials<\/a><\/li>\n<li><a href=\"https:\/\/www.baeldung.com\/spring-boot-vue-js\">Vue.js Frontend with a Spring Boot Backend<\/a><\/li>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/tutorials\/spring-boot-restful.html\">Creating a RESTful Web Service with Spring Boot (Kotlin)<\/a><\/li>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/reference\/data-classes.html\">Data Classes (Kotlin)<\/a><\/li>\n<li><a href=\"https:\/\/www.baeldung.com\/kotlin-data-classes\">Data Classes in Kotlin<\/a><\/li>\n<li><a href=\"https:\/\/logrocket.com\/blog\/jwt-authentication-best-practices\/\">JWT authentication: When and how to use it<\/a><\/li>\n<li><a href=\"https:\/\/vuex.vuejs.org\">What is Vuex?<\/a><\/li>\n<li><a href=\"https:\/\/itnext.io\/managing-state-in-vue-js-with-vuex-f036fd71f432\">Managing state in Vue.js with Vuex<\/a><\/li>\n<\/ul>\n<\/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\/467161\/\"> https:\/\/habr.com\/ru\/post\/467161\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c, \u0434\u043e\u0440\u043e\u0433\u0438\u0435 \u043e\u0431\u0438\u0442\u0430\u0442\u0435\u043b\u0438 \u0425\u0430\u0431\u0440\u0430\u0445\u0430\u0431\u0440\u0430!<\/p>\n<p>  \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u043c\u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u044b\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043f\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u0422\u043e \u0435\u0441\u0442\u044c, \u044f \u0431\u044b\u043b \u0432\u043e\u043b\u0435\u043d \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0435\u043a \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439 \u043d\u0430 \u0441\u0432\u043e\u0451 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435. \u041f\u043e\u0442\u043e\u043c\u0443 \u043d\u0435 \u043f\u0440\u0435\u043c\u0438\u043d\u0443\u043b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u00ab\u043f\u043e\u0449\u0443\u043f\u0430\u0442\u044c\u00bb <s>\u043c\u043e\u0434\u043d\u044b\u0435, \u043c\u043e\u043b\u043e\u0434\u0451\u0436\u043d\u044b\u0435<\/s> \u043c\u043d\u043e\u0433\u043e\u043e\u0431\u0435\u0449\u0430\u044e\u0449\u0438\u0435, \u043d\u043e \u043c\u0430\u043b\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u043c\u043d\u0435 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 <b>Kotlin<\/b> \u0438 <b>Vue.js<\/b>, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 <b>Spring Boot<\/b> \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0438\u0432 \u0432\u0441\u0451 \u044d\u0442\u043e \u043d\u0430 \u043d\u0435\u0437\u0430\u043c\u044b\u0441\u043b\u043e\u0432\u0430\u0442\u043e\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.   <\/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-294612","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/294612","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=294612"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/294612\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=294612"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=294612"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=294612"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}