En aquest tema, aprendrem com gestionar les excepcions en una aplicació Spring Boot que exposa serveis web RESTful. La gestió adequada d'excepcions és crucial per proporcionar respostes coherents i informatives als clients de l'API.

Objectius

  • Entendre la importància de la gestió d'excepcions en serveis RESTful.
  • Aprendre a utilitzar les anotacions de Spring per gestionar excepcions.
  • Implementar un controlador d'excepcions global.
  • Proporcionar respostes personalitzades per a diferents tipus d'errors.

  1. Importància de la Gestió d'Excepcions en REST

Quan es desenvolupa una API RESTful, és important gestionar les excepcions de manera que els clients rebin respostes clares i coherents. Això ajuda a:

  • Millorar l'experiència de l'usuari.
  • Facilitar el depurament i la resolució de problemes.
  • Mantenir la seguretat de l'aplicació evitant la divulgació d'informació sensible.

  1. Utilitzant @ExceptionHandler

Spring Boot proporciona l'anotació @ExceptionHandler per gestionar excepcions específiques en un controlador. Vegem un exemple:

@RestController
@RequestMapping("/api")
public class ProductController {

    @GetMapping("/products/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        Product product = productService.findById(id);
        if (product == null) {
            throw new ProductNotFoundException("Product not found with id: " + id);
        }
        return ResponseEntity.ok(product);
    }

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

En aquest exemple:

  • ProductController té un mètode getProductById que llança una excepció ProductNotFoundException si el producte no es troba.
  • El mètode handleProductNotFoundException està anotat amb @ExceptionHandler per gestionar aquesta excepció i retornar una resposta personalitzada.

  1. Creant un Controlador d'Excepcions Global

Per evitar repetir el codi de gestió d'excepcions en cada controlador, podem crear un controlador d'excepcions global utilitzant @ControllerAdvice.

@ControllerAdvice
public class GlobalExceptionHandler {

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

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

En aquest exemple:

  • GlobalExceptionHandler és una classe anotada amb @ControllerAdvice que gestiona excepcions a nivell global.
  • Té dos mètodes per gestionar excepcions específiques (ProductNotFoundException) i genèriques (Exception).

  1. Proporcionant Respostes Personalitzades

Podem crear una classe ErrorResponse per estructurar les respostes d'error de manera coherent.

public class ErrorResponse {
    private int status;
    private String message;

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

    // Getters and setters
}

Exercici Pràctic

Objectiu

Implementar la gestió d'excepcions en un controlador RESTful.

Passos

  1. Crea una excepció personalitzada UserNotFoundException.
  2. Implementa un controlador UserController amb un mètode per obtenir un usuari per ID.
  3. Afegeix un mètode @ExceptionHandler per gestionar UserNotFoundException.
  4. Crea un controlador d'excepcions global per gestionar excepcions genèriques.

Solució

  1. Excepció personalitzada:
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}
  1. Controlador UserController:
@RestController
@RequestMapping("/api")
public class UserController {

    @GetMapping("/users/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.findById(id);
        if (user == null) {
            throw new UserNotFoundException("User not found with id: " + id);
        }
        return ResponseEntity.ok(user);
    }

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFoundException(UserNotFoundException ex) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
    }
}
  1. Controlador d'excepcions global:
@ControllerAdvice
public class GlobalExceptionHandler {

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

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

Resum

En aquesta secció, hem après com gestionar les excepcions en una aplicació Spring Boot que exposa serveis web RESTful. Hem vist com utilitzar @ExceptionHandler per gestionar excepcions específiques i com crear un controlador d'excepcions global amb @ControllerAdvice. També hem après a proporcionar respostes personalitzades per a diferents tipus d'errors. La gestió adequada d'excepcions és essencial per proporcionar una API robusta i fàcil de depurar.

Curs de Spring Boot

Mòdul 1: Introducció a Spring Boot

Mòdul 2: Conceptes bàsics de Spring Boot

Mòdul 3: Construint serveis web RESTful

Mòdul 4: Accés a dades amb Spring Boot

Mòdul 5: Seguretat a Spring Boot

Mòdul 6: Proves a Spring Boot

Mòdul 7: Funcions avançades de Spring Boot

Mòdul 8: Desplegant aplicacions Spring Boot

Mòdul 9: Rendiment i monitorització

Mòdul 10: Millors pràctiques i consells

© Copyright 2024. Tots els drets reservats