SC24EP02 Разработка REST-сервиса - Разработка проектов со Spring

  Рет қаралды 11,240

Уголок сельского джависта

Уголок сельского джависта

Күн бұрын

Пікірлер: 121
@СергейЛымарь-э2н
@СергейЛымарь-э2н 8 ай бұрын
Я - человек простой. Вижу видео от Саши - ставлю лайк) спасибо за туториал)
@Edu-wi3il
@Edu-wi3il 8 ай бұрын
Спасибо! Было полезно узнать про классы ProblemDetail и RestClient, как альтернатива RestTemplate
@akalavan5395
@akalavan5395 7 ай бұрын
Второй день, второе видео пройдено, всё очень интересно и познавательно.
@Devivl
@Devivl 8 ай бұрын
Саш, как всегда, жирный лайк! Судя по гитхабу на выходе серьезный проект получается. Отличная практика. От души спасибо.
@tekkaruwer8789
@tekkaruwer8789 7 ай бұрын
Очень крутое качество кода, зная все это, все равно очень полезно смотреть лекции, хотя бы просто для того, чтобы поучиться так грамотно писать) ❤
@МихаилМихаил-ф7у
@МихаилМихаил-ф7у Ай бұрын
Отличный материал! Спасибо огромное!
@Константин-ы9к
@Константин-ы9к 7 ай бұрын
Наконец-то осилил до конца. Смотрю дальше. Отличный материал.
@itmaker1821
@itmaker1821 7 ай бұрын
Очень классный гайд, всё на высоте, спасибо
@Константин-ы9к
@Константин-ы9к 8 ай бұрын
Отличное начало. Супер. Как всегда качественный профессиональный материал.
@ejatohvee
@ejatohvee 3 ай бұрын
Спасибо вам большое за такие уроки. После получения в университете и на просторах интернета знаний очень помогает разложить все по полочкам, а также узнать что-то новое. Начинаю первый полностью свой проект по вашему курсу!
@АлександрЛапин-б7р
@АлександрЛапин-б7р 4 ай бұрын
Огромное спасибо! Смотрится на одном дыхании!
@alekseizhitenev6020
@alekseizhitenev6020 4 ай бұрын
большое спасибо!) смотрится прям легко
@timur.k
@timur.k 4 ай бұрын
Спасибо за отличный урок!
@vladislavchaplin894
@vladislavchaplin894 8 ай бұрын
ОЧень годно, спасибо большое, что делитесь
@artemv5226
@artemv5226 8 ай бұрын
Эх, жаль, что цикла этого не было еще, когда ваял свой первый проект:) От прыжков по многочисленным граблям бы избавился. Спасибо за труды!
@АлександрТяпкин-п2ц
@АлександрТяпкин-п2ц 8 ай бұрын
Спасибо за новый урок
@Lina-sl9js
@Lina-sl9js 4 ай бұрын
Спасибо за видео! ) Хотела заметить, что для формирования ResponseEntity удобнее (как мне кажется) пользоваться готовым функционалом Spring Hateoas! ;)
@shurik_codes
@shurik_codes Ай бұрын
Ну, такое)
@shluhogon_42
@shluhogon_42 8 ай бұрын
Благодарю!
@ровойт
@ровойт 8 ай бұрын
спасибо большое
@partiec6065
@partiec6065 5 ай бұрын
Спасибо, братиш 🙂🤘
@webicode
@webicode 6 ай бұрын
СПАСИБО за труд !!!
@FrendlyFrend-g6j
@FrendlyFrend-g6j 8 ай бұрын
Спасибо Александр и все таки URL и URI это не одно и тоже:)
@ГенрихАвдеев-ь9з
@ГенрихАвдеев-ь9з 8 ай бұрын
Привет. Отличный курс, большая работа проделана, виден системный подход. Большой лайк за труды. Вопрос по блоку возвращения ResponseEntity при обработке ошибок. Заметил, что статус ошибки заполняется два раза, сначала в ProblemDetail, потом как статус ResponseEntity, а problemDetail возвращается в body. В этом есть сакральный смысл (спрашиваю, т.к. есть ощущение, что просто так ничего в роликах не говорится и не делается)? Я у себя сделал вариант ResponseEntity .of(problemDetails) .build() Вроде работает ))
@shurik_codes
@shurik_codes 8 ай бұрын
Да, действительно работает, я упустил этот момент
@romanovichihin2429
@romanovichihin2429 5 ай бұрын
Комент для продвижения
@aleksey2793
@aleksey2793 3 ай бұрын
8:00 - Когда речь идет про три разных варианта класса данных Product (для представления, базы данных и самого объекта), то нужны некие преобразователи из одного варианта в другой? Их реализовывать в контроллере и репозитории соответственно? Это получается что-то вроде адаптеров в гексагональной архитектуре?
@shurik_codes
@shurik_codes 3 ай бұрын
По идее да, должны быть преобразователи, можно преобразования писать прямо в контроллере и репозитори, можно выносить в отдельные классы. Да, контроллер и репозиторий являются адаптерами в контексте гексагональной архитектуры
@o.sandman
@o.sandman 8 ай бұрын
Александр, спасибо за видео, с интересом посмотрел. Печалька, что такой полезный класс как ProblemDetail сделали только в 6 версии Spring, не могу его использовать - у нас на проекте 5-я версия)
@shurik_codes
@shurik_codes 8 ай бұрын
Самостоятельно описать)
@_mapc8763
@_mapc8763 21 күн бұрын
Здраствуйте! 29:45 Не пойму смысл if (bindingResult.hasErrors()) { if (bindingResult instanceof BindException exception) { throw exception; } else { throw new BindException(bindingResult); } } Почему нельзя сократить до if (bindingResult.hasErrors()) { throw new BindException(bindingResult); }
@shurik_codes
@shurik_codes 20 күн бұрын
В целом можно и так сделать, да, но зачем создавать новое исключение, если можно выбросить уже существующее?
@_mapc8763
@_mapc8763 20 күн бұрын
@@shurik_codes Понял, спасибо!
@alexandr6055
@alexandr6055 8 ай бұрын
Заметил у вас интересную штуку. Вот к примеру в методе мы не находим по id и в блоке if кидаем исключение. Затем отдельный метод "ловец" этого исключения. А не проще ли не кидать эксепшн, а просто в блоке иф делать обращение к методу "ловцу"? Как-то выглядит более прямой такая логика, нет?
@shurik_codes
@shurik_codes 8 ай бұрын
Я немного ненаглядно показал, да, но предполагается, что в реальных условиях исключение может возникнуть в нескольких местах, и чтобы везде не писать обработку на месте, таким образом дублируя код, гораздо удобнее написать метод с @ExceptionHandler
@alexandr6055
@alexandr6055 8 ай бұрын
Понял, спасибо ​@@shurik_codes
@ji1ja
@ji1ja 8 ай бұрын
NoSuchElementException выбрасывается в нескольких местах, и будет странно если в одном мы будем выбрасывать в другом обращаться к методу, тем более, что оно выбрасывается в сервисе и мы оттуда не можем обращаться к контроллеру. Вообще по хорошему создать нужно какой-нибудь рест контроллер эдвайс и там уже хэндлить
@viewer_evgeniy
@viewer_evgeniy 7 ай бұрын
Я верно понимаю, что ResponseEntity по сути нужен только, если требуется кастомизация статуса? Если достаточно каких-то дефолтных (на успех это 200, а на ошибки не помню, что там спринг по умолчанию использует), то соответственно из методов контроллеров возвращаем просто нужный нам объект?
@shurik_codes
@shurik_codes 7 ай бұрын
В целом да
@oleksandrhavryush9250
@oleksandrhavryush9250 7 ай бұрын
Спасибо автору за отличный материал. У меня вопрос: объясните пожалуйста почему сервис и менеджер крутятся на разных портах, если мы в ямл файлах прописали один порт? Почему в постман мы посылаем запросы на порт 8081, а в браузере видим порт 8080? Вот этот момент до сих пор понять не могу.
@shurik_codes
@shurik_codes 7 ай бұрын
В сервисе каталога порт - 8081 github.com/alex-kosarev/sc24/blob/SC24EP02-servlet-api-rest-service/catalogue-service/src/main/resources/application-standalone.yaml
@tusman4ik
@tusman4ik 8 ай бұрын
❤)
@pavelgurevich4018
@pavelgurevich4018 6 ай бұрын
Всем привет, подскажите почему в методе createProduct надо возвращать заголовок ?
@Hocorend
@Hocorend 6 ай бұрын
Спасибо за видео, уже становится сложнее всё запоминать из-за большой плотности информации, хоть и не впервой это вижу. Хоть уроков уже много выпущено, хотелось бы попросить озвучивать горячие клавиши, используемые при разработке, чтобы научиться так же быстро управляться с кодом, и прочие фишки IDEA . Ещё хотел уточнить, DTO не создаются для упрощения уроков и отсутствия работы с БД(на данный момент) или их создание устаревшая практика?
@shurik_codes
@shurik_codes 6 ай бұрын
Исключительно для упрощения уроков, на практике DTO нужны
@artyomzolotoverkhov8468
@artyomzolotoverkhov8468 5 ай бұрын
Чтобы лучше запоминать рекомендую повторять за Александром в своей IDE
@Hocorend
@Hocorend 5 ай бұрын
@@artyomzolotoverkhov8468 Это-то я несомненно делаю, просто смотреть вообще бестолку) Но по ему опыту, информация более менее железно укладывается только через пол года повторений
@СергейЗаря-х9ь
@СергейЗаря-х9ь 2 ай бұрын
Добрый день, с чем связан выбор в пользу record, вместо стандартного dto?
@shurik_codes
@shurik_codes 2 ай бұрын
Потому что record, на мой взгляд, идеальны для DTO
@trfguiikbfdyjkk
@trfguiikbfdyjkk 5 ай бұрын
Здравствуйте, а зачем нужна проверка является ли BindingResult экземпляром BindException, нельзя сразу выбросить BindException(bindingResult)?
@shurik_codes
@shurik_codes 5 ай бұрын
У BindingResult есть и другие реализации, не являющиеся исключением
@РусланСаматов-ы4с
@РусланСаматов-ы4с 7 ай бұрын
Спасибо за ролик! С первого ролика не совсем понял, может кто нибудь объяснить почему мы используем NewPayload и UpdatePayload? Можно же вроде Product передавать?
@shurik_codes
@shurik_codes 7 ай бұрын
Принцип единственной ответственности, по крайней мере одна из его трактовок. При создании и изменении объекта мы не задаём все свойства, из которых объект состоит. В добавок в разных операциях мы можем изменять разные наборы данных. На практике для каждой операции лучше иметь отдельный класс, описывающий полезную нагрузку.
@РусланСаматов-ы4с
@РусланСаматов-ы4с 7 ай бұрын
@@shurik_codes Спасибо понял. А правильно ли я понимаю, что почти в таком же контексте(для не изменения сущности, и отделения ее) для таких целей при работе с базами данных используют DTO?
@shurik_codes
@shurik_codes 7 ай бұрын
@@РусланСаматов-ы4с да
@non_holy6286
@non_holy6286 2 ай бұрын
Александр, привет! 22:40 тут не совсем понял в какой момент заполняется аргумент product на 27 строке, и в какой момент отработает метод на строке 21?
@non_holy6286
@non_holy6286 2 ай бұрын
Подебажил, как будто бы вызывается перед тем, как вызвать метод контроллера, но как это работает не понятно)
@shurik_codes
@shurik_codes Ай бұрын
Метод getProduct (21 строка) вызывается перед findProduct (27 строка), его задача - добавить в модель товар, чтобы потом из модели передать товар в аргументы метода findProduct
@aleksey2793
@aleksey2793 4 ай бұрын
А как такие rest-сервисы масштабируются? Просто запускается еще один экземпляр, и нагрузка распределяется балансировщиком? Такая архитектура сервиса - хорошее решение для написания масштабируемых приложений?
@shurik_codes
@shurik_codes 4 ай бұрын
Да, масштабирование происходит примерно по такой схеме. Архитектура тоже вполне пойдёт
@sdhfdsfh2413
@sdhfdsfh2413 8 ай бұрын
Привет, а как можно сделать, чтобы можно было скрывать левую боковую панель по бинду??
@shurik_codes
@shurik_codes 8 ай бұрын
Alt+1
@ji1ja
@ji1ja 8 ай бұрын
Привет, спасибо за видос) Вопрос такой, почему просто не отлавливать в глобальном эксэпшн хэндлере ошибки валидации без BindingResult'а в контроллере?
@shurik_codes
@shurik_codes 8 ай бұрын
А откуда взяться исключению?
@ji1ja
@ji1ja 8 ай бұрын
@@shurik_codes у спринга есть MethodArgumentNotValidException который экстендит bindexception и выбрасывается при фейле валидации
@rainrainov4495
@rainrainov4495 5 ай бұрын
@@shurik_codes Добрый день. Через хэндлер отлавливается, просто нужно в настройках ProblemDetail подключить. К сожалению для ошибок валидации все равно придется в хендлере из BindingResult вытаскивать. Жаль стандарт не включает ошибки валидации и при тесте приходится заморачиваться с проверкой проперти, хотя можно просто расширить ProblemDetail, что мне кажется предпочтительней.
@hurricane-rus
@hurricane-rus 4 ай бұрын
@@shurik_codes Если у нас провалится валидация из Payload, вылетит MethodArgumentNotValidException - его как раз и будем перехватывать. Думаю, не стали заморачиваться с хэндлерами просто для экономии времени, а так конечно, ошибки (и тем более их обработку) обычно не ловят в контроллерах
@НатаСметанова
@НатаСметанова 7 ай бұрын
Добрый день! Спасибо за курс. У меня проблема - вроде делаю все также, но вылезает ошибка MissingPathVariableException: Required URI template variable 'productId' for method parameter type Integer is not present
@shurik_codes
@shurik_codes 7 ай бұрын
Какой путь и как объявлен аргумент метода, получающий переменную пути?
@НатаСметанова
@НатаСметанова 7 ай бұрын
Появляется на страницах catalogue/products/list и catalogue/products/create, где в пути вообще нет productId
@shurik_codes
@shurik_codes 7 ай бұрын
А в контроллере есть метод с аннотацией @ModelAttribute и аргументом, отмеченным аннотацией @PathVariable?
@НатаСметанова
@НатаСметанова 7 ай бұрын
@@shurik_codes Спасибо, поняла ))
@ровойт
@ровойт 6 ай бұрын
а если у вас будет время можете показать какой-то реальный пример из жизни несложного проекта на спрингу
@SlevySoddik
@SlevySoddik 8 ай бұрын
вопрос по структуре методов контроллера с ветвлениями, зачем блок else если в блоке if есть return? верификация в контроллере не нарушает SRP?
@shurik_codes
@shurik_codes 8 ай бұрын
Про метод с ветвлениями - не понял о каком методе идёт речь. Блок else затем, чтобы выполнить код, если условие в if не сработало. Валидация выполняется не в контроллере, а в валидаторе силами фреймворка, контроллер обрабатывает результат валидации, так что никакого нарушения SRP здесь нет.
@SlevySoddik
@SlevySoddik 8 ай бұрын
@@shurik_codes про if имел ввиду такую структуру: if(somePredicate){ return x; } return anotherX; таким образом else нет, и порядок обработки не теряется, но это, наверно, больше к код стайлу относится.
@shurik_codes
@shurik_codes 8 ай бұрын
@@SlevySoddik а, ну так да, можно делать
@ИванГубарев-к4ь
@ИванГубарев-к4ь 5 ай бұрын
Доброго времени суток! Подскажите, на JDK17 этот код должен работать?
@shurik_codes
@shurik_codes 5 ай бұрын
Не тестировал, но вроде ничего из JDK 18+ в проекте не используется
@ЭдуардВолков-к7л
@ЭдуардВолков-к7л 5 ай бұрын
Привет, ты указываешь active profile - standalone на 59 минуте, как это сделать если версия community ?
@shurik_codes
@shurik_codes 5 ай бұрын
spring.profiles.active в application.yml
@ЭдуардВолков-к7л
@ЭдуардВолков-к7л 5 ай бұрын
@@shurik_codes то есть в файле application-standalone.yaml прописать строчку spring: profile: active ------------- да?
@shurik_codes
@shurik_codes 5 ай бұрын
@@ЭдуардВолков-к7л не, в файле application.yml, ну или при запуске mvn spring-boot:run -Dspring.profiles.active=standalone но это не точно
@GyMaNoiD-ql3wb
@GyMaNoiD-ql3wb 5 ай бұрын
@@ЭдуардВолков-к7л С помощью терминала через cd заходите в директорию вашего сервиса("cd catalogue-service", например) и в терминале пишете: mvn spring-boot:run -D"spring-boot.run.profiles"=standalone
@svyatoiambrozii
@svyatoiambrozii 6 ай бұрын
Вам как профессиональному разработчику приятнее с REST или MVC работать? Где проще разработка выходит?)
@shurik_codes
@shurik_codes 6 ай бұрын
С классическими веб-приложениями я работаю крайне редко (не знаю уж, к счастью или к сожалению), REST в моей практике занимает существенно больше времени. В целом мне без разницы с чем работать)
@denisskyter4526
@denisskyter4526 8 ай бұрын
Я так понял restclient в manager-app это для взаимодействия с сервисом каталога что бы с клиента туда кидать запросы
@shurik_codes
@shurik_codes 8 ай бұрын
да
@Пумпурумм
@Пумпурумм 24 күн бұрын
Классные видео, спору нет, но не разделяю шквал похвалы, тк задача автора не только всё детально показать, но и доходчиво объяснить. На мой взгляд данное видео местами сложновато для понимания новичками, и вызывает не мало вопросов, это на фоне других обучающих материалов по спрингу, где объясняют на примерах необходимого минимума.
@ИльяКалендарев-е8ж
@ИльяКалендарев-е8ж 8 ай бұрын
Спасибо за видео. Но у меня есть вопрос) в Вашем примере объект UpdateProductPayload содержит всего два свойства. Предположим этих свойств гораздо больше и содержать новые данные для обновления могут не все т.е. допускается null значение. Как тогда оптимальней всего реализовать обновление объекта, может есть вариант, как избежать ручной проверки данных в каждом из свойств объекта?
@shurik_codes
@shurik_codes 8 ай бұрын
Bean Validation)
@ИльяКалендарев-е8ж
@ИльяКалендарев-е8ж 8 ай бұрын
@@shurik_codes Не очень понимаю, как это поможет если свойство может быть null, т.е. это значение разрешено, то при сохранении null заменит уже имеющееся значение в бд. А задача сохранить только те значения которые не null.
@shurik_codes
@shurik_codes 8 ай бұрын
А, вот про что вопрос. Есть два варианта: 1. Описывать структуры данных для каждого варианта изменения, чтобы они содержали только те свойства, которые могут быть изменены 2. Для каждого варианта изменения описывать свой запрос к БД (специфично для SQL, JPA, Spring Data и т.д.)
@javac
@javac 8 ай бұрын
Просто мысль вслух: можно попробовать @DynamicUpdate на сущность поставить, а при маппинге из payload в сущность null-ы пропускать (но это уже hibernate на борту подразумевается). Неизмененные поля в SQL не попадут (но потеряется перф, т.к. запрос динамический и не закешируется).
@bazilval
@bazilval 6 ай бұрын
@@ИльяКалендарев-е8ж Посмотрите связку mapStruct и JsonNullable для этих целей. Если кратко, то в DTO, которые отвечают за создание и обновление сущности нужным полям нужно сделать тип JsonNullable (или не String). Это такая обёртка, которая позволит различать null явный, когда мы хотим, чтобы у сущности поле стало null и null от того, что мы не указали это поле в теле запроса. Далее при отправке запроса, в случае если это поле не будет указано в теле запроса, то его значение будет null, а если указали и явно указали ему стать null, то этот null будет зашит внутри обёртки После этого мы настраиваем mapStruct для того, чтобы такие поля корректно мапились при преобразовании DTO в объект Если интересно, могу скинуть учебный проект, где я такое реализовывал @shurik_codes также интересно ваше мнение про этот подход!
@ladamira3477
@ladamira3477 7 ай бұрын
У меня у одной что-ли в BindException нет метода getAllErrors()?
@ladamira3477
@ladamira3477 7 ай бұрын
а, все, исправила импорт)) но у меня в toList просто не собирается, требует collect(Collectors.toList()))
@shurik_codes
@shurik_codes 7 ай бұрын
Это для JDK 17+, в примере используется JDK 21
@ladamira3477
@ladamira3477 7 ай бұрын
​@@shurik_codes у меня 17. По идее должно работать. И ещё приложение при запуске каждый раз требует новый порт чтобы развернуться. В чем причина?
@shurik_codes
@shurik_codes 7 ай бұрын
Что-то занимает этот порт, возможно, запущенный ранее сервис
@sermaz-blg
@sermaz-blg 7 ай бұрын
Приветствую. Что за плагин стоит и оставляет отметку simple (проценты)?
@shurik_codes
@shurik_codes 7 ай бұрын
Code Complexity
@denisskyter4526
@denisskyter4526 8 ай бұрын
А откуда у вас ultimate idea , с community не хочу ходить
@shurik_codes
@shurik_codes 8 ай бұрын
Неравнодушные люди помогают обновлять подписку)
@Hocorend
@Hocorend 6 ай бұрын
На торрентах поищи, тебе же для обучения, никто штраф не предъявит, версию 2022 года точно можно найти
@romoshi
@romoshi 7 ай бұрын
Не пойму почему не выводит продукт, на выхлопе получается "ID: 0, Название: , Описание: ", но в самом списке товаров id и title корректные. :(
@shurik_codes
@shurik_codes 7 ай бұрын
Возможно, где-то есть ошибки, код к ролику: github.com/alex-kosarev/sc24/tree/SC24EP02-servlet-api-rest-service
@romoshi
@romoshi 7 ай бұрын
@@shurik_codes Спасибо, буду разбираться!
@bolekrus
@bolekrus 6 ай бұрын
Catalague-service запускается без проблем, а Manager запускается один раз. Потом выключаешь, перезагружаешь программу, но всё равно ошибка Web server failed to start. Port 8080 was already in use.. Что за???
@shurik_codes
@shurik_codes 6 ай бұрын
Ну, значит, приложение менеджера не выключается корректно
@odtour
@odtour Ай бұрын
59:47 при попытке перейти на localhost:8080/catalogue/products/list выдает ошибку: There was an unexpected error (type=Internal Server Error, status=500). java.lang.IllegalArgumentException: URI with undefined scheme ... at ag.selm.manager.client.RestClientProductsRestClient.findAllProducts(RestClientProductsRestClient.java:31) ~[classes/:na] at ag.selm.manager.controller.ProductsController.getProductsList(ProductsController.java:23) ~[classes/:na] и чё с этим делать непонятно
@shurik_codes
@shurik_codes Ай бұрын
Посмотреть внимательно на настройки RestClient, судя по ошибке, URL не содержит схемы (http:)
@odtour
@odtour Ай бұрын
@@shurik_codes uri почему-то выходит вот такой: http/:localhost:8081/catalogue-api/products
@odtour
@odtour Ай бұрын
@@shurik_codes а где эти настройки найти?
@odtour
@odtour Ай бұрын
@@shurik_codes всё, нашел ошибку - было http//: вместо 😃
@Boraldan
@Boraldan 7 ай бұрын
Спасибо!
My MEAN sister annoys me! 😡 Use this gadget #hack
00:24
Человек паук уже не тот
00:32
Miracle
Рет қаралды 4 МЛН
Human vs Jet Engine
00:19
MrBeast
Рет қаралды 200 МЛН
СОБАКА ВЕРНУЛА ТАБАЛАПКИ😱#shorts
00:25
INNA SERG
Рет қаралды 3,6 МЛН
GOLANG СОБЕСЕДОВАНИЕ LAMODA НА 300К
1:54:35
nilchanpub
Рет қаралды 15 М.
Шаблоны проектирования для микросервисов
1:07:50
Александр Бармин
Рет қаралды 30 М.
SC24EP07 Разработка реактивных REST-сервисов - Разработка проектов со Spring
1:05:30
Что такое сервлет (servlet)? Что такое JSP?
12:27
Sergey Nemchinskiy
Рет қаралды 58 М.
WS МИТАП №3: БЭКЕНД (JAVA)
3:12:09
Work Solutions
Рет қаралды 455
SC24EP20 Развёртывание сервисов в Kubernetes - Разработка проектов со Spring
1:24:07
My MEAN sister annoys me! 😡 Use this gadget #hack
00:24