Я думаю, было бы справедливо заявить, что мы, как разработчики программного обеспечения, всегда ищем способы написать меньше кода, который делает больше вещей, автоматически или нет. В связи с этим проект Spring Boot , являющийся гордым участником портфолио Spring , нарушил традиционные подходы, резко ускорив и упростив разработку приложений на основе Spring .
О Spring Boot можно многое сказать, о внутренних деталях его работы и его плавной интеграции с большинством, если не со всеми проектами Spring . Но его возможности выходят далеко за рамки этого, поддерживая первоклассную интеграцию с популярными средами Java.
В этой статье мы рассмотрим, как мы можем использовать Spring Boot в сочетании с проектом Apache CXF для быстрой разработки REST (ful) веб-сервисов . Как мы увидим очень скоро, Spring Boot позаботится о большом количестве шаблонов, что позволит нам сосредоточиться на тех частях приложения, которые действительно имеют ценность. Надеемся, что в конце этого поста преимущества использования Spring Boot для ваших проектов станут очевидными.
После этого давайте начнем с разработки простого веб-сервиса REST (ful) для управления персоналом, включенного в привычный ресурс PeopleRestService JAX-RS :
|
1
2
3
4
5
6
7
8
9
|
@Path("/people")@Componentpublic class PeopleRestService { @GET @Produces({MediaType.APPLICATION_JSON}) public Collection<Person> getPeople() { return Collections.singletonList(new Person("a@b.com", "John", "Smith")); }} |
Добавлять особо нечего, довольно простая реализация, которая возвращает жестко запрограммированную коллекцию людей. Мы можем упаковать и развернуть этот сервис JAX-RS несколькими способами, но, пожалуй, самый простой из них — разместить его во встроенном контейнере сервлетов, таком как Tomcat , Jetty или Undertow . С этим приходит рутина: инициализация контейнера, настройка местоположений контекста Spring , регистрация слушателей,… Давайте посмотрим, как Spring Boot может помочь здесь, рассмотрев конфигурацию контекста Spring ниже.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
@Configuration@EnableAutoConfiguration@ComponentScan(basePackageClasses = PeopleRestService.class)public class AppConfig { @Autowired private PeopleRestService peopleRestService; @Bean(destroyMethod = "shutdown") public SpringBus cxf() { return new SpringBus(); } @Bean(destroyMethod = "destroy") @DependsOn("cxf") public Server jaxRsServer() { final JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean(); factory.setServiceBean(peopleRestService); factory.setProvider(new JacksonJsonProvider()); factory.setBus(cxf()); factory.setAddress("/"); return factory.create(); } @Bean public ServletRegistrationBean cxfServlet() { final ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new CXFServlet(), "/api/*"); servletRegistrationBean.setLoadOnStartup(1); return servletRegistrationBean; }} |
Класс AppConfig выглядит как типичная конфигурация на основе Spring Java, за исключением этой необычной аннотации @EnableAutoConfiguration , которая без удивления приходит из модуля Spring Boot . Под капотом эта аннотация обеспечивает сложный и интеллектуальный процесс предположения, среди прочего, о том, какое приложение мы будем запускать и какие компоненты Spring нам могут понадобиться для нашего приложения. С этой конфигурацией нам просто нужен бегун для нашего приложения, также с небольшим количеством Spring Boot :
|
1
2
3
4
5
6
|
@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(AppConfig.class, args); }} |
Имея мета-аннотацию @SpringBootApplication и используя SpringApplication для инициализации нашего контекста Spring , у нас есть полноценное работающее Java-приложение, которое можно запустить из Apache Maven с помощью плагина Spring Boot :
|
1
|
mvn spring-boot:run |
Или упакован как один работающий Uber- JAR и вызывается из командной строки:
|
1
2
|
mvn packagejava -jar target/jax-rs-2.0-cxf-spring-boot-0.0.1-SNAPSHOT.jar |
И это все, просто пара аннотаций вместе с одной строкой кода ( основной метод). Запустив приложение, мы сможем убедиться, что наш веб-сервис REST (ful) для управления персоналом правильно развернут и полностью функционирует:
|
1
2
3
4
5
6
7
8
|
$ curl -i http://localhost:8080/api/peopleHTTP/1.1 200 OKContent-Type: application/json;charset=utf-8Transfer-Encoding: chunkedServer: Jetty(9.3.8.v20160314)[{"email":"a@b.com","firstName":"John","lastName":"Smith"}] |
На данный момент вы можете спросить, как это работает? Мы нигде не имели дело с контейнером сервлетов, так почему же Jetty обслуживает наши запросы? По правде говоря, нам нужно только включить наш контейнер выбора в качестве зависимости, например, используя файл Apache Maven pom.xml :
|
1
2
3
4
5
|
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.3.8.v20160314</version></dependency> |
Spring Boot вместе с @ EnableAutoConfiguration / @ SpringBootApplication делает все остальное: он обнаруживает присутствие Jetty в пути к классам, приходит к обоснованному выводу, что мы намерены запустить веб-приложение и дополнить контекст Spring необходимыми элементами. Разве это не просто великолепно?
Было бы несправедливо заканчивать, не освещая еще одну важную особенность проекта Spring Boot : поддержку интеграционного тестирования. В этом отношении Spring Boot использует тот же подход и предоставляет несколько аннотаций, чтобы снять все строительные леса, которые мы должны были бы написать сами, в противном случае. Например:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes = AppConfig.class)@WebIntegrationTest(randomPort = true)public class PeopleRestServiceIntegrationTest { @Value("${local.server.port}") private int port; @Before public void setUp() { RestAssured.port = port; } @Test public void testListOfPersonsIsBeingReturnedSuccessfuly() { given() .when() .contentType(ContentType.JSON) .get("/api/people") .then() .statusCode(200) .log() .ifValidationFails(); }} |
Всего две аннотации: @SpringApplicationConfiguration (обратите внимание, что мы используем ту же конфигурацию в тесте, что и для основного приложения) и @WebIntegrationTest (которая учитывает специфику тестирования веб-приложения и запускает встроенный контейнер сервлета на случайном порте), и у нас есть полноценный интеграционный тест с нашей службой управления JAX-RS . Порт, на котором работает контейнер сервлета, доступен через свойство среды local.server.port, поэтому мы можем настроить REST-гарантированный в фоновом режиме тестирования. Легко и просто.
В этой статье мы только что рассмотрели один конкретный случай использования Spring Boot для увеличения скорости разработки ваших проектов JAX-RS . С Spring Boot многие вещи становятся очень тривиальными, с каждым разом добавляется все больше и больше интеллекта, не говоря уже об отличной интеграции с выбранной вами IDE. Я надеюсь, что вы действительно взволнованы Spring Boot и хотите узнать больше об этом. Это стоит времени и усилий.
Полный проект доступен на Github .
| Ссылка: | Лень в крайности: разработка сервисов JAX-RS с Spring Boot от нашего партнера по JCG Андрея Редько в блоге Андрея Редько . |