Guida rapida ai controller a molla

1. Introduzione

In questo articolo ci concentreremo su un concetto fondamentale in Spring MVC: i controller.

2. Panoramica

Cominciamo facendo un passo indietro e dando uno sguardo al concetto di Front Controller nella tipica architettura Spring Model View Controller .

Ad un livello molto alto, ecco le principali responsabilità che stiamo osservando:

  • Intercetta le richieste in arrivo
  • Converte il payload della richiesta nella struttura interna dei dati
  • Invia i dati a Model per ulteriori elaborazioni
  • Ottiene i dati elaborati dal modello e li sposta nella vista per il rendering

Ecco un breve diagramma per il flusso di alto livello in Spring MVC :

Come puoi vedere, il DispatcherServlet svolge il ruolo di Front Controller nell'architettura.

Il diagramma è applicabile sia ai controller MVC tipici che ai controller RESTful, con alcune piccole differenze (descritte di seguito).

Nell'approccio tradizionale, le applicazioni MVC non sono orientate ai servizi, quindi è presente un V iew Resolver che rende le viste finali in base ai dati ricevuti da un controller .

Le applicazioni RESTful sono progettate per essere orientate ai servizi e restituiscono dati grezzi (in genere JSON / XML). Poiché queste applicazioni non eseguono il rendering della vista, non ci sono View Resolver : generalmente si prevede che il controller invii i dati direttamente tramite la risposta HTTP.

Cominciamo con i controller in stile MVC0.

3. Dipendenze di Maven

Per poter lavorare con Spring MVC , affrontiamo prima le dipendenze di Maven:

 org.springframework spring-webmvc 5.0.6.RELEASE 

Per ottenere l'ultima versione della libreria, dai un'occhiata a spring-webmvc su Maven Central.

4. Project Web Config

Ora, prima di esaminare i controller stessi, dobbiamo prima impostare un semplice progetto web ed eseguire una rapida configurazione del servlet .

Vediamo prima come è possibile impostare DispatcherServlet senza utilizzare web.xml , ma utilizzando invece un inizializzatore:

public class StudentControllerConfig implements WebApplicationInitializer { @Override public void onStartup(ServletContext sc) throws ServletException { AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); root.register(WebConfig.class); root.refresh(); root.setServletContext(sc); sc.addListener(new ContextLoaderListener(root)); DispatcherServlet dv = new DispatcherServlet(new GenericWebApplicationContext()); ServletRegistration.Dynamic appServlet = sc.addServlet("test-mvc", dv); appServlet.setLoadOnStartup(1); appServlet.addMapping("/test/*"); } }

Per impostare le cose senza XML, assicurati di avere servlet-api 3.1.0 sul tuo classpath.

Ecco come apparirebbe il file web.xml :

 test-mvc  org.springframework.web.servlet.DispatcherServlet  1  contextConfigLocation /WEB-INF/test-mvc.xml   

Stiamo impostando la proprietà contextConfigLocation qui, che punta al file XML utilizzato per caricare il contesto Spring. Se la proprietà non è presente, Spring cercherà un file denominato {servlet_name} -servlet.xml .

Nel nostro caso il servlet_name è test-mvc e quindi, in questo esempio, DispatcherServlet cercherà un file chiamato test-mvc-servlet.xml .

Infine, impostiamo il DispatcherServlet e lo mappiamo a un particolare URL - per finire il nostro sistema basato sul Front Controller qui:

 test-mvc /test/* 

Pertanto, in questo caso, DispatcherServlet intercetterebbe tutte le richieste all'interno del pattern / test / * .

5. Spring MVC Web Config

Vediamo ora come può essere configurato il servlet Dispatcher utilizzando Spring Config :

@Configuration @EnableWebMvc @ComponentScan(basePackages= { "com.baeldung.controller.controller", "com.baeldung.controller.config" }) public class WebConfig implements WebMvcConfigurer { @Override public void configureDefaultServletHandling( DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Bean public ViewResolver viewResolver() { InternalResourceViewResolver bean = new InternalResourceViewResolver(); bean.setPrefix("/WEB-INF/"); bean.setSuffix(".jsp"); return bean; } }

Vediamo ora come impostare il Dispatcher Servlet utilizzando XML . Di seguito è mostrata un'istantanea del file XML DispatcherServlet , il file XML che DispatcherServlet utilizza per caricare controller personalizzati e altre entità Spring :

    /WEB-INF/   .jsp  

Sulla base di questa semplice configurazione, il framework ovviamente inizializzerà qualsiasi controller bean che troverà sul classpath.

Si noti che stiamo anche definendo il View Resolver, responsabile del rendering della vista: qui utilizzeremo InternalResourceViewResolver di Spring . Ciò si aspetta che il nome di una vista venga risolto, il che significa trovare una pagina corrispondente utilizzando prefisso e suffisso (entrambi definiti nella configurazione XML ).

Quindi, ad esempio, se il Controller restituisce una vista denominata " welcome" , il view resolver proverà a risolvere una pagina chiamata "welcome.jsp" nella cartella WEB-INF .

6. Il controller MVC

Adesso implementiamo finalmente il controller in stile MVC.

Si noti come stiamo restituendo un oggetto ModelAndView , che contiene una mappa del modello e un oggetto di visualizzazione ; entrambi saranno usati da V isualizza Resolver per il rendering dei dati:

@Controller @RequestMapping(value = "/test") public class TestController { @GetMapping public ModelAndView getTestData() { ModelAndView mv = new ModelAndView(); mv.setViewName("welcome"); mv.getModel().put("data", "Welcome home man"); return mv; } }

Allora, cosa abbiamo creato esattamente qui.

Innanzitutto, abbiamo creato un controller chiamato TestController e lo abbiamo mappato sul percorso "/ test" . Nella classe abbiamo creato un metodo che restituisce un oggetto ModelAndView ed è mappato a una richiesta GET, quindi qualsiasi chiamata URL che termina con " test " verrebbe instradata dal DispatcherServlet al metodo getTestData nel TestController .

And of course we're returning the ModelAndView object with some model data for good measure.

The view object has a name set to “welcome“. As discussed above, the View Resolver will search for a page in the WEB-INF folder called “welcome.jsp“.

Below you can see the result of an example GET operation:

Note that the URL ends with “test”. The pattern of the URL is “/test/test“.

The first “/test” comes from the Servlet, and the second one comes from the mapping of the controller.

7. More Spring Dependencies for REST

Let's now start looking at a RESTful controller. Of course, a good place to start is the extra Maven dependencies we need for it:

  org.springframework spring-webmvc 5.0.6.RELEASE   org.springframework spring-web 5.0.6.RELEASE   com.fasterxml.jackson.core jackson-databind 2.9.5   

Please refer to jackson-core, spring-webmvc and spring-web links for the newest versions of those dependencies.

Jackson is of course not mandatory here, but it's certainly a good way to enable JSON support. If you're interested to dive deeper into that support, have a look at the message converters article here.

8. The REST Controller

The setup for a Spring RESTful application is the same as the one for the MVC application with the only difference being that there is no View Resolvers and no model map.

The API will generally simply return raw data back to the client – XML and JSON representations usually – and so the DispatcherServlet bypasses the view resolvers and returns the data right in the HTTP response body.

Let's have a look at a simple RESTful controller implementation:

@Controller public class RestController { @GetMapping(value = "/student/{studentId}") public @ResponseBody Student getTestData(@PathVariable Integer studentId) { Student student = new Student(); student.setName("Peter"); student.setId(studentId); return student; } }

Note the @ResponseBody annotation on the method – which instructs Spring to bypass the view resolver and essentially write out the output directly to the body of the HTTP response.

A quick snapshot of the output is displayed below:

The above output is a result of sending the GET request to the API with the student id of 1.

One quick note here is – the @RequestMapping annotation is one of those central annotations that you'll really have to explore in order to use to its full potential.

9. Spring Boot and the @RestController Annotation

The @RestController annotation from Spring Boot is basically a quick shortcut that saves us from always having to define @ResponseBody.

Here's the previous example controller using this new annotation:

@RestController public class RestAnnotatedController { @GetMapping(value = "/annotated/student/{studentId}") public Student getData(@PathVariable Integer studentId) { Student student = new Student(); student.setName("Peter"); student.setId(studentId); return student; } }

10. Conclusion

In questa guida, esploriamo le basi dell'utilizzo dei controller in Spring, sia dal punto di vista di una tipica applicazione MVC che da un'API RESTful.

Ovviamente tutto il codice nell'articolo è disponibile su GitHub.