SC24EP01 Разработка веб-приложения - Разработка проектов со Spring
HTML-код
- Опубликовано: 3 мар 2024
- В первом ролике цикла я демонстрирую разработку классического веб-приложения со Spring WebMVC, Thymeleaf и Jakarta Bean Validation. В ролике демонстрируется несколько способов создания нового проекта на основе Spring Boot, вкратце описывается многоуровневая архитектура и шаблон проектирования MVC, создание базовых компонентов приложения, валидация данных и интернационализация. Кроме этого продемонстрировано несколько способов запуска приложения на основе Spring Boot.
В цикле роликов "Разработка проектов со Spring" я рассказываю на простых примерах о процессе разработки веб-приложений и REST-сервисов на языке программирования Java с использованием экосистемы Spring. Данный цикл охватывает разработку классических и реактивных проектов, вопросы их сопровождения, такие как документация и мониторинг, адаптацию их к облачной инфраструктуре и процесс их развёртывания в Docker и Kubernetes.
Репозиторий проекта: github.com/alex-kosarev/sc24/...
Мои ресурсы:
- Сайт: alexkosarev.name
- Канал на RUclips: / @shurik_codes
- Канал в Telegram: t.me/+TZCuO38vG3oqu_Jq
- Группа для обсуждений в Telegram: t.me/+UFAkw187WstX0wqy
- Паблик в VK: shurik.codes
- Канал в Дзене: dzen.ru/shurik_codes
- Канал на Rutube: rutube.ru/channel/24432001/
- Страница в Boosty: boosty.to/akosarev
Поддержать проект:
- Доны в VK: donut/shurik.codes
- Донаты в Boosty: boosty.to/akosarev/donate
- Через Tinkoff: www.tinkoff.ru/cf/4PEOiVCZQuS
#java #spring #web #validation #thymeleaf #howto
спасибо) полезно и приятно слушать)
Александр - потрясающий преподаватель. Всегда очень приятно смотреть и слушать. Спасибо, Саш, что ты делаешь.
Присоединяюсь, для меня тоже один из лучших преподавателей 🔥🔥
Братик вот хочешь верь или не верь, но то что ты делаешь это имба дикая !
После всех других роликов по спринг - отбивались руки только. У вас же всё очень понятно и информативно, появилась вера в возможность освоения фреймворка😆. Буду продолжать смотреть ваш канал. Успехов вам!
Спасибо за урок! Я недавно теорию по спрингу выучил, а тут практика годная с объяснением тонких моментов. Сохраняешь работягам кучу времени. Чисто кайф.
P.S. Круто, что оставляешь моменты типа такого 1:26:51 было весело видеть твою реакцию на баг
было бы интересно, в будущем, увидеть ролики про проектирование приложения в гексагональной архитектуре)
Ждал этот видос больше, чем выход второй Дюны !!
Спасибо! Все крайне понятно
Отличное видео.
Главное, чтобы запал не пропал у человека.
Хотелось бы про деплой на прод увидеть - как сервис выбрать, как залить, как запустить, какие особенности и т.д. - в общих чертах.
Поддержу комментаторов выше- автор очень понятно и интересно объясняет.
Спасибо! Жду следующие выпуски.
Не пропадет. Он уже отснял все 22 ролика, просто выкладывает поэтапно)
@@alexandr6055 да, спасибо, я увидел его вступительный ролик.
Темы хорошие озвучивает, посмотрю все обязательно.
как всегда хорошо, спасибо
Спасибо за видос, как всегда кайфанул
Спасибо за контент!
Спасибо вам огромное за урок!
Бомба 💣💣💣
Огромное спасибо автору. Отличное видео!
Спасибо! ждем продолжения!
Интригующе.
Офигенно! Спасибо большое, еще и настолько подробно и понятно!
cпасибо большое вы как будто услышали наши пожелания
Очень хорошо, что вы стали записывать такие интересные ролики, которые не только зеленому новичку будут полезны. 🙂👍👍👍
Спасибо! Будем просвещаться )
1,5 часа == ОГОНЬ!!! Спасибо , Александр!
большое спасибо _ побольше таких уроков +) лайк комент подписка
Спасибо, самое то, что мне сейчас нужно
Спасибо за то, что делитесь знаниями! Видео отличное, всё чётко и понятно)
Давненько не видел!! Очень рад, что не забросил дело)))
Это прекрасно! Мне как раз спринг освоить сильно захотелось день назад :)
Отличная серия роликов
Большое спасибо. Очень информативно. Как раз сейчас начинаю писать свою дипломную работу по Спрингу и очень рад, что вас нашел.
Супер! Смотрится на одном дыхании, как детективная история, чем дальше - тем интереснее
Спасибо Вам огромное!!!))))
Очень информативно, понятно и интересно
Лучший канал по Джаве))))
Классный, полезный ролик без воды. Все полтора часа полезной информации. Хотелось бы по больше фишек, которые применяются в реальной разработки
Успехов Вам и спасибо за полезную информацию
Спасибо ! Но нужно еще раз пересмотреть и попробывать своими ручками. Мне очень понравилось
Класс, очень понятно и доступно, очень рад что нашел ваши видео вКонтакте, а теперь и здесь на канале! Однозначно подписка.
Александр спасибо за ваш труд, просто лучший.
это настоящий подарок :D
Отличный контент Александр, продолжайте, не останавливайтесь) Ваши труды поддержал донатом, благодарю за уроки
Опыта работы программистом не имею, только обучаюсь длительное время.
С данного видео получил больше полезной инфы чем от всяких лекций и многих других видео с ютуба.
Очень благодарен за труд, твои видео как клад, очень рад что наткнулся.
Друг, хочу сказать тебе огромное спасибо. Очень тяжело найти свежие ролики, где всё досконально объясняют. Спасибо тебе огромное!
ждееем!!!!!
Огромное спасибо за труд! Было бы отлично добавить тайм-коды к видео:) Когда пытаюсь повторить на практике, часто возвращаюсь к разным частям разных уроков, пытаясь вспомнить где и что было рассказано и показано)
Таймкоды будут, не успел их проставить
谢谢老师,你厉害得很
Спасибо! Было интересно узнать про валидацию данных и интернализацию, а также что можно аннотировать @ModelAttribute методы. Как предложение, можно было кратко описать спецсимволы HTML в ходе повествования, либо привести ссылку на документацию, а также добавить пример подключения статических ресурсов CSS и JS, все таки это распространенный кейс
Про валидацию уже был ролик на канале, про Thymeleaf будут
коммент для продвижения
велосипед не изобрел но под пивасик нормас!
Классный материал. Очень насыщенный и наглядный! Александр, в начале ролика Вы упомянули, что будете разрабатывать многомодульный проект, и каждый модуль будет развернут как отдельный микросервис. Хотелось бы узнать почему выбран именно такой подход? Если за альтернативу взять вариант с разработкой каждого приложения в отдельном проекте, то какие плюсы и минусы будут в сравнении с выбранным Вами подходом?
Мне так проще всё держать в одном месте) В реальных условиях так не всегда удобно делать
Спасибо, что выпускаешь свои ролики, многие моменты из твоих роликов помогают улучшить мой код. Такой вопрос: Почему ты в подавляющей части роликов используешь систему сборки maven, а не gradle?
Я использую во всех роликах maven, потому что привык)
Простите, а чем обусловлен выбор Linked List в качестве структуры данных для продуктов в ин мемори репо?
Спасибо за видео, повторял сейчас за вами все и столкнулся с ошибкой что форма вела на /catalogue/products/catalogue/products/create, изменил data-th-action="@{/catalogue/products/create}" на data-th-action="@{create}" и все заработало, форма перенаправляет куда надо. Интересно с чем связано такое поведение🤔
Спасибо за отличный контент!
А что за расширение, которое показывает simple (0%) и что оно вообще делает?
Code complexity
Здравствуйте, у вас в плейлисте перепутаны первый и второй ролики
Используете ли инструменты ИИ для помощи с написанием кода, и с генерацией тестов?
Нет, всё пишу сам
Добрый день! Что бы вы посоветовали использовать для интеграционного тестирования MockMvc, TestRestTemplate, WebTestClient, RestAssure возможно другой вариант. Для работы с WebTestClient обязательно добавлять webflux или в последних версиях Spring можно настроить и без webflux?
По тесты будут 5 и 10 ролики, RestAssured выглядит перспективнее всех за счёт универсальности, но я использую либо MockMvc, либо WebTestClient. Да, для последнего нужен webflux
Александр, вопрос: можно чуть подробней - для чего нужно что бы при компиляции сохранялись наименования аргументов методов? (об говорится в 20:00 по шкале времени)
Чтобы не уточнять в @PathVariable, @RequestParam и других аналогичных аннотациях названия переменных. Например, если скомпилировать без сохранением названия аргументов такой код:
@RequestMapping("/path/with/{variable}")
String doSomething(@PathVariable String variable)
то аргумент в рантайме будет называться arg0 (вроде), и при вызове метода будет выброшено исключение, т.к. в пути нет {arg0}
@@shurik_codes Спасибо! вот такие объяснения очень ценны для чайников!
скажите, а для чего при обращении в методах к сервисам или репозиториям которые инжектированы внутри класса вы используете конструкцию this.servise...? Что даёт здесь этот this?
для собственного удобства, чтобы видеть, что обращение идёт к свойству экземпляра класса, а не к локальной переменной
Здравствуйте! Спасибо за ваши видео. Подскажите пожалуйста, в чем разница между аннотацией @ModelAttribute и использованием модели в качестве параметра и соответственно добавлением атрибутов с помощью метода addAttribute.
Оба данных подхода реализуют одно и то же действие - добавление атрибута в модель. @ModelAttribute позволяет написать метод, добавляющий атрибут в модель для всех запросов, обрабатываемых в контроллере. По сути уменьшается дублирование кода.
Планируете ли делать разбор работы с хибернейтом?
От вас бы было классно посмотреть
Будет
@@shurik_codes
🎉🎉🎉🎉
🔥🔥🔥🔥@@shurik_codes
Посмотрел код в гитхабе. И мне показалось, что конечная задумка будет что-то вроде книги spring microservices in action. Я правильно понимаю?
Я из этой книги взял кусок про Spring Cloud и Helm, остальное - авторское) Ну и если буду переснимать в будущем цикл, то Spring Cloud будет фундаментально переписан
@@shurik_codes Круто, спасибо.
А если spring под капотом работает в многопотоке, то надо все синхронизировать и использовать потокобезопасные структуры данных?
Да, и это касается не только Spring, но и вообще всех многопользовательских систем
@@shurik_codes а синхронизировать нужно только структуры данных или еще много чего
А будет запись стрима... Я в школе просто буду
Это не стрим, а премьера видео, так что да, будет
Как напечатать перечеркнутое равно? Перебрал все: ≠, ≠, U+2260, !=, (ne), ne, =!, , !==, Alt+8800. Не печатается.
Спасибо проклятому автору за действительно крутое и полезное видео и будь он проклят. Добавь крипту для доната.
Нужно включить поддержку лигатур в настройках шрифта, если речь об IDEA
Интересно конечно на java делать веб-приложения, но на Golang будет выглядеть намного проще и быстрее
Показываю, что знаю и умею
Здравствуйте, спасибо за видео, подскажите, зачем делать 2 pom.xml файла?
Каждый pom-файл отвечает за отдельный модуль, корневой - за весь проект в целом
21:48
Присоединяюсь к комментариям ниже, действительно, смотреть ваши уроки одно удовольствие. Но у меня один вопрос. Почему мы помечаем стереотипными аннотациями саму реализацию интерфейса, а не сам интерфейс. Пометив аннотацией реализацию интерфейса, Spring создаст бины классов реализующих его?
1. Если я ничего не путаю, то применение стереотипичных аннотаций к интерфейсам не регистрирует соответствующие компоненты в контексте приложения, а это ведёт к возникновению NoSuchBeanDefinitionException при попытке внедрения.
2. При таком подходе интерфейс в какой-то мере становится зависимым от Spring, а я стараюсь делать интерфейсы независимыми, не смотря на всю свою любовь к Spring.
Но вообще я на практике из стереотипных аннотаций использую только @Controller, остальные компоненты я предпочитаю конфигурировать руками в @Configuration/@Bean.
Спасибо за видео!
Но у меня в процессе просмотра возникло пару вопросов:
1. 23:30 А если у меня две реализации ProductService как спринг будет выбирать екземпляр.
2. Почему вы синхронизировали список через Collections а не пакет concurrency.
3. 40:37 Можно ли было написать product.setId(products.size() + 1);?
4. Что за магия происходит с @PostMapping("create") public String createProduct(NewProductPayload payload)
Как класс NewProductPayload собирается над ним даже аннотаций не стоит, как это работает?
5. Почему метод updateProduct в DefaultProductService мы реализовали так как реализовали, а не как до этого вызвали бы метод у productRepository?
1. @Qualifier или @Order/@Priority
2. Первое, что в голову пришло
3. Тогда возможно появление в разных промежутках времени разных товаров с одним идентификатором, но опять же это не играет большой роли
4. Объясняется вот тут в самом конце: docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/arguments.html По сути логика аналогична применению @ModelAttribute к аргументу NewProductPayload payload
5. Не понял вопроса
Подскажите, пожалуйста, каким образом payload в методе createProduct() автоматически получил данные из формы. Разве мы не должны прописывать th:object в form, чтобы это работало?
Если метод аннотированного контроллера принимает аргумент какого-то собственного типа, то это равносильно объявлению его с аннотацией @ModelAttribute, подробнее вот тут в самом конце: docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/arguments.html
По сути создаётся экземпляр указанного класса и в него подставляются данные из запроса.
Большое спасибо за разъяснение!@@shurik_codes
Александр. Спасибо за уроки. у меня вопрос. Я совсем начинающая. у меня версия maven 3.9.4 и spring-boot-maven-plugin у меня красный и никак не хочет добавляться. что делать? поставить вашу версию maven поможет?
1. Если версия плагина не указана через pluginManagement в текущем или родительском проекте, то её нужно указать явно
2. groupId должна быть org.springframework.boot, artifactId - spring-boot-maven-plugin
Если даже после этого плагин выделен красным и речь идёт об IDEA, то нужно чистить кеш
@@shurik_codes я там в каком-то уроке сделала обертку для maven. теперь не знаю как её убрать
и еще когда создается проект через сайт. то главный модуль уже получается дочерний от spring-boot и модуль у меня не добавляется. только директория manager-app
Можно ли вместо Integer использовать класс UUID, вместо обозначения для поля id?
Конечно можно
Если помню Вы где-то хотели в процессе видео объяснить, почему нужно обертку инта использовать вместо примитива, но так и не вернулись к этому. Если, конечно, я не пропустил.
Ну вот как-то да, упустил этот момент. Это нужно, чтобы в 3 ролике корректно работал JPA)
На 50:05 - там же PostMapping должен быть, разве нет?...
А то получается два одинаковых GetMapping-а
А....
Там не PostMapping
Там должен был быть GetMapping, но на другой урл - в одном "{\\d+}", а во втором - "{\\d+}/edit"
как-то можно сопоставить разные имена из формы и атрибуты payload?
Да, при помощи методов с аннотацией @InitBinder
А вы пользуетесь Jpa buddy ?
Нет, я на практике с JPA вообще редко сталкиваюсь
Очень полезное видео.
Только вот если в валидации я убираю аннотацию Size, оставляя только NotNull, то могу создавать объекты без названий
Импорты все из одного пакета(
Всё логично
@@shurik_codes Я думал NotNull для того чтобы мы не могли сохранить значение вообще без символов, но видимо я не правильно понимаю(
@@3am6ep @NotNull только для проверки на null
А что делать есть у меня .jar файл собирается, но после команды java -jar name.jar ничего не происходит? И соответственно localhost ничего не возвращает в браузере. Все остальные способы работают нормально.
Возможно, jar собран либо без Spring Boot Maven Plugin, либо он не "толстый".
@@shurik_codes спасибо большое
А подскажите, как вообще создавать такие многомодульные проекты в intellij? У вас в selmage-parent нет src и вложенных в него папок. Я когда пытаюсь создать пустой "родительский" maven проект, то у меня все равно эта папка появляется. Или вы просто вручную из parent их удаляете?
Я создаю обычный maven-проект и удаляю src
Народ, где сейчас больше денег можно заработать на сеньорной позиции в срденем, golang или java?
В среднем - на Go
Я так понял таких роликов будет много , да?
Да, всего в цикле будет 22 ролика, полный список роликов я публиковал у себя в Telegram-канале и во вступительном ролике
можно было обойтись без класса NewProductPayload, сразу создавая Product?
Теоретически - да, ничто не мешает так делать, но с точки зрения архитектуры это плохая идея. Структуры данных должны соответствовать намерениям и нести только тот набор свойств, которые могут быть заполнены пользователем.
А почему для Id используется тип Integer?
Чтобы ничего не переделывать для третьего ролика
как добавить локали на другие языки сразу же?
Создавать соответствующие файлы интернационализации
На каком сайте? Ваш сайт почему то не работает(
alexkosarev.name, в теории он может быть недоступен из-за пределов РФ
Вау, спринг мвс с таймлифом в 2024 году?!😂 Надеюсь там и jsp будет?
А почему нет? Оно всё вполне актуальное
Так это же плейлист по основам, так что стоило ожидать. Тем более сам создатель канала опубликовал объявления об этой серии видео
@@shurik_codes Актуальное может быть, но таймлиф и вообще шаблонизаторы - редко применимы в проде, только для специфических задач. Хотя похоже вы не захотели отвлекаться на spa-js-фреймворки. А спринг мвс типа не модный, в отличии от вебфлакса. Хотя на нем большинство даже новых сервисов пишут, потому что настоящая потребность в реактивных сервисах редка.
Почему нет? Новичкам очень важно потрогать то, что они пишут, превратить их работы в реальный продукт. Не думаю, что js с 0 учить для такой цели рационально)
Саша, привет. Спасибо, контент очень качественно подан. Но у меня вопрос. Зачем это нужно с практической точки зрения? Ведь же мы уже давно на бэке работаем с JSON, который прилетает с фронта. Я про шаблонизатор Thymeleaf. Спасибо заранее за ответ.
Ну, как показывает практика, серверный рендеринг вполне активно используется, недаром он присутствует в том числе и в Angular, Vue и React
@@shurik_codes Я к тому, что напрямую мы не используем thymeleaf или еще что, например jsp, на бэке. В практике реальной это не пригодится сейчас. Все очень стремительно меняется в наше время.
product.setId(products.size() + 1);
Можно и так, только в случае удаления товара не из конца списка возможно дублирование идентификаторов
12:31:49.908 [restartedMain] ERROR org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter --
***************************
APPLICATION FAILED TO START
***************************
Description:
No spring.config.import property has been defined
Action:
Add a spring.config.import=configserver: property to your configuration.
If configuration is not required add spring.config.import=optional:configserver: instead.
To disable this check, set spring.cloud.config.enabled=false or
spring.cloud.config.import-check.enabled=false.
К этому ролику код с тэгом sc24ep01
у меня @NotNull игнорировал и не выводил ошибку, если поле пустое. Поставил @NotEmpty
@NotNull только проверяет на null, @NotEmpty проверяет, что строка состоит из 1+ символов