Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Адреса, параметры пути и строки запроса

Одного адреса со списком мало: нужно открыть конкретную статью и отфильтровать список. Номер статьи обычно передают частью пути — /api/posts/2, а необязательные условия — в строке запроса после ?: /api/posts?author=anna. Spring умеет доставать оба вида параметров прямо в аргументы метода.

Общий префикс

Чтобы не повторять /api/posts в каждом методе, адрес ставят над классом:

// src/main/java/com/example/blog/PostController.java
@RestController
@RequestMapping("/api/posts")
public class PostController {
 
    private final PostService postService;
 
    public PostController(PostService postService) {
        this.postService = postService;
    }
 
    @GetMapping
    public List<Post> list() {
        return postService.findAll();
    }
}

@RequestMapping("/api/posts") задаёт префикс для всех методов класса, а пустой @GetMapping означает сам префикс, то есть GET /api/posts.

Параметр пути

// src/main/java/com/example/blog/PostController.java
@GetMapping("/{id}")
public Post show(@PathVariable Long id) {
    return postService.findById(id);
}

Фигурные скобки в адресе объявляют переменную часть. @PathVariable кладёт её значение в аргумент с тем же именем и сам переводит текст "2" в число Long. В сервисе добавим поиск по номеру:

// src/main/java/com/example/blog/PostService.java
public Post findById(Long id) {
    return repository.findById(id)
            .orElseThrow(() -> new PostNotFoundException(id));
}
// src/main/java/com/example/blog/PostNotFoundException.java
package com.example.blog;
 
public class PostNotFoundException extends RuntimeException {
 
    public PostNotFoundException(Long id) {
        super("Статья " + id + " не найдена");
    }
}

Запрос curl http://localhost:8080/api/posts/2 вернёт статью номер 2. Для несуществующего номера пока придёт ошибка 500 — в уроке об обработке ошибок превратим её в понятный ответ 404.

Параметр строки запроса

// src/main/java/com/example/blog/PostController.java
@GetMapping
public List<Post> list(@RequestParam(required = false) String author) {
    return postService.findAll(author);
}
// src/main/java/com/example/blog/PostService.java
public List<Post> findAll(String author) {
    return repository.findAll().stream()
            .filter(post -> author == null || post.author().equals(author))
            .sorted(Comparator.comparing(Post::id))
            .limit(properties.pageSize())
            .toList();
}

@RequestParam берёт значение author из строки запроса. Без required = false параметр был бы обязательным. Когда статьи появятся, запрос curl "http://localhost:8080/api/posts?author=anna" вернёт только статьи Анны:

[{"id":1,"title":"Привет, Spring","body":"Первая статья","author":"anna","createdAt":"2026-10-04T08:50:07.494425300Z"}]

Адрес в кавычках, потому что знак ? и & командная оболочка может понять по-своему.

Значение по умолчанию

@RequestParam(defaultValue = "0") int page

Если параметра нет, Spring подставит 0. Такой параметр уже необязателен.

Аннотации для методов HTTP

АннотацияЗапросНазначение
@GetMappingGETПолучить данные
@PostMappingPOSTСоздать
@PutMappingPUTЗаменить целиком
@PatchMappingPATCHИзменить часть
@DeleteMappingDELETEУдалить

Частая ошибка

Если в путь вместо числа попал текст, например /api/posts/abc, Spring не сможет перевести его в Long и ответит 400:

{"timestamp":"2026-10-04T08:50:07.919Z","status":400,"error":"Bad Request","path":"/api/posts/abc"}

В журнале появится Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'. Это не ошибка в коде — клиент прислал неверный адрес.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.