Come è strutturato e come si implementa un Rest Controller in Spring Boot? In questo articolo troverai le informazioni necessarie per la realizzazione di un controller per l’esposizione di servizi web RESTful in ambiente Spring Boot.

Lo scopo di un componente Controller, e nello specifico un RestController come vedrai tra poco, è quello di fornire un’implementazione rapida e semplice di un’interfaccia raggiungibile dall’esterno. In particolare, una classe Java annotata in Spring Boot come RestController serve a definire un’API REST.

 

Rest Controller in Spring Boot

Spring Boot, nella sua natura di framework, utilizza un sistema di annotazioni per facilitare la scrittura del codice e velocizzare il processo d’implementazione. Per quanto riguarda i componenti REST, le annotazioni necessarie sono fornite dalla libreria spring-boot-starter-web, disponibile come dipendenza Maven (o Gradle).

Il primo passo consiste quindi nell’aggiungere la suddetta dipendenza al progetto. Al momento della scrittura di questo articolo, la versione Spring Boot disponibile è la 2.6.4.

Maven:

Gradle:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.6.4</version>
</dependency>
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.6.4'
 

Nel codice di esempio sottostante trovi le annotazioni minime da usare per l’implementazione di un RestController in Spring Boot.

@RestController
@RequestMapping("api/demo")
public class DemoController {
    
    @GetMapping
    public List get(@RequestParam("queryParam") String queryParam) {
        // implement here
    }
    
    @GetMapping("{id}")
    public DemoType getById(@PathVariable("id") Long id) {
        // implement here
    }
    
    @PostMapping
    public DemoType create(@RequestBody DemoTypeDto body) {
        // implement here
    }
    
    // ... @PathMapping, @PutMapping, @DeleteMapping ...
}

Per prima cosa devi creare una nuova classe Java, nell’esempio DemoController.

Le prima annotazione da inserire @RestController, è un’annotazione a livello di classe, ovvero applicata subito sopra la definizione della classe stessa. @RequestMapping, al contrario, può essere aggiunta sia a livello di classe che a livello di metodo.

RestController indica la classe DemoController come componente da inserire all’interno del contesto dell’applicazione. Senza entrare troppo nello specifico, considera @RestController come un particolare @Component con caratteristiche aggiuntive. È inoltre un’estensione dell’annotazione @Controller (adatta a tutti i tipi di controller, anche non HTTP) e, in particolare, contiene al suo interno l’annotazione @ResponseBody adatta all’utilizzo tramite HTTP.

RequestMapping serve per configurare una mappatura per le richieste esterne. In pratica, associa ai metodi della classe una URL per le richieste. Se utilizzata a livello di classe, il valore viene applicato a tutti i metodi della classe, nell’esempio /api/demo/… sarà la path iniziale per tutti i metodi (es. getById -> /api/demo/1).

 

Le altre annotazioni presenti nel codice di esempio si applicano ai metodi.

@GetMapping e @PostMapping (ma anche Patch, Put, Delete …) sono particolari annotazioni RequestMapping. Permettono quindi la mappatura del metodo aggiungendo un’ulteriore dettaglio: si tratta di chiamate HTTP, in quanto definite all’interno di un controller REST, con specificato il metodo (GET, POST, …). Lo stesso risultato si sarebbe raggiunto ad esempio con @RequestMapping(value = “{id}”, method = RequestMethod.GET).

In fine, le annotazioni @PathVariable, @RequestParam e @RequestBody associate ai parametri del metodo, si riferiscono rispettivamente alle variabili di path configurate (ad esempio {id}), ai parametri di query (?queryParam=…) e al body di una richiesta POST.

 

Gestire la risposta di una API

RestController imposta di per se il tipo di risposta adatto al protocollo HTTP (tramite @ResponseBody). Per questo motivo, è sufficiente dichiarare un metodo con il tipo di oggetto voluto (DemoType); sarà RestController ad occuparsi della traduzione.

Nell’esempio che segue, i due metodi some e other (PATCH e GET rispettivamente) mostrano la suddetta gestione della risposta HTTP (204-No content e 200-Ok rispettivamente).

@PatchMapping()
@ResponseStatus(HttpStatus.NO_CONTENT)
public void some() {
    // implement here
}

@GetMapping
public DemoType other() {
    DemoType result = ...;
    // implement here
    return result;
}

È anche possibile utilizzare la classe ResponseEntity specificando lo stato HTTP della risposta.

I due metodi sopra risultano rispettivamente uguali ai seguenti:

@PatchMapping
public ResponseEntity<Void> some() {
    // implement here
    return ResponseEntity.noContent().build();
}

@GetMapping
public ResponseEntity<DemoType> other() {
    DemoType result = ...;
    // implement here
    return ResponseEntity.ok(result);
}

Puoi utilizzare ResponseEntity in forma semplificata ResponseEntity.ok(…) oppure in forma generica ResponseEntity.status(HttpStatus.OK).body(…).

In caso di errore, è possibile specificare il codice di stato da restituire (default: 500-Internal Server Error) attraverso la stessa classe ResponseEntity se utilizzata, altrimenti lanciando un’eccezione di tipo ResponseStatusException:

@GetMapping
public DemoType other() {
    DemoType result;
    try {
        result = ...;
    } catch (Exception e) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "some message");
    }
    return result;
}
@GetMapping
public ResponseEntity<?> other() {
    DemoType result;
    try {
        result = ...;
    } catch (Exception e) {
        return ResponseEntity.badRequest().body("some message");
    }
    return ResponseEntity.ok(result);
}
 

Conclusioni

In questo articolo hai visto come è strutturato e come si implementa un Rest Controller in Spring Boot. Per scoprire come realizzare un servizio web RESTfull completo in Spring Boot rimando a questo articolo.

Recommended Posts

No comment yet, add your voice below!


Add a Comment

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *