Создание RESTful web-сервиса с Spring Boot Actuator
Spring Boot Actuator является подпроектом Spring Boot. Он добавляет несколько сервисов бизнес-уровня без особых усилий с вашей стороны. В этом уроке вы создадите приложение и увидите, как добавить эти сервисы.
Что вы создадите
В этом уроке освещаются шаги создания "hello world" RESTful Web Service c использованием Spring Boot Actuator. Вы создадите сервис, который принимает HTTP GET запрос:
$ curl http://localhost:9000/hello-world
А в ответ возвращает JSON:
{"id":1,"content":"Hello, World!"}
Также есть некоторые возможности для вашего приложения "из коробки" управлять сервисом в рабочем (или других) окружениях. Бизнес логика сервиса построена так же, как в Создание RESTful Web-сервиса. Вам необязательно использовать это руководство для изучения, однако это может быть интересным, чтобы впоследствии сравнить результаты.
Что вам потребуется
- Примерно 15 минут свободного времени
- Любимый текстовый редактор или IDE
- JDK 7 и выше
- Gradle 1.11+ или Maven 3.0+
- Вы также можете импортировать код этого урока, а также просматривать web-страницы прямо из Spring Tool Suite (STS), собственно как и работать дальше из него.
Как проходить этот урок
Как и большинство уроков по Spring, вы можете начать с нуля и выполнять каждый шаг, либо пропустить базовые шаги, которые вам уже знакомы. В любом случае, вы в конечном итоге получите рабочий код.
Чтобы начать с нуля, перейдите в Настройка проекта.
Чтобы пропустить базовые шаги, выполните следующее:
- Загрузите и
распакуйте архив с кодом этого урока, либо кнонируйте из репозитория с помощью
Git:
git clone https://github.com/spring-guides/gs-actuator-service.git
- Перейдите в каталог
gs-actuator-service/initial
- Забегая вперед, создайте класс представления
Когда вы закончите, можете сравнить получившийся результат с образцом в gs-actuator-service/complete
.
Настройка проекта
Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle и Maven. Если вы не знакомы ни с одним из них, ознакомьтесь с соответсвующими уроками Сборка Java-проекта с использованием Gradle или Сборка Java-проекта с использованием Maven.
Создание структуры каталогов
В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру,
командой mkdir -p src/main/java/hello
для *nix систем:
└── src └── main └── java └── hello
Создание файла сборки Gradle
Ниже представлен начальный файл сборки Gradle. Файл pom.xml находится здесь. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.
pom.xml
, вы найдете, что указана версия для maven-compiler-plugin.
В общем, это не рекомендуется делать. В данном случае он предназначен для решения проблем с нашей CI системы,
которая по умолчанию имеет старую(до Java 5) версию этого плагина.
build.gradle
buildscript {
repositories {
maven { url "http://repo.spring.io/libs-release" }
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.8.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
jar {
baseName = 'gs-actuator-service'
version = '0.1.0'
}
repositories {
mavenLocal()
mavenCentral()
maven { url "http://repo.spring.io/libs-release" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile("junit:junit")
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
Spring Boot gradle plugin предоставляет множество удобных возможностей:
- Он собирает все jar'ы в classpath и собирает единое, исполняемое "über-jar", что делает более удобным выполнение и доставку вашего сервиса
- Он ищет
public static void main()
метод, как признак исполняемого класса - Он предоставляет встроенное разрешение зависимостей, с определенными номерами версий для соответсвующих Spring Boot зависимостей. Вы можете переопределить на любые версии, какие захотите, но он будет по умолчанию для Boot выбранным набором версий
Запуск пустого сервиса
Ниже представлено пустое Spring MVC приложение.
src/main/java/hello/HelloWorldConfiguration.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class HelloWorldConfiguration {
public static void main(String[] args) {
SpringApplication.run(HelloWorldConfiguration.class, args);
}
}
Аннотация @EnableAutoConfiguration
обеспечивает загрузку по умолчанию
(подобно встроенному сервлет контейнеру) в зависимости от содержания вашего classpath
и других вещей. Она также ключает Spring MVC @EnableWebMvc
аннотацию
для активации web компонентов.
Не все компоненты определены в этом приложении, но этого достаточно для запуска и
просмотра некоторых возможностей Actuator'а. Команда SpringApplication.run()
знает как запустить web приложение. Все, что вам нужно, это запустить команду:
$ ./gradlew clean build && java -jar build/libs/gs-actuator-service-0.1.0.jar
Вы ещё не писали код, так что же случится? Подождите, пока сервер запустится, перейдите в терминал и попробуйте выполнить:
$ curl localhost:8080 {"timestamp":1384788106983,"error":"Not Found","status":404,"message":""}
Итак, сервер запущен, но вы пока не определили ни одну точку выхода бизнес логики. Поэтому по умолчанию
контейнер генерирует HTML ответ ошибки, вы видите общий JSON ответ из Actuator точки выхода /error
.
Попробуйте что-то другое, например:
$ curl localhost:8080/health ok
Вы получили "ОК", значит все хорошо.
Более подробную информацию смотрите на Spring Boot Actuator Project.
Создание класса представления
Для начала, давайте подумаем, как будет выглядеть ваше API.
Вы хотите обрабатывать GET запросы для /hello-world
, дополнительно с учетом параметра name.
В ответ на этот запрос вы будете отправлять JSON, представляющий сообщение, которое выглядит примерно так:
{
"id": 1,
"content": "Hello, World!"
}
Поле id
является уникальным идентификатором сообщения, а content
- текстовым
представлением.
Для моделирования представления сообщения, создайте класс представления:
src/main/java/hello/Greeting.java
package hello;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
Теперь вам нужно создать контроллер точки выхода, который будет обслуживать этот класс.
Создание контроллера ресурсов
В Spring, точки выхода REST - это просто Spring MVC контроллеры. Представленный ниже
Spring MVC контроллер обрабатывает GET запрос для /hello-world
и возвращает
ресурс Greeting
:
src/main/java/hello/HelloWorldController.java
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/hello-world")
public class HelloWorldController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping(method=RequestMethod.GET)
public @ResponseBody Greeting sayHello(@RequestParam(value="name", required=false, defaultValue="Stranger") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
Ключевое отличие между обычным(human-facing) контроллером и REST контроллером в том, как создан ответ. Вместо того, чтобы опираться на представление(такое как JSP) для отображения данных модели в HTML, REST контроллер просто возвращает данные, записанные прямо в тело ответа.
Аннотация @ResponseBody
говорит Spring MVC не отображать модель в представлении, а писать возвращаемый объект в тело ответа.
Делается это с помощью одного из ковертеров сообщений Spring. Т.к. Jackson 2 находится в classpath,
то значит MappingJackson2HttpMessageConverter
будет обрабатывать конвертацию Greeting в JSON при условии, что заголовок Accept
запроса
указывает, что необходимо вернуть JSON.
mvn dependency:tree
или
./gradlew dependencies
, то можно увидеть подробное дерево зависимостей, в котором есть
Jackson 2. Вы также можете увидеть, что он идет в составе spring-boot-starter-web.
Создание выполняемым главный класс
Вы можете запустить приложение из собственного главного класса, либо мы можем сделать это напрямую
из одного из конфигурационных классов. Самым простым способом является использование вспомогательного
класса SpringApplication
:
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
В обычном Spring MVC приложении вы должны добавлять @EnableWebMVC
для
включения ключевого поведения, включая конфигурацию на DispatcherServlet
.
Но Spring Boot подключает эту аннотацию автоматически, когда обнаруживает spring-webmvc
в вашем classpath. Это позволяет собрать контроллер в последующем этапе.
Также присутствует аннотация @componentScan
, которая говорит Spring сканировать пакет
hello
на контроллеры(вместе с другими аннотированными компонентом классами).
Сборка исполняемого JAR
Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.
./gradlew build
Затем вы можете запустить JAR-файл:
java -jar build/libs/gs-actuator-service-0.1.0.jar
Если вы используете Maven, вы можете запустить приложение, используя mvn spring-boot:run
,
либо вы можете собрать приложение с mvn clean package
и запустить JAR примерно так:
java -jar target/gs-actuator-service-0.1.0.jar
Запуск сервиса
Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:
./gradlew clean build && java -jar build/libs/gs-actuator-service-0.1.0.jar
mvn clean package && java -jar target/gs-actuator-service-0.1.0.jar
.
Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:
./gradlew bootRun
mvn spring-boot:run
.... service comes up ...
Протестируем:
$ curl localhost:8080/hello-world {"id":1,"content":"Hello, Stranger!"}
Переключение на другой порт сервера
Spring Boot Actuator по умолчанию запускается на порте 8080. Добавив файл application.properties
,
вы можете переопределить эту настройку.
src/main/resources/application.properties
server.port: 9000
management.port: 9001
management.address: 127.0.0.1
Запустите сервер снова:
$ ./gradlew clean build && java -jar build/libs/gs-actuator-service-0.1.0.jar ... service comes up on port 9000 ...
Протестируем:
$ curl localhost:8080/hello-world curl: (52) Empty reply from server $ curl localhost:9000/hello-world {"id":1,"content":"Hello, Stranger!"}
Итог
Поздравляем! Вы только что разработали простой RESTful сервис, используя Spring. Вы добавили некоторые полезные встроенные сервисы благодаря Spring Boot Actuator.
С оригинальным текстом урока вы можете ознакомиться на spring.io.
comments powered by Disqus