Spring MVC e l'annotazione @ModelAttribute

1. Panoramica

Una delle annotazioni Spring-MVC più importanti è l'annotazione @ModelAttribute.

Il @ModelAttribute è un'annotazione che lega un parametro di metodo o valore di ritorno del metodo ad un attributo di modello di nome e quindi espone a una vista web.

Nell'esempio seguente, dimostreremo l'usabilità e la funzionalità dell'annotazione, attraverso un concetto comune: un modulo inviato da un dipendente dell'azienda.

2. @ModelAttribute in profondità

Come rivelato nel paragrafo introduttivo, @ModelAttribute può essere utilizzato sia come parametro del metodo che a livello di metodo.

2.1 A livello di metodo

Quando l'annotazione viene utilizzata a livello di metodo, indica che lo scopo di quel metodo è aggiungere uno o più attributi del modello. Tali metodi supportano gli stessi tipi di argomenti dei metodi @RequestMapping ma non possono essere associati direttamente alle richieste.

Diamo un'occhiata a un rapido esempio qui per iniziare a capire come funziona:

@ModelAttribute public void addAttributes(Model model) { model.addAttribute("msg", "Welcome to the Netherlands!"); } 

Nell'esempio, mostriamo un metodo che aggiunge un attributo denominato msg a tutti i modelli definiti nella classe controller.

Ovviamente lo vedremo in azione più avanti nell'articolo.

In generale, Spring-MVC effettuerà sempre una chiamata prima a quel metodo, prima di chiamare qualsiasi metodo di gestione delle richieste. Cioè, i metodi @ModelAttribute vengono richiamati prima che vengano richiamati i metodi del controller annotati con @RequestMapping . La logica alla base della sequenza è che l'oggetto del modello deve essere creato prima che qualsiasi elaborazione inizi all'interno dei metodi del controller.

È anche importante annotare la rispettiva classe come @ControllerAdvice. Pertanto, puoi aggiungere valori in Model che verranno identificati come globali. Ciò significa in realtà che per ogni richiesta esiste un valore predefinito, per ogni metodo nella parte di risposta.

2.2 Come argomento del metodo

Quando viene utilizzato come argomento del metodo, indica che l'argomento deve essere recuperato dal modello. Quando non è presente, dovrebbe essere prima istanziato e poi aggiunto al modello e una volta presente nel modello, i campi degli argomenti dovrebbero essere popolati da tutti i parametri della richiesta che hanno nomi corrispondenti.

Nello snippet di codice che segue l' attributo del modello del dipendente viene popolato con i dati di un modulo inviato all'endpoint addEmployee . Spring MVC lo fa dietro le quinte prima di richiamare il metodo di invio:

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST) public String submit(@ModelAttribute("employee") Employee employee) { // Code that uses the employee object return "employeeView"; }

Più avanti in questo articolo vedremo un esempio completo di come utilizzare l' oggetto dipendente per popolare il modello dipendenteView .

Quindi, lega i dati del modulo con un bean. Il controller annotato con @RequestMapping può avere uno o più argomenti di classe personalizzati annotati con @ModelAttribute .

Questo è ciò che è comunemente noto come data binding in Spring-MVC, un meccanismo comune che ti evita di dover analizzare individualmente ogni campo del modulo.

3. Esempio di modulo

In questa sezione forniremo l'esempio a cui si fa riferimento nella sezione panoramica: un modulo molto semplice che richiede a un utente (dipendente di un'azienda, nel nostro esempio specifico), di inserire alcune informazioni personali (nello specifico nome e id). Dopo che l'invio è stato completato e senza errori, l'utente si aspetta di vedere i dati inviati in precedenza, visualizzati su un'altra schermata.

3.1 La vista

Creiamo prima un semplice modulo con i campi id e nome:

 Name  Id    

3.2 Il Titolare

Ecco la classe controller, dove viene implementata la logica per la vista sopra menzionata:

@Controller @ControllerAdvice public class EmployeeController { private Map employeeMap = new HashMap(); @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) public String submit( @ModelAttribute("employee") Employee employee, BindingResult result, ModelMap model) { if (result.hasErrors()) { return "error"; } model.addAttribute("name", employee.getName()); model.addAttribute("id", employee.getId()); employeeMap.put(employee.getId(), employee); return "employeeView"; } @ModelAttribute public void addAttributes(Model model) { model.addAttribute("msg", "Welcome to the Netherlands!"); } }

Nel metodo submit () abbiamo un oggetto Employee legato alla nostra View . Riesci a vedere il potere di questa annotazione? Puoi mappare i tuoi campi modulo a un modello a oggetti con la stessa semplicità. Nel metodo stiamo recuperando i valori dal modulo e impostandoli su ModelMap .

Alla fine restituiamo dipendenteView , il che significa che il rispettivo file JSP verrà chiamato come rappresentante della vista .

Inoltre, esiste anche un metodo addAttributes () . Il suo scopo è aggiungere valori nel Modello che saranno identificati a livello globale. Cioè, verrà restituito un valore predefinito come risposta per ogni richiesta a ogni metodo del controller. Dobbiamo anche annotare la classe specifica come @ControllerAdvice .

3.3 Il Modello

Come accennato prima, l' oggetto Model è molto semplicistico e contiene tutto ciò che è richiesto dagli attributi "front-end". Ora, diamo un'occhiata a un esempio:

@XmlRootElement public class Employee { private long id; private String name; public Employee(long id, String name) { this.id = id; this.name = name; } // standard getters and setters removed }

3.4 Conclusione

Il @ControllerAdvice assiste un controllore in particolare, @ModelAttribute metodi che si applicano a tutti @RequestMapping metodi. Ovviamente, il nostro metodo addAttributes () sarà il primo ad essere eseguito, prima del resto dei metodi @RequestMapping .

Tenendo presente questo e dopo aver eseguito sia submit () che addAttributes () , potremmo semplicemente fare riferimento a loro nella vista restituita dalla classe Controller , menzionando il loro nome all'interno di una coppia di parentesi graffe dollarizzata, come ad esempio $ {nome} .

3.5 Visualizzazione dei risultati

Stampiamo ora ciò che abbiamo ricevuto dal modulo:

${msg}

Name : ${name} ID : ${id}

4. Conclusione

In questo tutorial abbiamo esaminato l'utilizzo dell'annotazione @ModelAttribute , sia per gli argomenti del metodo che per i casi di utilizzo a livello di metodo .

L'implementazione di questo semplice tutorial può essere trovata nel progetto github.