Java for Beginner
677 subscribers
546 photos
155 videos
12 files
838 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Работа с HTTP-методами в Spring: GET, POST, PUT, DELETE

HTTP-методы (или «глаголы») — это действия, которые клиент может выполнять на ресурсе в веб-приложении. В контексте RESTful архитектуры, они представляют собой стандартные операции для взаимодействия с ресурсами.

Spring предоставляет удобный механизм работы с HTTP-методами через аннотации контроллеров, такие как @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, которые упрощают реализацию RESTful API.

Настройка HTTP-методов в Spring


Общий пример контроллера
@RestController
@RequestMapping("/api/users")
public class UserController {

@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return new User(id, "John Doe", "john@example.com");
}

@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
user.setId(1L); // Пример генерации ID
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}

@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return ResponseEntity.ok(user);
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
return ResponseEntity.noContent().build();
}
}


HTTP-методы


1. GET — Чтение данных

Назначение: Возвращает данные с сервера (например, список пользователей, детали одного пользователя).
Идемпотентный метод: Повторный вызов GET не изменяет состояние ресурса.


Пример запроса:
GET /api/users/1 HTTP/1.1
Host: example.com


Реализация в Spring:
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return new User(id, "John Doe", "john@example.com");
}


Особенности:
Используется аннотация @GetMapping.
Данные возвращаются в формате JSON или XML в зависимости от заголовка Accept.


2. POST — Создание нового ресурса
Назначение: Создает новый ресурс на сервере.
Не идемпотентный метод: Повторный вызов создаёт новые записи.


Пример запроса:
POST /api/users HTTP/1.1
Content-Type: application/json
Host: example.com

{
"name": "Jane Doe",
"email": "jane@example.com"
}


Реализация в Spring:

@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
user.setId(1L); // Симуляция сохранения с генерацией ID
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}


Особенности:
Используется аннотация @PostMapping.
Данные передаются через тело запроса (
@RequestBody).
В ответе часто возвращается код 201 Created и URL нового ресурса.


3. PUT — Обновление ресурса
Назначение: Обновляет существующий ресурс или создаёт его, если он не существует.
Идемпотентный метод: Повторный вызов приводит к тому же результату.


Пример запроса:
PUT /api/users/1 HTTP/1.1
Content-Type: application/json
Host: example.com

{
"name": "John Smith",
"email": "john.smith@example.com"
}


Реализация в Spring:
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id); // Симуляция обновления ресурса
return ResponseEntity.ok(user);
}


Особенности:
Используется аннотация @PutMapping.
Данные для обновления передаются через тело запроса.
В ответе обычно возвращается 200 OK с обновлённым ресурсом.


4. DELETE — Удаление ресурса
Назначение: Удаляет ресурс на сервере.
Идемпотентный метод: Повторный вызов приводит к тому же результату (ресурс уже удалён).


Пример запроса:
DELETE /api/users/1 HTTP/1.1
Host: example.com


Реализация в Spring:
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
return ResponseEntity.noContent().build();
}


Особенности:
Используется аннотация @DeleteMapping.
В ответе часто возвращается 204 No Content.


#Java #Training #Spring #GET #PUT #POST #DELETE
Примеры сложных сценариев

1. Обработка ошибок
Если ресурс не найден, можно вернуть соответствующий HTTP-ответ:
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return userService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).build());
}


2. Валидация данных

Использование @Valid для проверки корректности входящих данных:
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
user.setId(1L);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}


Пример ошибок валидации:
{
"timestamp": "2024-12-11T12:00:00",
"status": 400,
"errors": [
{
"field": "name",
"message": "Name is required"
}
]
}


3. Поддержка разных форматов данных
Spring поддерживает автоматическое преобразование данных в зависимости от заголовков запроса:
JSON (application/json)
XML (application/xml)


Пример настройки:
@GetMapping(value = "/{id}", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public User getUser(@PathVariable Long id) {
return new User(id, "John Doe", "john@example.com");
}


#Java #Training #Spring #GET #PUT #POST #DELETE
Что выведет код?

import java.util.HashSet;
import java.util.Set;

public class Task201224_1 {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(2);
set.add(1);

System.out.println(set.size());
}
}


#Tasks
Варинаты ответа:
Anonymous Quiz
30%
5
0%
4
70%
3
0%
2
И куча банков🙈😂

https://t.me/Java_for_beginner_dev

#Mems
Создание CRUD API в Spring

Разработка CRUD API (Create, Read, Update, Delete) — стандартная задача для построения RESTful приложений. Использование Spring Boot и PostgreSQL позволяет быстро и эффективно создать такое API.

Шаг 1: Создание проекта Spring Boot

Перейдите на Spring Initializr.

Выберите:
Project: Maven.
Language: Java.
Dependencies: Spring Web, Spring Data JPA, PostgreSQL Driver, Validation (для валидации данных).
Скачайте проект и откройте его в IDE.


Шаг 2: Настройка подключения к PostgreSQL

Добавьте настройки базы данных в файл application.properties.

Пример application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/my_database
spring.datasource.username=postgres
spring.datasource.password=password

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect


Расшифровка настроек:
spring.datasource.url: URL подключения к PostgreSQL (с указанием базы данных).
spring.jpa.hibernate.ddl-auto: Автоматическое управление схемой базы данных (update, create, none).
spring.jpa.show-sql: Показывать SQL-запросы в консоли.
spring.jpa.properties.hibernate.dialect: Dialect Hibernate для PostgreSQL.


Шаг 3: Создание сущности (Entity)

Сущность представляет таблицу в базе данных.
import jakarta.persistence.*;
import jakarta.validation.constraints.*;

@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank(message = "Name is mandatory")
private String name;

@Email(message = "Email should be valid")
@NotBlank(message = "Email is mandatory")
private String email;

@NotNull(message = "Age is mandatory")
private Integer age;
// Геттеры и сеттеры...
}


Примечания:
Аннотация @Entity связывает класс с таблицей в базе данных.
Аннотация @Id указывает первичный ключ.
Аннотация
@GeneratedValue используется для автоинкремента.
@Table(name = "users") указывает имя таблицы.
Аннотации валидации (@NotBlank, @Email, @NotNull) проверяют корректность данных.

Шаг 4: Создание слоя доступа к данным (Repository)

Интерфейс репозитория предоставляет методы для взаимодействия с базой данных.
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}


Особенности:
JpaRepository предоставляет стандартные CRUD-методы (save, findById, findAll, deleteById).
Не нужно реализовывать методы вручную.


Шаг 5: Реализация бизнес-логики (Service)

Слой Service инкапсулирует логику работы с данными.
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Service
public class UserService {

private final UserRepository userRepository;

@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

public List<User> getAllUsers() {
return userRepository.findAll();
}

public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found with id: " + id));
}

public User createUser(User user) {
return userRepository.save(user);
}

public User updateUser(Long id, User updatedUser) {
User existingUser = getUserById(id);
existingUser.setName(updatedUser.getName());
existingUser.setEmail(updatedUser.getEmail());
existingUser.setAge(updatedUser.getAge());
return userRepository.save(existingUser);
}

public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}


Примечания:
Методы инкапсулируют работу с UserRepository.
Если пользователь не найден, выбрасывается исключение.


#Java #Training #Spring #CRUD_API
Шаг 6: Создание REST-контроллера

Контроллер обрабатывает HTTP-запросы и возвращает данные клиенту.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {

private final UserService userService;

@Autowired
public UserController(UserService userService) {
this.userService = userService;
}

@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}

@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
return ResponseEntity.ok(userService.getUserById(id));
}

@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
return ResponseEntity.status(201).body(userService.createUser(user));
}

@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @Valid @RequestBody User user) {
return ResponseEntity.ok(userService.updateUser(id, user));
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}


Примечания:
Методы контроллера возвращают данные с помощью ResponseEntity.
Данные валидируются аннотацией
@Valid.
Используются стандартные HTTP-коды:
200 OK для успешных операций.
201 Created для создания ресурса.
204 No Content для удаления.


Шаг 7: Тестирование API

Пример запросов (с использованием Postman или curl):

Получение всех пользователей:
GET http://localhost:8080/api/users


Получение пользователя по ID:
GET http://localhost:8080/api/users/1


Создание пользователя:
POST http://localhost:8080/api/users
Content-Type: application/json

{
"name": "Jane Doe",
"email": "jane.doe@example.com",
"age": 28
}


Обновление пользователя:
PUT http://localhost:8080/api/users/1
Content-Type: application/json

{
"name": "John Smith",
"email": "john.smith@example.com",
"age": 35
}


Удаление пользователя:
DELETE http://localhost:8080/api/users/1


Дополнительные возможности

Обработка ошибок: Добавьте обработчик ошибок с помощью @ControllerAdvice:
@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {
return ResponseEntity.status(404).body(ex.getMessage());
}
}


Тестирование с помощью MockMvc:
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {

@Autowired
private MockMvc mockMvc;

@Test
public void testGetAllUsers() throws Exception {
mockMvc.perform(get("/api/users"))
.andExpect(status().isOk());
}
}


#Java #Training #Spring #CRUD_API
Доброго субботнего утра! ☀️

Как Ваши дела? Елку поставили?🎄

Готовлю на завтра выполнение тестового задания от одного из работодателей с hh.ru.🤌

Посмотрим, разберем, да что-нибудь напишем🤪😂

Всем хороших выходных🎉
Всем привет!

В 16:00 по МСК, я вновь жду Вас на встрече в Яндекс.Телемост!

Попробуем сделать тестовое задание от работодателя на hh.ru, обсудим детали)

Жду всех!✌️
Встреча создана!

https://telemost.yandex.ru/j/89268837201575

Залетаем!
Пишем тестовое задание от реального работодателя. Встреча от 22.12.2024

Запись нашей сегодняшней встречи -
YOUTUBE
RUTUBE

Крайне благодарен всем кто пришел, за участие!💪

На сегодняшней встрече мы начали писать тестовый сервис по документации реального работодателя с hh.ru:
— разобрали логику приложения
— создали сущность и Dto
— начали писать сервисы и контроллер


Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!

Всем хорошего настроения! 🫡✌️
Всем доброго утра!

Есть вопрос - вчера мы начали писать тестовый сервис хранения носков на складе. Стоит ли продолжить? И второй момент, что можно это сделать в середине недели. Вас это устроит, или привычнее вечер воскресения?
Anonymous Poll
88%
Да, продолжай в любой день!
8%
Да, но мне удобнее быть в воскресение
0%
Какой сервис, о чем ты?
0%
Не, не стоит продолжать, не интересно
4%
Хватит выкладывать всякую чушь!
Пагинация и фильтрация данных в REST API с использованием Spring

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

1. Пагинация (Pagination) в Spring

Пагинация позволяет разделить большие объемы данных на страницы и возвращать их по частям. В Spring Boot пагинация реализуется с помощью Spring Data JPA.

Подключение пагинации в проекте

Spring Data JPA предоставляет интерфейсы и аннотации для легкой реализации пагинации.

Добавьте параметр Pageable в методы репозитория:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {

Page<User> findAll(Pageable pageable);

}


Page — это контейнер, который содержит данные текущей страницы и мета-информацию (например, общее количество страниц).
Pageable — это интерфейс для параметров пагинации: номер страницы, размер страницы и сортировка.


Использование Pageable в контроллере:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {

private final UserRepository userRepository;

@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@GetMapping
public ResponseEntity<Page<User>> getAllUsers(Pageable pageable) {
Page<User> users = userRepository.findAll(pageable);
return ResponseEntity.ok(users);
}
}


Пример запроса с пагинацией:
GET /api/users?page=0&size=5&sort=name,asc
page — номер страницы (начинается с 0).
size — количество элементов на странице.
sort — параметры сортировки (поле,направление).


Пример ответа:
{
"content": [
{"id": 1, "name": "John", "email": "john@example.com"},
{"id": 2, "name": "Jane", "email": "jane@example.com"}
],
"pageable": {
"pageNumber": 0,
"pageSize": 5
},
"totalPages": 2,
"totalElements": 10,
"last": false
}


2. Фильтрация данных в REST API

Фильтрация позволяет клиентам задавать условия, по которым нужно отбирать данные.


Подходы к фильтрации

Фильтрация по параметрам запроса (Request Parameters): Используется для простой фильтрации данных.

Динамическая фильтрация с помощью Specification или Criteria:
Применяется для сложных и многоуровневых условий.

Фильтрация по параметрам запроса
Реализация простого поиска с фильтрацией:

Добавьте методы в репозиторий:
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {

List<User> findByNameContaining(String name);

List<User> findByAgeGreaterThanEqual(Integer age);

}


#Java #Training #Spring #Pagination #Filter
Добавьте фильтры в контроллер:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {

private final UserRepository userRepository;

@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@GetMapping("/search")
public ResponseEntity<List<User>> searchUsers(
@RequestParam(required = false) String name,
@RequestParam(required = false) Integer age) {

if (name != null) {
return ResponseEntity.ok(userRepository.findByNameContaining(name));
} else if (age != null) {
return ResponseEntity.ok(userRepository.findByAgeGreaterThanEqual(age));
} else {
return ResponseEntity.ok(userRepository.findAll());
}
}
}


Примеры запросов:

Фильтрация по имени:
GET /api/users/search?name=John


Фильтрация по возрасту:
GET /api/users/search?age=30


Динамическая фильтрация с использованием Specification
Для сложных фильтров можно использовать Spring Data JPA Specification.

Добавьте зависимость:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>


Создайте Specification для фильтрации:
import org.springframework.data.jpa.domain.Specification;

public class UserSpecification {

public static Specification<User> hasName(String name) {
return (root, query, cb) -> cb.like(root.get("name"), "%" + name + "%");
}

public static Specification<User> hasAgeGreaterThan(Integer age) {
return (root, query, cb) -> cb.greaterThanOrEqualTo(root.get("age"), age);
}
}


Расширьте репозиторий:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}


Добавьте динамическую фильтрацию в контроллер:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {

private final UserRepository userRepository;

@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@GetMapping("/filter")
public ResponseEntity<List<User>> filterUsers(
@RequestParam(required = false) String name,
@RequestParam(required = false) Integer age) {

Specification<User> spec = Specification.where(null);

if (name != null) {
spec = spec.and(UserSpecification.hasName(name));
}

if (age != null) {
spec = spec.and(UserSpecification.hasAgeGreaterThan(age));
}

return ResponseEntity.ok(userRepository.findAll(spec));
}
}


Пример запроса с фильтрацией:

GET /api/users/filter?name=Jane&age=25


3. Пагинация и фильтрация вместе

Совмещение пагинации и фильтрации:
@GetMapping("/filter")
public ResponseEntity<Page<User>> filterUsers(
@RequestParam(required = false) String name,
@RequestParam(required = false) Integer age,
Pageable pageable) {

Specification<User> spec = Specification.where(null);

if (name != null) {
spec = spec.and(UserSpecification.hasName(name));
}

if (age != null) {
spec = spec.and(UserSpecification.hasAgeGreaterThan(age));
}

Page<User> result = userRepository.findAll(spec, pageable);
return ResponseEntity.ok(result);
}


Пример запроса:
GET /api/users/filter?name=Jane&page=0&size=5&sort=age,desc


#Java #Training #Spring #Pagination #Filter
Что выведет код?

import java.util.HashMap;
import java.util.Map;

public class Task231224_1 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("a", 3);
map.put("c", null);

System.out.println(map.get("a") + " " + map.get("c"));
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
43%
1 null
4%
3 0
52%
3 null
0%
2 null
И поднять его теперь не так просто🤪😂

https://t.me/Java_for_beginner_dev

#Mems
Обработка ошибок в REST API с использованием Spring Boot

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

1. Основные аспекты обработки ошибок


Использование HTTP-кодов:
1xx: Informational (информационные)
2xx: Success (успешно)
3xx: Redirection (перенаправление)
4xx: Client Error (ошибка клиента, например, неправильный запрос, ресурс не найден).
5xx: Server Error (ошибка сервера, например, проблемы на уровне базы данных или приложения).


Возврат стандартного формата ошибки: Сообщения об ошибках должны быть понятны и содержать:
- Код состояния HTTP.
- Сообщение об ошибке.
- Вспомогательную информацию (например, время ошибки или идентификатор запроса).


Обработка различных типов ошибок:
- Ошибки валидации.
- Отсутствие ресурсов.
- Некорректный формат запроса.
- Ошибки на уровне сервера.


2. Обработка ошибок с использованием @ControllerAdvice

Аннотация @ControllerAdvice позволяет централизованно обрабатывать исключения, возникающие в контроллерах.

Создайте класс для обработки исключений:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
ex.getMessage(),
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
ex.getMessage(),
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
}


Класс ответа на ошибку:
public class ErrorResponse {

private int status;
private String message;
private long timestamp;

public ErrorResponse(int status, String message, long timestamp) {
this.status = status;
this.message = message;
this.timestamp = timestamp;
}

// Геттеры и сеттеры...
}


Пользовательское исключение для отсутствия ресурса:
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}


#Java #Training #Spring #API_Errors
3. Обработка ошибок валидации

Spring Boot поддерживает валидацию запросов с помощью аннотаций javax.validation. Ошибки можно обрабатывать централизованно.

Добавьте валидацию в сущность:
import jakarta.validation.constraints.*;

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank(message = "Name cannot be blank")
private String name;

@Email(message = "Invalid email address")
private String email;

@Min(value = 18, message = "Age must be at least 18")
private Integer age;

// Геттеры и сеттеры...
}


Обработайте ошибки валидации:

import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
for (FieldError error : ex.getBindingResult().getFieldErrors()) {
errors.put(error.getField(), error.getDefaultMessage());
}
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
}


Пример ответа при ошибке валидации:
{
"name": "Name cannot be blank",
"email": "Invalid email address"
}


4. Обработка ошибок на уровне контроллера

Если требуется специфичная обработка для одного контроллера, можно использовать аннотацию @ExceptionHandler внутри самого контроллера.
@RestController
@RequestMapping("/api/users")
public class UserController {

@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
}

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
ex.getMessage(),
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
}


5. Настройка формата ответа

Вы можете настроить формат ответа об ошибке на уровне всего приложения с помощью аннотации @RestControllerAdvice (аналог @ControllerAdvice, но возвращает JSON по умолчанию).

@RestControllerAdvice
public class GlobalRestExceptionHandler {

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"An unexpected error occurred",
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}


#Java #Training #Spring #API_Errors
6. Настройка ошибок Spring Boot

Spring Boot возвращает стандартные страницы ошибок, такие как Whitelabel Error Page. Для кастомизации ошибок используйте ErrorController.

Отключите Whitelabel Error Page:
server.error.whitelabel.enabled=false
Создайте собственный контроллер ошибок:
java
Копировать код
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.request.WebRequest;

import java.util.Map;

@Controller
public class CustomErrorController implements ErrorController {

private final ErrorAttributes errorAttributes;

public CustomErrorController(ErrorAttributes errorAttributes) {
this.errorAttributes = errorAttributes;
}

@RequestMapping("/error")
public ResponseEntity<Map<String, Object>> handleError(WebRequest webRequest) {
Map<String, Object> errors = errorAttributes.getErrorAttributes(webRequest, ErrorAttributeOptions.defaults());
HttpStatus status = HttpStatus.valueOf((int) errors.get("status"));
return new ResponseEntity<>(errors, status);
}
}


7. Пример API с обработкой ошибок

Пример запроса:
GET /api/users/999


Пример ответа:

{
"status": 404,
"message": "User not found with id: 999",
"timestamp": 1702745190123
}


8. Советы по обработке ошибок

Возвращайте только необходимую информацию:
Не отправляйте stack trace клиенту.
Показывайте сообщение об ошибке, понятное конечному пользователю.


Используйте стандартные HTTP-коды:
400 (Bad Request) — ошибка клиента.
401 (Unauthorized) — пользователь не авторизован.
404 (Not Found) — ресурс не найден.
500 (Internal Server Error) — ошибка сервера.


Добавьте логирование: Все ошибки должны логироваться для анализа.


#Java #Training #Spring #API_Errors