API на Java: REST, GraphQL, gRPC — что выбрать в 2025?

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: эволюция API на Java

Мир Java-разработки не стоит на месте. Ещё 10 лет назад выбор был очевиден: REST и JSON. Сегодня же, проектируя микросервисную архитектуру или мобильное приложение, разработчик сталкивается с целым зоопарком протоколов. REST, GraphQL, gRPC — каждый из них обещает райские кущи, но в реальности за каждой технологией стоят компромиссы.

В этой статье мы не будем пересказывать документацию. Мы возьмём живую задачу: нам нужно создать API для образовательной платформы (как наш PythonLib, только на Java). У нас есть курсы, студенты и прогресс обучения. И мы попробуем реализовать один и тот же endpoint тремя разными способами.

Поехали разбираться, какой протокол сделает ваш код быстрее, а жизнь — проще.

REST API на Java: классика, которая не умирает

REST (Representational State Transfer) — это архитектурный стиль, а не протокол. В Java стандартом де-факто для REST стал Spring Boot с его аннотациями. Простота, понятность, огромное комьюнити — вот за что мы любим REST.

Пример: получаем список курсов

Допустим, нам нужно отдать клиенту список всех курсов с базовой информацией:

@RestController
@RequestMapping("/api/courses")
public class CourseController {

    @GetMapping
    public ResponseEntity<List<CourseDTO>> getAllCourses() {
        List<Course> courses = courseService.findAll();
        List<CourseDTO> dtos = courses.stream()
                .map(c -> new CourseDTO(c.getId(), c.getTitle(), c.getAuthor()))
                .toList();
        return ResponseEntity.ok(dtos);
    }
}

Клиент получает JSON:

[
  {"id": 1, "title": "Java для начинающих", "author": "Иван Петров"},
  {"id": 2, "title": "Spring Boot Masterclass", "author": "Анна Смирнова"}
]

Плюсы REST на Java:

  • Минимальный порог входа — любой Java-разработчик знает Spring.
  • Кэширование через HTTP-заголовки (ETag, Cache-Control).
  • Широкая поддержка инструментов (Postman, Swagger, OpenAPI).

Минусы:

  • Проблема over-fetching (лишние данные) и under-fetching (не хватает данных, нужно делать несколько запросов).
  • Слабая типизация — всё решает контракт, который легко нарушить.

REST идеален для публичных API, когда клиенты — третьи лица, и вам нужна максимальная совместимость. Но если ваш клиент — мобильное приложение, которое хочет получать ровно то, что нужно, REST начинает раздражать.

GraphQL на Java: дайте мне только то, что я прошу

GraphQL — это язык запросов, созданный Facebook. В Java его чаще всего реализуют через библиотеку graphql-java или интеграцию с Spring — GraphQL Kickstart.

Клиент сам решает, какие поля ему нужны. Никакого over-fetching. Один запрос — и ты получаешь курсы вместе с прогрессом студента.

Пример: GraphQL schema и resolver

Определяем схему:

type Course {
    id: ID!
    title: String!
    author: String!
    progress(studentId: ID!): Int
}

type Query {
    courses: [Course!]!
}

Пишем резолвер на Java:

@Component
public class CourseResolver implements GraphQLQueryResolver {

    @Autowired
    private CourseService courseService;

    public List<Course> courses() {
        return courseService.findAll();
    }
}

@Component
public class CourseFieldResolver implements GraphQLResolver<Course> {

    @Autowired
    private ProgressService progressService;

    public Integer progress(Course course, Long studentId) {
        return progressService.getProgress(course.getId(), studentId);
    }
}

Запрос от клиента:

query {
  courses {
    title
    progress(studentId: 42)
  }
}

Ответ — только title и прогресс. Никаких лишних полей.

Плюсы GraphQL на Java:

  • Гибкость запросов — один endpoint решает всё.
  • Сильная типизация схемы (SDL) — меньше ошибок на стыке фронта и бэка.
  • Отличная документация через GraphiQL или Voyager.

Минусы:

  • Сложность кэширования на уровне HTTP (POST-запросы, динамические ответы).
  • Риск N+1 проблемы — если не использовать DataLoader, каждый запрос к БД будет множиться.
  • Кривая обучения для команды, привыкшей к REST.

GraphQL — выбор для сложных клиентских приложений с динамическими интерфейсами. Например, дашборды или мобильные приложения с разными ролями пользователей.

gRPC на Java: скорость и строгость контрактов

gRPC — это RPC-фреймворк от Google, использующий Protocol Buffers (protobuf) для сериализации и HTTP/2 для транспорта. В Java он живёт через библиотеку io.grpc.

Если вам нужно передавать гигабайты данных между микросервисами с минимальной задержкой — gRPC ваш выбор. Здесь нет человекочитаемого JSON, зато есть бинарный протокол и строгий контракт.

Пример: gRPC сервис на Java

Сначала описываем proto-файл:

syntax = "proto3";

service CourseService {
    rpc GetCourse (CourseRequest) returns (CourseResponse);
}

message CourseRequest {
    int32 id = 1;
}

message CourseResponse {
    int32 id = 1;
    string title = 2;
    string author = 3;
}

Генерируем Java-классы (через Maven/Gradle плагин) и реализуем сервис:

public class CourseServiceImpl extends CourseServiceGrpc.CourseServiceImplBase {

    @Override
    public void getCourse(CourseRequest request, 
                          StreamObserver<CourseResponse> responseObserver) {
        Course course = courseService.findById(request.getId());
        CourseResponse response = CourseResponse.newBuilder()
                .setId(course.getId())
                .setTitle(course.getTitle())
                .setAuthor(course.getAuthor())
                .build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}

Клиент вызывает метод как локальный:

ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080)
        .usePlaintext()
        .build();
CourseServiceGrpc.CourseServiceBlockingStub stub = CourseServiceGrpc.newBlockingStub(channel);
CourseResponse response = stub.getCourse(CourseRequest.newBuilder().setId(1).build());
System.out.println(response.getTitle());

Плюсы gRPC на Java:

  • Высокая производительность (бинарный протокол, HTTP/2, потоковая передача).
  • Автоматическая генерация кода из proto-файлов — контракт всегда в актуальном состоянии.
  • Поддержка стриминга (server-streaming, client-streaming, bidirectional).

Минусы:

    <

Блоги

Рекомендаций по книгам