Comments 42
Я вот например начал знакомство со спринг и закончил почти сразу же. Какие-то конфигураторы для конфигураторов и ко всему этому фреймворк для запуска. Жуть какая-то, spring превратился в огромный комбайн и переплюнул java ee.
Сейчас например остановился на JSF. Для сайтов уровня hello world — самое то. Что-то крупнее hello world еще не пробовал писать. Может в этом случае я выиграл бы от такого комбайна как spring?
Бекенд в чистом видел – это API сервер, который ничего не должен знать про фронтенд. Сейчас все больше и больше мобильных клиентов, которым нужно отдавать только данные. Веб-сайты постепенно отходят на задний план.
Да серверный ренден еще остается, но для этого будут нужны «тяжеловесные» фреймворки. Для остальних же, нужны крайне легковесные, которым хватало бы каких-нибудь дешевых t1.micro.
Я сам не сильно люблю Spring, но Spring WebFlux – это совсем другое дело, если все так, как выглядит, то это замечательный инструмент (пока они не превратят его в Spring WebFlux Boot).
Думаю, не превратят. Он и планируется как легковесная микрофреймворковая штука для желающих. Хотя точно так же он может работать и в рамках обычного Spring приложения, просто @Controller
может вернуть не ответ, а Flux / Mono в качестве ответа — и все, реактивный контроллер готов. И даже можно объявить бин с типом RouterFunction
и привязать роутер к существующему приложению, а @Controller
аннотации не использовать вообще. Более того, чтобы оценить масштаб — по-умолчанию, Spring WebFlux даже не тащит зависимость на Spring MVC, они прям вообще разные.
Думаю, не превратят.Это же Spring, не стоит их недооценивать :-)
Кстати, попробовал потыкать webflux из примера на ApacheBenchmark – он вообще не отвечает на запросы. Ну а по консоли видно, что это сейчас на стадии альфы или в лучшем случае беты.
и пробовал выполнить:
ab -k -c 10 -n 1000 «localhost:8080/»
ab -k -c 1 -n 1 «localhost:8080/»
Оба зависают.
А через браузер отлично отдает ответ.
Команда Spring это одна из самых прагматичных и профессиональных, которые я встречал, так что не стоит их недооценивать ;)
Текущий статус Release Candidate, релиз будет до конца этого года.
Собственно, в этом и замысел — если приложение простое и экспортирует только пару эндпоинтов, то можно его написать супер просто, без магии вообще, но оставаться в рамках одного фреймворка.
Комбайн как Spring рулит когда в приложении много разных аспектов, типа интеграции, облачных штук, безопасности. В общем случае (не в крайних) их проще и быстрее сделать на Спринге, чем писать самому. Если приложение просто отдает html / json по данным из базы — его теперь можно сделать очень просто (хотя и раньше было просто, если уж откровенно).
Например, здесь https://docs.spring.io/spring/docs/5.0.0.RC3/spring-framework-reference/web.html#web-reactive
Если же нужно просто взять Spring (Boot) как есть с его DI и транзакциями, и прикрутить роутер, все делается просто регистрацией бина в конфигурации:
@Bean
public RounterFunction routerFunction() {
return route(...)
}
Есть несколько вариантов использования реактивного веба в Spring:
- Без Application context, DI, конфигураций и т.п. — как описано в статье
- Используя
@Controller
аннотации и возвращаяFlux<T>
илиMono<T>
из методов контроллера - Не используя контроллеры, определить бин типа
RouterFunction
с явно заданной таблицей машрутов и хендлерами.
Да, все верно, это старый-добрый Спринг, WebFlux это новая парадигма для веб-разработки, даже не замена MVC, а дополнение. А в качестве приятного бонуса, теперь на Spring можно писать microframework-style приложения à la Sparkframework, Ninja etc. без контекста приложений, DI и автоконфигураций.
Все говорят о каком то облегчении жизни, типа так быстрее.
Два месяца и 1 человек — готовый портал без фреймворка с нуля.
Неужели сейчас делается еще быстрее?
Хорошая попытка, Спринг, но нет, это плохая попытка. Получается, для того, чтобы вывести JSON вместо строки, нужно указать content-type:
.contentType(APPLICATION_JSON)
А дальше начинается счастье и проклятие спринга — спринговая магия. Какой сериализатор мы используем? Как его настроить? А если я хочу выдавать не json с content-type application/json? А если я хочу свой сериализатор вкрутить? И вообще зачем веб-серверу зависеть от спринга?
21 век на дворе, сейчас всем нужны:
- http server, где спрингом бы и не пахло
- сериализатор json, где спрингом бы и не пахло
- возможность скомпоновать 1 и 2, вне зависмости от релиализации.
.body(fromObject(new Hello("world")))
И там уже (как я очень надеюсь) можно использовать любой сериализатор.
А если я хочу свой сериализатор вкрутить?
берите и вкручивайте и даже свой ContentType можете в виде строки передать — там никакой магии — сплошная документация
http server, где спрингом бы и не пахло
Вообще говоря, это неоднозначное желание. Т.е. я могу вас понять, и представить такие запросы. Но я также могу представить свои запросы, где скажем сервлеты (ну или в более общем виде обработчики http запросов) это spring бины, и я хочу, чтобы сервер знал про спринговые контексты, и умел подключать оттуда обработчиков. И вообще говоря — не только спринговые.
Иными словами — как вы в общем виде компоновать-то 1 и 2 собираетесь, если у вас нет контейнера, где лежит сериализатор, http сервер, и что-нибудь еще?
Что мешает написать:
HttpServer
.withCodecRegistry(
new CodecRegistry()
.bind(APPLICATION_JSON, new JsonCodec( ... ))
.bind(APPLICATION_XML, new XmlCodec( ... ))
)
.withRouteRegistry(
new RouteRegistry()
.bind(GET("/"), (r) -> Response.ok());
)
...
.run(8080);
Или что-то подобное…Более того, чтобы файл не был на тысячи строк, можно этот конфиг разбить на несколько: RouteConfig, ErrorHandlerConfig, CodecConfig, etc.
Для проектов, у которых меньше 50-100 эндпоинтов это будет вполне приемлемый подход.
Это не будет слишком избыточным кодом или страшным бойлерплейтом, это будет вполне удобный и красивый конфиг.
Лямбды и чистые функции позвляют значительно улучшать конфиги. В этом плане инновационные языки — Scala и Javascript. Вкратце, идея в том, что любой сетевой обработчик, фильтр и собственно сервер — это функция Request -> Response
. Т.е. приложение можно собирать функциональной композицией индивидуальных обработчиков, фильтров и роутеров.
Ну да. И что вы хотели этим сказать, что вам DI не нужно?
DI нужен, не нужна конфигурация через данные. Конфигурация кодом — лучше.
Конфигурация кодом как правило меняется только при перекомпиляции. Это не плохо и не хорошо — но бывает что нужно и в рантайме. Ну т.е. функциональная композиция — это хорошо, но иногда хочется собрать без компиляции.
Конфигурация DI кодом уже есть в Spring 5 и называется Programmatic Bean Registration и даже есть удобный Kotlin DSL для него.
Это нормально, но я не могу сказать, что это однозначно лучше. Или хуже. Во-первых, кроме явного кода вы выбрали инициализацию статическую, где все определяется при компиляции. Где-то это хорошо, где-то не факт. Это не лучше и не хуже — это разные потребности.
Скажем прямо — у меня и так не видно, чтобы скажем http server где-то зависел от спринга. От вот этих самых сериализаторов и обработчиков — да, зависит. Они возможно даже инжектятся спрингом — только сервер про спринг (который DI) не знает.
Во-первых, кроме явного кода вы выбрали инициализацию статическую, где все определяется при компиляции.Никто не мешает использовать конфиги – поменял конфиг и рестартовал и погнали.
Спринг крутой, он позволяет быстро написать то, что будет работать.
Но вот я, к примеру, всегда хотел выкинуть из спринга все ненужное мне в конкретном проекте. У меня API сервер, который умеет только JSON и ничего больше. Но спринг такой классный, что подсовывает мне дополнительно кучу кода, который нужен для поддержки xml, html, а еще загружает классы для AOP и кучу своих связок для других вещей, которые нафик не нужны. А ведь RAM то ограничен.
Но это уже offtop с моей стороны пошел.
Знаете, у меня в прошлом проекте были "аналитики", которые тоже говорили: "А чо, поменял конфиги, рестартовал и погнали". А то что на входе непрерывный поток данных (финансовых), который можно потерять пока рестартуем — это им в голову не приходило. Всякие проекты бывают, попросту говоря.
Что же до "загружает всякие классы для AOP" — ну так вообще говоря, это не является обязательным.
Единственное что меня лично в этом вопросе расстраивает — это тот факт, что не всегда очевидно, зачем конкретно тут вот появился AOP (или что-то еще). Хотя если подумать, обычно ответ недалеко — включил аннотацию @Cacheable для кеширования результатов метода — так оно что, святым духом что-ли будет вызовы метода перехватывать? Нет же, будет либо Proxy, либо AOP, со всеми вытекающими. Ну т.е., нужно иногда понимать, как оно там внутри, что за неонки.
Знаете, у меня в прошлом проекте были «аналитики», которые тоже говорили: «А чо, поменял конфиги, рестартовал и погнали». А то что на входе непрерывный поток данных (финансовых), который можно потерять пока рестартуем — это им в голову не приходило. Всякие проекты бывают, попросту говоря.Инструмент выбирается под проект. Я не говорил, что Spring – это абсолютное зло, он хорош для много. Я лишь сказал, что для большинства задач, с которыми я сталкивался в своей карьере он излишне «жирный».
Кстати, а как вы решали такую задачу, когда необходимо поменять конфиг на живом потоке данных?
Только в битве за RAM не забывайте, что вообще весь Spring сам по себе, занимает не так уж и много памяти — до 32Мб. Есть интересное исследование на эту тему от Дейва Сайера.
Spring: ваш следующий Java микрофреймворк