29 ноября 2014 в 19:55

Стоит ли использовать Spring Boot в вашем следующем проекте? перевод

Java*


Большинство моих профессиональных Java проектов за последнее десятилетие были основаны на Spring или JEE. Обе платформы развиваются достаточно уверенно, однако все ещё страдают от различных проблем.

Spring и JEE по-прежнему остаются золотыми стандартами для масштабных Java-проектов и больших команд разработчиков, трудящихся над сложными enterprise-решениями. Однако, неизбежным следствием зрелости Java-сообщества стала частичная потеря прежнего энтузиазма и инновационности, что существенно ударило по авторитету обоих.


JEE изменилась довольно резко на протяжении многих лет, но до сих пор осуждается разработчиками за подходы и решения, которые были обозначены создателями платформы как deprecated ещё начиная с версии EJB 2.x. Многие люди до сих пор называют JEE как “J2EE”, хотя изменение названия состоялось 8 лет назад!

Spring тоже заметно усовершенствовался, однако далеко не всеми пользователями это воспринимается. Невзирая на возможность создания при помощи Spring 3.x и выше современных приложений с прозрачной, неоторванной от кода конфигурацией, большинство проектов продолжают с избытком пестреть XML-файлами и устаревшими архитектурными решениями. Проблема в том, что много разработчиков по тем или иным причинам не меняют отработанного на предыдущих версиях подхода.

По указанным причинам открылась дорога другим языкам и фреймворкам. Java был, вероятно, самым популярным языком для личных проектов, более десятка лет тому назад, но молодые разработчики сегодня, кажется, стали обращать больше внимания на Python, Scala и т.д. Наиболее влиятельные веб-фреймворки предыдущего десятилетия Rails, и основанная на Ruby Sinatra породили ряд микро-фреймворков на протяжении последних пяти лет.

Groovy и Grails, в мире Java, стали первым серьёзным ответом Ruby и Rails. Их теперь можно встретить в наборе инструментов даже самых консервативных команд enterprise-разработки. Однако, новые фреймворки на основе JVM идут гораздо дальше. Вместо просто обёртывания API JEE и Spring в легкую для использования интерфейс-оболочку Play фреймворк начал, так сказать с чистого листа, отбрасывая даже, казалось бы фундаментальную модель Java-сервлета.

Spring уже не рассматривается как современный инновационный инструмент. Разработчики еще используют его, особенно для старых приложений, но в основном, потому что они должны, а не потому, что они этого сами хотят. Я не могу вспомнить, когда последний раз я говорил с разработчиком, использовавшем Spring в личном проекте, в то время как Play или совершенно другая платформа встречаются повсеместно.

Это позор, ведь Spring – невероятно мощный инструмент, если получится правильно его настроить. Spring Data JPA предоставляет простое управление реляционными базами данных без написания классов DAO, также Spring Data JPA позволяет получить тот же функционал по отношению к NoSQL хранилищам данных, если получится правильно его настроить. Кроме того, с помощью Spring вы имеете возможность осуществлять enterprise-интеграцию, доступ к API самых популярных социальных сервисов для ваших веб- или android-приложений, позаботится о безопасности вашего приложения посредством Spring Security, но, опять же, если у вас получится правильно все сконфигурировать.

Построение приложения на основе Spring может быть очень болезненным процессом. Отчасти это из-за большого количества существующих альтернатив при выборе технологий. Например, стоит ли осваивать и использовать Spring Data JPA, если вы уже потратили время на изучение JdbcTemplate и Hibernate/JPA? Какая разница между Spring Data REST и Spring HATEOAS?

Другим осложняющим фактором является то, что Spring редко признает что-либо deprecated, и не предоставляет достаточной информации для принятия обоснованного решения по выбору технологий, устранения разнообразных конфликтов и решения других часто возникающих проблем. Если вы будете искать в Интернете пример устранения какой-то неполадки, ссылки на устаревшие подходы и решения будут в топе результатов поиска. По большей части именно из-за этого XML-конфигурация остается такой распространённой, невзирая на простоту имплементации и поддержки конфигурации на основе аннотаций. Вместо использования чистой системы шаблонов такой как Thymeleaf или Velocity, в большинстве приложений по-прежнему применяется JSP с JSTL.

Жажда к ликвидации указанных проблем никогда не угасала у создателей Spring. Вдохновившись инструментом командной строки Rails, они презентовали Spring Roo – систему быстрой разработки, которая кроме того позволяет создавать элементы, такие как веб-контроллеры или JPA сущности посредством командной строки. Тем не менее, для нетривиального использования, освоить Spring Roo почти так же сложно, как собирать приложения вручную. Многих разработчиков отталкивало обилие аннотаций и AspectJ-файлов, которые Roo повсеместно добавляет в проект для обеспечения своей “магии”. Хотя и заявляется, что Roo можно легко и безболезненно удалить из проекта, если понадобится, реальность оказывается более суровой, чем теория. И даже если у вас все получилось, конвертация AspectJ в Java напрочь лишает вас возможности пользоваться магическим инструментом командной строки.

Spring Boot – следующая генерация средств упрощения процесса конфигурации Spring приложений. Он не является средством автоматической генерации кода, а представляет собой плагин для системы автоматизации сборки проектов (поддерживает Maven и Gradle).

Плагин предоставляет возможности для тестирования и разворачивания Spring приложения. Команда mvn spring-boot:run обеспечивает запуск вашего приложения на порту 8080. Это чем-то напоминает довольно популярный плагин Maven Jetty. Кроме того, Spring Boot позволяет упаковывать приложение в отдельный jar-файл, с внедренным полноценным контейнером Tomcat. Этот подход позаимствован у модели развертывания приложений фреймворка Play (вместе с тем вы также можете создавать традиционные war-файлы).

Основная выгода Spring Boot – конфигурирование ресурсов исходя из содержания classpath. Например, если pom.xml файл вашего Maven проекта содержит JPA зависимости и драйвер PostgreSQL, Spring Boot настроит persistence-модуль для PostgreSQL. Если вы добавили веб-зависимость, вы получите сконфигурированный по умолчанию Spring MVC. Если вам нужна персистентность и ничего кроме этого, Spring Boot сконфигурирует Hibernate как JPA провайдер с базой данных HSQLDB. Если вы создаете веб-приложение, но не указываете ничего дополнительно, Spring Boot сконфигурирует view resolver для системы шаблонов Thymeleaf.

Говоря о конфигурации по умолчанию, Spring Boot достаточно интуитивен в этом плане. Вы можете не всегда быть согласны с его выбором настроек, но, по крайней мере, он предоставит вам работающий модуль. Это очень полезный подход, особенно для начинающих разработчиков, которые могут начать работу с настройками по умолчанию, а потом, по мере изучения существующих альтернатив, вносить изменения в конфигурацию. Согласитесь, это намного лучше чем получить кучу сложных вопросов, без решения которых просто невозможно стартовать. Вдобавок на официальной странице проекта есть ряд полноценных туториалов, позволяющих быстро понять и практически реализовать все основные виды проектов на уровне “Hello world”.



Построение инфраструктуры приложения, фактически заключается в добавлении нужных модулей в pom.xml:

...
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.0.0.RC3</version>
</parent>
...
<properties>
  <start-class>com.mypackage.Application</start-class>
  <java.version>1.7</java.version>
</properties>
...
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.3.174</version>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>
...
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>
...


а также написании main Java-класс следующим образом:

@Configuration
@EnableAutoConfiguration
@ComponentScan
@PropertySource("classpath:application.properties")
public class Application {
 
    @Bean
    MyCustomService myCustomService() {
        return new MyCustomService("");
    }
 
    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
 
        System.out.println("Let's inspect the beans provided by Spring Boot:");
 
        String[] beanNames = ctx.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
    }
}


Для большинства случаев изменения настроек по умолчанию, достаточно изменить POM-файл. Так, в примере выше продемонстрированно добавление зависимости для базы данных H2. Spring Boot, видя такое изменение, конфигурирует persistence-модуль JPA для базы данных Н2 вместо, предлагаемой по умолчанию HSQLDB. Если вам хочется использовать Jetty как встроенный контейнер, вместо предлагаемого по умолчанию Tomcat, просто добавьте соответствующую зависимость.

В данный момент Spring Boot находится на этапе становления, и, безусловно, до выхода на стабильный уровень ему предстоит пережить немало метаморфоз. Возможно, его еще рано использовать для построения серьезных систем, однако он вполне подходит для выполнения разного рода персональных, тренировочных и тестовых проектов, при реализации которых очень важно избавится от нежелательного объема непродуктивной, рутинной работы, никоим образом не связанной с созданием полезной функциональности.

В контексте потенциальных перспектив перерастания Spring Boot в будущем в серьезный инструмент для Spring разработки, особенно обнадёживает присутствие приемлемой технической документации (правда, только на английском языке и все ещё достаточно скудной, в сравнении с 800 страничной “энциклопедией” Spring Framework).
Перевод: Steve Perkins
Aleksandr Vengrovskyi @alexVengrovsk
карма
9,0
рейтинг 0,0
Похожие публикации
Самое читаемое Разработка

Комментарии (41)

  • +7
    Перевод отличный.
    А вот содержание, кажется, спорное!
    Это, конечно, вопрос к автору англоязычной статьи, но голые утверждения о том, что «Spring уже не рассматривается как современный инновационный инструмент», выглядят необоснованными.
    • +1
      Нужно еще принять во внимание ориентацию автора на тенденции среди западных (американских) разрабочиков
    • +1
      Не такие резкие, но близкие по сути выводы можно сделать исходя из следующего материала (слайды 39 — 43). Как продемонстрировано там, более «молодые» фреймворки получили более высокие оценки, чем Spring, или очень плотно к нему приблизились. Кроме этого, достаточно интересные результаты представлены тут.
      • 0
        Ну вы же понимаете, что все такие результаты субъективны)
  • 0
    пробовал я писать свой проект поверх boot
    ага-ага, хелоуволды то пишутся легко и быстро, но чуть шаг в сторону — начинается чехарда со spring аннотациями\xml-ми и тому подобным
    • +1
      Главное, чтобы конфигурационный класс с @ComponentScan hello world'а был хоть в каком-нибудь пакете (не в корне), то у новичка крышу сорвёт)
    • 0
      Намерения у разработчиков Spring Boot довольно благие, но как показали комментарии разработчиков на разнообразных форумах, подтвержденное и Вашим комментарием, его основной проблемой является высокая сложность кастомизации, особенно после создания проекта. Очевидно вызвана такая ситуация отсутствием наглядности, ведь фактически весь процесс конфигурации спрятан так сказать «под капот».
      Возможно в будущем появится более детальная информация по принципам работы данного инструмента, руководства и примеры решения сложных проблем разработки, что сможет исправить существующие сегодня недостатки.
      • 0
        Ещё они очень любят запихать свой parent POM, что не всегда удобно. Можно, конечно, обойтись без этого, но придется копировать существенный кусок dependency management, что резко снижает полезность сабжа, imho.
        • 0
          Вы же можете сделать свой parent pom.xml и вынести в него все что вы не хотите видеть в основном файле конфигурации.
          • 0
            Я и использую. Только держать пачку parent (с поддержкой boot и без оной) может быть не очень удобно.

            Плюс я не люблю bom-like parent pom (с dependencyManagement, включающим сторонние библиотеки), т. к. оно приводит к трудноуловимым багам. Например, вы в проекте зависите от какой-нибудь библиотеки A транзитивно зависящей от библиотеки B версии X. В spring-boot-starter-parent прописана B версии Y (отсутствие прямой и/или обратной совместимости между версиями X и Y), на которой A ломается. Увидев такое безобразие вы прописываете в dependencies библиотеку B версии X. Таким нехитрым образом можно получить крайне неприятный и относительно трудноуловимый баг, который вылезет в недрах того же spring boot'а или его компонентов.
    • 0
      Можете описать один-два таких момента? А то я как раз выбрал Spring Boot, как раз написал Hello World и теперь вот прочитал ваш коммент и загрустил.
      • 0
        Когда есть опыт работы со спрингом, особых проблем с кастомизацией не возникает. Если хочется что-то настроить под себя — просто смотришь исходники соответствующего класса автоконфигурации, и либо переделываешь его с нуля, либо меняешь соответствующие бины. Но если опыта нет, то будет тяжело во всём этом разбираться.
        Пара неприятных проблем, которые мне встречались:
        При сабмите www-url-encoded формы кодировка определялась как ISO-8859-1. Быстро вылечилось заменой томката на джетти. Потом выяснил, что можно пофиксить добавлением соответствующего фильтра в цепочку spring security.
        Пара библиотек отказалась работать со вложенными jar'ами — пришлось дописать лишнюю сотню строк кода.
        Thymeleaf под себя дорабатывать довольно трудно, но это с непривычки и к спрингу мало относится.
        • 0
          >Если хочется что-то настроить под себя — просто смотришь исходники соответствующего класса автоконфигурации, и либо переделываешь его с нуля
          >переделываешь
          >лечилось заменой
          >дописать
          в этом весь спринг бут, спасибо
          • 0
            В этом весь %любойфреймворк%.
            По большому счёту, бут — это набор стартовых конфигов. Править и переделывать их — естественная задача. А чтобы их править, надо для начала изучить спринг DI, WebMvc, Security, Data и кучу всего прочего, что бут настраивает по умолчанию.
            Вы до этого со спрингом много работали? «Чехарда с xml и аннотациями» вообще не должна возникать — в новом проекте должно использоваться либо то, либо другое.
            • 0
              почему смешанное использование xml и аннотаций это чехарда? и почему либо одно либо другое?
              • 0
                Чехарда — это цитата из первого комментария ветки — поленился правильно выделить.
                Смешивание разных способов конфигурации почти всегда усложняет структуру приложения. Поначалу кажется, что «а ладно, здесь я проще добавлю xml с нэймспейсом», а через год-другой там уже десятки файлов от разных разработчиков друг друга дёргают. Это в худшем случае, конечно, но всё равно лишний риск.
            • 0
              со спрингом работал много
              когда я попытался сделать standalone rest сервер который бы отдавал не только crud, но и немного логики, я был сильно огорчён тем, что всё снова пришлось делать руками, и тогда нет разницы, использовать spring boot или, например, jersey
              • 0
                А, тогда не спорю. Преимущество бута, на мой взгляд, в том, что можно быстро получить рабочую версию приложения, а потом уже, по мере необходимости, настраивать её под себя. Время, затрачиваемое на настройку не исчезает, но более плавно распределяется по периоду разработки.
        • 0
          У меня Thymeleaf в одном из проектов. Дорабатывался легко.
          Да с автоконфигурациями можно наступить на грабли, если нужно что-то конкретно переделать, но в таком случае, лучше отключить нужную автоконфигурацию и написать свою с нуля.
          • 0
            Я долго разбирался, как сделать своё переписывание ссылок внутри @{}. В итоге остановился на костыльной обёртке вокруг CsrfRequestDataValueProcessor. Наверно, это можно как-то сделать через диалекты и процессоры атрибутов, но пока и так сойдёт.
  • +4
    Я вот в новом проекте на спринге сделал Java-конфигурацию, а она не подхватилась Idea нормально, Thymeleaf-шаблоны нормально не навигируются. Буду переделывать на XML, удобство превыше всего. Ещё транзакционные настройки через aspectJ не задаются в Java Config, только в XML.

    Да и не видел я никогда в XML ничего плохого, честно говоря. Просто модно его хаять, вот и всё. Формат, как формат, с хорошим редактором очень даже удобный.
    • 0
      Его, собственно, и не любят за:
      — многословность,
      — неудобство редактирования без специализированного редактора.
      • –3
        Выходит — за то же за что и Java'у )
    • +2
      Кстати, на одном видео с jug.ru был показан бенчмарк, в котором java-конфигурация загружалась медленнее, чем xml.

      Мне еще нравится xml тем, что при необходимости, можно залезть в war-ку, и в xml законфигурировать разные параметры, и все это заработает без перекомпиляции. Незаслуженно недооценивают xml (те, кто его хаят).
      • +1
        Ничего страшного. Временем загрузки можно и пожертвовать. В джава конфигах еще и проксей по-моему много создается, поэтому вызов вашего метода тоже замедляется. Мне нравится практика скрещивания описаний, что-то в xml, что-то аннотациями. В последнее время смотрю уже на groovy конфиг. Скорее бы идея с ним научилась нормально работать)
  • 0
    Есть видео, как за 20 минут сделать минимальный проект с базой данных на scala и play www.youtube.com/watch?v=eNCerkVyQdc
    Есть аналогичные про python+django, есть про GWT, vaadin и много других. А вот видео про то, как сделать чего-то осязаемое на spring за 10-20 минут или даже за час я не нашёл, хоть и старался. О чём-то это говорит.
    • 0
      куплю книжку «Spring Framework For Dummies» — добавлю в коллекцию к «Java Programming. 24-Hour Trainer»
    • 0
      Видел как-то в официальном блоге Spring.io:
      Screencast: How to create a RESTful app in five minutes or less
    • 0
      В случае thymeleaf вам нужно подрубить только зависимость и написать main класс. Минимальный проект выходит за 1 минуту. Хотя это смотря, что считать «минимальным проектом»
  • +1
    Просто Spring это не игрушка на 20 минут. Это, безусловно, сложный инструмент, но одновременно и очень мощный, с огромными возможностями. Ведь на Boeing тоже не учат летать за 20 минут
  • 0
    Пишу уже второй небольшой проект (на буте + ангуляре) в свободное от работы время. Когда искал на что бы пересесть кроме приевшегося jee стека, наткнулся на спринг бут, и остался очень доволен. Используя только spring.io с документашками, поднял всё что мне было нужно и без особых проблем. Самый большой затык был разве что в data rest. Долго не мог понять почему не получалось сменить base url для рестов. В остальном вещь просто отличная. Если добавить генерилку jpa сущностей, то по уровню spring boot можно сравнить с обычным скаффолдингом в рельсах.
    • 0
      Дык entity может идея из базы сгенерить)
      • 0
        Но для этого надо сделать базу, а это тоже иногда лень ) Мне проше писать сучности jpa и потом уже в базу сливать )
        А в большом проекте всё равно как-то лучше вначале нарисовать примерную uml с классами и по ней нагенерить.
  • 0
    Используем Spring Boot в своих проектах, в целом удобно, но кастомизация — боль.
    Однако для своих маленьких проектов он удобен. Если надо что-то быстро запустить — лучший выбор.
    Лично для меня, само собой.
    • 0
      А уточните в чем конкретно боль, возможно уже пройденные грабли.
      • 0
        Довольно сложно настроить под себя. Он уже идет с набором библиотек и стандартных конфигов, если надо что-то свое, то настройка превращается в исключение зависимостей и выключение некоторых функций, плюс громоздкие конструкции вида
        @ComponentScan(basePackages = {"my.company"},
                excludeFilters = {
                        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ApiGlobalMethodSecurityConfiguration.class),
                        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ApiGlobalMethodSecurityConfiguration.ApiWebSecurityConfigurationAdapter.class)
                }
        )
        @EnableAutoConfiguration(exclude = {WebMvcAutoConfiguration.class})
        @ImportResource({"classpath:portal-hazelcast.xml", "classpath:springmvc-resteasy.xml"})
        @EnableCaching
        

        или
            @Bean
            public EmbeddedServletContainerCustomizer containerCustomizer() {
        
                return new EmbeddedServletContainerCustomizer() {
        
                    @Override
                    public void customize(ConfigurableEmbeddedServletContainer factory) {
                        if (factory instanceof TomcatEmbeddedServletContainerFactory) {
                            TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) factory;
                            LOG.info("SSL {}", sslEnabled ? "enabled" : "disabled");
                            if (sslEnabled) {
        
                                LOG.info("Using keystore {}", getKeystorePath());
        
                                containerFactory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
        
                                    @Override
                                    public void customize(Connector connector) {
                                        connector.setSecure(true);
                                        connector.setScheme("https");
                                        connector.setAttribute("keyAlias", keyAlias);
                                        connector.setAttribute("keystorePass", keystorePass);
                                        try {
                                            final File file = ResourceUtils.getFile(getKeystorePath());
                                            if (!file.exists()){
                                                throw new FileNotFoundException(getKeystorePath() + " is not found");
                                            }
                                            connector.setAttribute("keystoreFile", file.getAbsolutePath());
                                        } catch (FileNotFoundException e) {
                                            throw new IllegalStateException("Cannot load keystore:" + e.getMessage(), e);
                                        }
                                        connector.setAttribute("clientAuth", "false");
                                        connector.setAttribute("sslProtocol", "TLS");
                                        connector.setAttribute("SSLEnabled", true);
                                    }
                                });
                            }
                        }
                    }
                };
            }
        
        
  • 0
    Не знаю насколько оправдано использование Spring Boot. Для реального проекта не принципиально, потрачу ли я десять минут на подключение зависимостей и написание конфигурации. Также не могу понять полезность spring-boot:run если всю жизнь можно было пускать embedded Jetty container из main(). В большом проекте с кучей профайлов и зависимостей сведется на нет все преимущества автоконфигурирования.
  • –1
    Простите, не нашел ссылки на оригинал
    • +1
      В самой нижней части статьи (там, где отображается количество просмотров и т.п.) есть ссылка «Steve Perkins»
      • –1
        Спасибо:)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.