Salta al contenuto principale

Creare e gestire le API REST con Spring Boot

Profile picture for user luca77king

Una volta definito il livello dei servizi, il passo successivo nello sviluppo di applicazioni con Spring Boot è quello di esporre queste funzionalità al mondo esterno tramite API REST. In altre parole, i servizi che abbiamo costruito diventano i “motori” della nostra applicazione, mentre le API REST costituiscono l’interfaccia attraverso la quale client esterni, applicazioni front-end o altri microservizi possono interagire con essi.

Le API RESTful rappresentano oggi lo standard più diffuso per la comunicazione tra sistemi distribuiti. Grazie alla loro semplicità e flessibilità, permettono di scambiare dati attraverso il protocollo HTTP utilizzando i metodi standard: GET, POST, PUT, PATCH, DELETE. In combinazione con Spring Boot, possiamo creare rapidamente endpoint robusti, sicuri e facili da manutenere, senza dover scrivere codice boilerplate complicato.

L’adozione di un’architettura RESTful consente inoltre di rispettare alcuni principi chiave:

  • Statelessness: ogni richiesta HTTP è indipendente, semplificando la scalabilità dell’applicazione.

  • Chiarezza nella struttura delle risorse: le URL rappresentano le risorse (ad esempio /products, /orders) e non le azioni.

  • Separazione chiara dei livelli: i controller gestiscono la comunicazione con il client, i servizi gestiscono la logica di business e i repository gestiscono l’accesso ai dati.

Seguendo questo approccio, otteniamo applicazioni più modulabili, testabili e facilmente estendibili, con una divisione dei ruoli chiara e coerente tra le componenti.

Creare un controller REST

Il controller REST è la classe responsabile di ricevere le richieste HTTP, delegare il lavoro al servizio corrispondente e restituire la risposta appropriata. In Spring Boot, la classe si annota con @RestController, che è una combinazione di @Controller e @ResponseBody. Questo significa che tutti i metodi della classe restituiranno automaticamente dati serializzati in JSON, senza bisogno di configurazioni aggiuntive.

Insieme a @RestController, possiamo utilizzare @RequestMapping per definire il percorso base delle risorse gestite dal controller.

Esempio di base:

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

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping
    public List<Product> getAllProducts() {
        return productService.findAllProducts();
    }

    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productService.findProductById(id);
    }

    @PostMapping
    public Product createProduct(@RequestBody Product product) {
        return productService.createProduct(product);
    }

    @PutMapping("/{id}")
    public Product updateProduct(@PathVariable Long id, @RequestBody Product updated) {
        return productService.updateProduct(id, updated);
    }

    @DeleteMapping("/{id}")
    public void deleteProduct(@PathVariable Long id) {
        productService.deleteProduct(id);
    }
}

Analisi delle annotazioni principali

  • @RestController: indica a Spring Boot che questa classe gestirà richieste REST e restituirà dati JSON.

  • @RequestMapping("/products"): definisce il percorso base per tutte le richieste a questo controller.

  • @GetMapping, @PostMapping, @PutMapping, @DeleteMapping: mappano i metodi HTTP sui metodi della classe.

  • @PathVariable: consente di catturare valori dalla URL, ad esempio l’ID di una risorsa.

  • @RequestBody: indica che il corpo della richiesta HTTP deve essere deserializzato in un oggetto Java.

Gestione delle eccezioni e risposta coerente

In un’applicazione reale, non tutte le richieste avranno successo. È quindi fondamentale gestire correttamente le eccezioni e restituire messaggi chiari e coerenti al client. Spring Boot mette a disposizione il meccanismo di @ControllerAdvice per centralizzare la gestione degli errori.

Esempio di gestione centralizzata:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ProductNotFoundException.class)
    public ResponseEntity<String> handleProductNotFound(ProductNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGeneralError(Exception ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                             .body("Si è verificato un errore: " + ex.getMessage());
    }
}

In questo modo, tutte le eccezioni sollevate dai servizi vengono intercettate e trasformate in risposte HTTP significative, migliorando l’esperienza del client e la manutenibilità del codice.

Gestione dei parametri e query string

Spesso le API REST devono ricevere parametri dinamici per filtrare, ordinare o cercare risorse. Spring Boot offre strumenti semplici per gestire questi scenari:

@GetMapping("/search")
public List<Product> searchProducts(@RequestParam String name, @RequestParam(required = false) Double maxPrice) {
    return productService.searchByNameAndPrice(name, maxPrice);
}
  • @RequestParam permette di leggere parametri dalla query string.

  • Il parametro required = false indica che il parametro non è obbligatorio.

Questa gestione è essenziale per creare API flessibili e adatte a scenari complessi senza appesantire i controller.

Buone pratiche nella progettazione delle API REST

  1. URL chiare e coerenti: usare nomi di risorse al plurale (/products, /orders) e gerarchie logiche.

  2. Metodi HTTP coerenti: GET per leggere, POST per creare, PUT/PATCH per aggiornare, DELETE per rimuovere.

  3. Status code significativi: 200 OK per successo, 201 Created per nuove risorse, 404 Not Found per risorse mancanti, 400 Bad Request per errori di input.

  4. JSON coerente: risposte consistenti, evitando campi null o non necessari.

  5. Validazione dei dati: usare @Valid insieme a Bean Validation (javax.validation) per garantire integrità dei dati in ingresso.

Conclusione

Creare API REST in Spring Boot è un passo naturale dopo aver implementato il livello dei servizi. I controller REST, combinati con servizi ben strutturati e repository affidabili, costituiscono la base di applicazioni moderne, scalabili e facili da manutenere. La chiara separazione dei livelli consente di concentrarsi sulla logica di business senza compromettere la leggibilità, la testabilità e la qualità del codice.

Con una solida base di servizi e controller REST, sei pronto per affrontare step successivi come autenticazione e autorizzazione, documentazione delle API con Swagger/OpenAPI, e gestione avanzata delle query e dei filtri, rendendo la tua applicazione robusta e pronta per il mondo reale.