четверг, 30 июля 2015 г.

Spring Boot на примере простого REST-сервиса

Последние пару месяцев я активно изучаю Spring Boot и перевожу некоторые из своих проектов на эту архитектуру. В этом посте я в кратце опишу создание простого приложения на Spring Boot.

Стартеры и зависимости

Разработчики Spring Boot постарались по максимуму уменьшить время, уходящее на конфигурирование проекта, добавив в Maven артефакты spring-boot-starter-* из группы org.springframework.boot. По сути это зависимости, которые тянут за собой остальные зависимости, необходимые для разработки приложения нужного типа. Подробнее со списком доступных стартеров можно ознакомиться в официальной документации по Spring Boot.

Хотя, если вы хотите самостоятельно указывать используемые зависимости, можно не использовать стартеры, а указать в зависимостях артефакт spring-boot-autoconfigure из org.springframework.boot. Но в целом стартеры очень удобны.

Приложение

В данном примере я буду использовать единственную зависимость:
<dependencies>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
        <version>1.2.5.RELEASE</version>
    </dependency>
</dependencies> 
Она за собой потянет всё необходимое для написания простого веб-приложения.

Так как это standalone-приложение, нам потребуется стадартый класс с методом main:
package name.alexkosarev.sandbox.springboot.rest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args).registerShutdownHook();
    }
}
В данном случае аннотация @SpringBootApplication заменяет собой аннотации @Configuration, @EnableAutoConfiguration и @ComponentScan.

В моём примере REST-сервис будет возвращать объект простого класса, в котором будет текстовое сообщение:

package name.alexkosarev.sandbox.springboot.rest.wrappers;

public class MessageWrapper {

    private String message;

    public MessageWrapper() {
    }

    public MessageWrapper(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

Теперь нужно добавить контроллер, который будет обрабатывать запрос и возвращать ответ:
package name.alexkosarev.sandbox.springboot.rest.services;

import name.alexkosarev.sandbox.springboot.rest.wrappers.MessageWrapper;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/example")
public class ExampleService {

    @RequestMapping
    public MessageWrapper index() {
        return new MessageWrapper("Hello world!");
    }
}

Аннотация @RestController комбинирует в себе @Controller и @ResponseBody, указывая, что данный контроллер является REST-контроллером и возвращаемые значения методов данного класса, помеченных аннотацией @RequestMapping, будут ответами на HTTP-запросы.

Теперь можно запустить приложение и открыть адрес http://localhost:8080/example. В ответ будет выведено {"message":"Hello world!"}.

МегаJAR

Это конечно, круто, скажите вы, но теперь у нас есть JAR с приложением и горстка JAR с зависимостями. Можно ли как-то с этим бороться? Да, можно. Разработчики Spring предлагают 2 варианта решения данной проблемы:
  1. Поместить все JAR зависимостей в директорию lib внутри JAR проекта, что не очень правильно
  2. Добавить в Maven-плагин spring-boot-maven-plugin из группы org.springframework.boot с целью repackage, в результате чего в директории target будет лежать 2 JAR: обычный и толстый, в который будут скопировано содержимое всех JAR зависимостей.
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>1.2.5.RELEASE</version>
    <executions>
        <execution>
   <goals>
       <goal>repackage</goal>
   </goals>
        </execution>
    </executions>
</plugin>

Комментариев нет:

Отправить комментарий