Ресурсы Jakarta REST
Сервлеты дают полный контроль над HTTP, но для API это слишком низкий уровень: адреса и параметры приходится разбирать вручную. Jakarta REST (раньше называлась JAX-RS) позволяет описать API аннотациями. Класс, который обслуживает группу адресов, называется ресурсом, а его методы — обработчиками запросов.
Включение REST
Сначала нужен класс, который включает Jakarta REST и задаёт общий префикс адресов. Генератор Open Liberty создаёт его сам; в нашем пакете он выглядит так:
// src/main/java/com/example/blog/RestApplication.java
package com.example.blog;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
@ApplicationPath("/api")
public class RestApplication extends Application {
}Класс пустой: сервер найдёт все ресурсы в приложении сам. Аннотация @ApplicationPath("/api") означает, что адреса API начинаются с http://localhost:8080/blog/api.
Первый ресурс
Создайте файл src/main/java/com/example/blog/PostResource.java:
// src/main/java/com/example/blog/PostResource.java
package com.example.blog;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/posts")
public class PostResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String list() {
return "Список записей";
}
}@Path("/posts") привязывает класс к адресу /api/posts. @GET говорит, что метод отвечает на GET-запросы, а @Produces — какой тип содержимого он возвращает. Строку, которую вернул метод, Jakarta REST сам запишет в тело ответа.
curl -i http://localhost:8080/blog/api/postsHTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
Список записей
Аннотации методов
| Аннотация | Метод HTTP | Типичное действие |
|---|---|---|
@GET | GET | Получить данные |
@POST | POST | Создать запись |
@PUT | PUT | Заменить запись |
@PATCH | PATCH | Изменить часть записи |
@DELETE | DELETE | Удалить запись |
@Path можно ставить и на метод — тогда его путь добавляется к пути класса. Метод с @Path("/latest") в нашем классе ответит на /api/posts/latest.
Типы содержимого
| Константа | Значение |
|---|---|
MediaType.TEXT_PLAIN | text/plain |
MediaType.TEXT_HTML | text/html |
MediaType.APPLICATION_JSON | application/json |
@Produces можно поставить на весь класс — тогда он действует для всех методов. Для API блога это будет APPLICATION_JSON, когда в следующих уроках мы начнём отдавать данные.
Сервлет или ресурс
| Сервлет | Ресурс Jakarta REST |
|---|---|
| Один класс на адрес | Много адресов в одном классе |
| Параметры читаются вручную | Параметры приходят аргументами метода |
| JSON собирается вручную | Объекты превращаются в JSON сами |
Для API почти всегда выбирают ресурсы. Сервлеты остаются для особых случаев: отдача файлов, фильтры, низкоуровневая работа с потоком.
Частая ошибка
Забыть класс с @ApplicationPath. Тогда Jakarta REST в приложении не включится, и сервер будет искать по адресу /api/posts обычный файл:
Error 404: jakarta.servlet.ServletException: java.io.FileNotFoundException: SRVE0190E: File not found: /api/posts
Если все адреса API отвечают 404, первым делом проверьте класс RestApplication.