Table des matières

Lien : https://docs.spring.io/spring/docs/3.0.0.M4/reference/html/ch15s02.html

Spring mvc : dispatches requests to controllers and offers other functionality that facilitates the development of web applications.

Spring's DispatcherServlet however, does more than just that. It is completely integrated with the Spring IoC container and as such allows you to use every other feature that Spring has.

Enchainement général du traitement d'une requête

When sending a request to your application the following happens:

  1. The request arrives at your server. Depending on the context path in the url the server decides to which application the request belongs.
  2. Depending on the url and the servlet mapping in the web.xml file of your application the server knows which servlet should handle the request.
  3. The request is passed to the servlet filter chain which can modify or reject requests
  4. The servlet takes control over the request. In case of your Spring application the spring Dispatcherservlet receives the request. Now Spring kicks in
  5. The request is processed by mvc intercepters preHandle methods
  6. The request is mapped to a controller based on the url. The corresponding controller method will be called.
    1. Your controller is processing the request. Many different responses can be returned in controllers (jsp, pdf, json, redirects, etc.). For now i assume you want to render a simple jsp view. Result of the controller are two things: a model and a view. The model is a map that contains the data you want to access later in your view. The view at this stage is most of the time a simple string containing a view name.
    2. Registered springs mvc interceptors can kick in again using the postHandle method (e.g. for modifying the model)
    3. The 'view' result of your controller is resolved to a real View using a ViewResolver. Depending on the ViewResolver the result can be jsp page, a tiles view, a thymeleaf template or many other 'Views'. In your case the ViewResolver resolves a view name (e.g. 'myPage') to a jsp file (e.g. /WEB-INF/jsp/myPage.jsp)
    4. The view is rendered using the model data returned by your controller
    5. The response with the rendered view will be passed to mvc interceptors again (afterCompletion method)
    6. The response leaves the dispatcher servlet. Here ends spring land
    7. The response passes servlet filters again
    8. The response is send back to client

WebApplicationContext, WebApplicationContext(s) et ServletContext

WebApplicationContext est un ApplicationContext. Elle permet d'accéder aux beans spring créés.

ApplicationContext instances in Spring can be scoped

2 articles très intéressants à ce sujet :

Par contre, on n'a qu'1 servletContext par application web (comprendre war). =⇒ on peut faire webApplicationContext.getServletContext() pour le récupérer.

webApplicationContext.getServletContext().getContextPath() : est bien le application context path

Que contiennent les WebApplicationContext

Des bean spring en plus que la servlet va utiliser pour traiter ses requêtes :

Particularité/ajout de WebApplicationContext par rapport au ApplicationContext :

  1. le WebApplicationContext dans lequel est traité la requête
  2. le ThemeResolver
  3. le LocalResolver

WebApplicationContext par défault pour les DispatcherServlet mais

On peut changer la classe de contexte dans les paramètre d'initialisation (dans le web.xml) : avec la balise <contextClass>.

Remarque : <contextConfigLocation> permet de changer le path du xml définissant les beans spécifiques pour cette servlet : [servlet-name]-servlet.xml

Controllers

Mettre ça dans l'appContext.xml <context:component-scan base-package=“packageToControllers”/>

ModelAndView, ModelMap, Model

@Controller

@RequestMapping

@PathVariable @RequestParam(“a_GET_param”)

@ResponseBody

@SessionAttributes et @ModelAttribute : pour une variable dans une session

@CookieValue : bound to http header cookie attribute of payload @RequestHeader

Exemple :

  @RequestMapping(value="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)

Handler Mappings

voir doc : Avec les versions de spring >=2.5, les méthodes annotées @RequestMapping sont scannées par le bean DefaultAnnotationHandlerMapping, qui instancié par défaut.

Cela dit, on peut redéfinir cette instance. Exemple :

<sxh xml>

 <beans>
   <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
     <property name="interceptors">
       <bean class="example.MyInterceptor"/>
     </property>
   </bean>

</sxh> <beans>

On peut aussi instancier d'autre HandlerMapping, comme SimpleUrlHandlerMapping (voir doc), par exemple dans le servlet15-servlet.xml

On peut par contre redéfinir ses propriétés :

     before()      : executée avant l'exécution du HandlerMapping
     after()       : executée après l'exécution du HandlerMapping
     complete()    : executée après l'exécution de compète de la requête
     preHandle(..) : retourne true ou false pour stopper la chaine à venir des HandlerMappings (par exemple )
         quand elle retourne false, alors ca signifie que ce HandlerMapping a bien pris en compte et traité la requête donc les autres HandlerMapping  ne seront pas exécuté

Exemple concret dans la doc : https://docs.spring.io/spring/docs/3.0.0.M4/reference/html/ch15s04.html

View Resolvers

Spring met à disposition pleins de type de view resolver :

Fonctionnement

Le view resolver est donc appelé par un HanderMapping.

Dans tous les cas, un view resolver prend en entrée un ModelAndView, puis tenter de retrouver la fameuse vue. Si il la trouve il la retourne (arrête la chaine de résolution, voir en dessous), sinon il retournera null.

Dans le cas des jsp (InternalResourceViewResolver) il cherche la vue à partir d'un RequestDispatcher (en type FORWARD (RequestDispatcher.forward(…)) retourne une InternalView si il la trouve. Hors il en trouve une forcément une, sinon il retourne la une sorte de view “Error”.

Chaine de viewResolvers dans une DispatcherServlet

Il est possible de chainer plusieurs views resolver. Il faut alors définir un ordre dans lequel il doivent chercher

Dans tous les cas, si aucune vue n'a été trouvée, alors spring lance une exception.

By passer les ViewResolvers

 return new ModelAndView("forward:/mesPagesJsps/log4jAdmin.jsp"); 

Ca n'utilisera pas l'InternalResourcesViewResolver, mais ça retournera bien une InternalResourcesView et ça forwardera.

Forward, sendRedirect and Include

http://programmergate.com/forward-vs-sendredirect-vs-include/

Forward

Le forward est censé faire une recherche interne d'une resource sans que le navigateur client ne soit au courant.

 request.getRequestDispatcher("HomeServlet").forward(request, response);

SendRedirect

When calling this method, the server sends back a HTTP status code of 302 (temporary redirect) which causes the web browser to issue a brand new HTTP GET request for the content at the redirected location.

 response.sendRedirect( "home.jsp?name=Hussein Terek" );

Include

Permet, au cours du traitement de la requete, d'embarquer une vue ou autre chose dans la réponse, puis de continuer le traitement de la réponse la où on en était.

 request.getRequestDispatcher("home.jsp").include(request, response);

Spring scanning de composant

@Component, @Repository, @Service, @Controller

https://docs.spring.io/spring/docs/3.0.0.M4/reference/html/ch03s10.html#beans-scanning-filters

By default, classes annotated with @Component, @Repository, @Service, @Controller, or a custom annotation that itself is annotated with @Component are the only detected candidate components.

Qualification des beans

@Qualifier (de spring et de javax)

@Genre

@Offline

Filtrer

On peut filtrer pour ne pas créer certains composants Exemple :

 <beans ...>
 
   <context:component-scan base-package="org.example">
      <context:include-filter type="regex" expression=".*Stub.*Repository"/>
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
   </context:component-scan>
 
 </beans>

Scope

      @Scope(scopeName="")
      //ConfigurableBeanFactory.SCOPE_PROTOTYPE
      //ConfigurableBeanFactory.SCOPE_SINGLETON
      //WebApplicationContext.SCOPE_APPLICATION
      //WebApplicationContext.SCOPE_REQUEST
      //WebApplicationContext.SCOPE_SESSION
      
      ScopeMetadataResolver