Présentation de SPRING

Un conteneur dit "léger"

SPRING est un conteneur dit « léger », c'est-à-dire une infrastructure similaire à un serveur d'application J2EE. Il prend donc en charge la création d'objets et la mise en relation d'objets par l'intermédiaire d'un fichier de configuration qui décrit les objets à fabriquer et les relations de dépendances entre ces objets.

Les avantages de Spring

L'avantage par rapport aux serveurs d'application est qu'avec SPRING, vos classes n'ont pas besoin d'implémenter une quelconque interface pour être prises en charge par le framework (au contraire des serveurs d'applications J2EE et des EJBs). C'est en ce sens que SPRING est qualifié de conteneur « léger ».

Outre cette fabrique d'objets, SPRING propose tout un ensemble d'abstractions permettant de gérer entre autres :

Spring s'appuie principalement sur l'intégration de trois concepts clés :

Spring MVC

L'architecture de base d'une application MVC est de la forme suivante :

Spring MVC implémente cette architecture d'une manière différente, décrit par ce schéma :

Ici le controller est assuré par le servlet "DispatcherServlet", c'est lui qui voit passer toute les demandes du client au controller. Ensuite il execute l'action demandé par une classe implémentant l'interface qui sera le "Controller", ce controleur sera appelé controleur secondaire, puisque le principal est le "DispatcherServlet".

Le contrôleur "Controller" traite une demande particulière de l'utilisateur. Pour ce faire, il peut avoir besoin de l'aide de la couche métier. Une fois la demande du client traitée, celle-ci peut appeler diverses réponses. Un exemple classique est :

Le contrôleur choisit la vue à envoyer au client. Choisir la réponse à envoyer au client nécessite plusieurs étapes :

En résumé cette étape consiste donc en le choix d'une vue V et la construction du modèle M nécessaire à celle-ci. Enfin, le contrôleur DispatcherServlet demande à la vue choisie de s'afficher. Il s'agit d'une classe implémentant l'interface "org.springframework.web.servlet.View".

Configuration

Première Etape

La creation d'un fichier de config XML. C'est l'endroit où on va declarer les Beans à générer par la suite. Permet de créer la structure avec laquelle on va manipuler les données.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans SYSTEM "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:db.properties</value>
</property>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${db.driver}</value></property>
<property name="url"><value>${db.url}</value></property>
<property name="username"><value>${db.username}</value></property>
<property name="password"><value>${db.password}</value></property>
</bean>

<!-- la source de donnéees DBCP -->
<bean id="dataSource2"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@//127.0.0.1:1521/xe" />
<property name="username" value="arel" />
<property name="password" value="lera" />
</bean>

<!-- SqlMapClient -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="configLocation">
<value>classpath:SpringIbatisapp-config-oracle.xml</value>
</property>
</bean>

<!-- la classes d'accè à la couche [daoUtilisateur] -->
<bean id="daoUtilisateur" class="SpringIbatis.model.dao.impl.UtilisateursDAOImpl">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>

<!-- la classes d'accè à la couche [daoTopic] -->
<bean id="daoTopic" class="SpringIbatis.model.dao.impl.TopicDAOImpl">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>

<!-- la classes d'accè à la couche [daoPost] -->
<bean id="daoPost" class="SpringIbatis.model.dao.impl.PostDAOImpl">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>

<!-- la classes d'accè à la couche [daoTopicPost] -->
<bean id="daoTopicPost" class="SpringIbatis.model.dao.impl.TopicPostDAOImpl">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>

<!-- la classes d'accè à la couche [daoTopicUtilisateur] -->
<bean id="daoTopicUtilisateur" class="SpringIbatis.model.dao.impl.TopicUtilisateurDAOImpl">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>
</beans>

Les « property » dans un bean servent donc à déclarer les relations de dépendance entre beans.

Seconde etape : Acces au fichier de Configuration

L'accès et la lecture du fichier de configuration correspondent à l'initialisation du « container » SPRING. Cette partie intervient dans le fichier "web.xml" comme dans une application JEE traditionnelle.


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>SpringIbatis.v.2.0</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<!--
- Filtre springSecurityFilterChain
-->

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!--
- ContextLoaderListener : chargement fichiers de définition de beans
-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<!--
- CONFIG DispatcherServlet
-->
<servlet>
<servlet-name>SpringIbatisapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>SpringIbatisapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>

<!--
- Fichiers XML de configuration, à charger par le ContextLoaderListener
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
<!--/WEB-INF/SpringIbatisapp-data.xml
/WEB-INF/SpringIbatisapp-service.xml-->
/WEB-INF/SpringIbatisapp-servlet.xml
/WEB-INF/security.xml
</param-value>

</context-param>
</web-app>

Ici lors de l'usage de la servlet DispatcherServlet, le fichier par défaut recherché est /WEB-INF/SpringIbatisapp-servlet.xml.

Troisieme Etape : Le Controller

C'est ici que seront créé les méthodes nécessaire au forum. Il faut savoir que grace a la couche MVC de Spring, il est totalement possible de créer plusieurs Controller (avec des noms différents) et que chacun puisse cohabiter. Ceci permet donc une totale neutralité lors du développement et le tout est facilement intégrable au projet final. En d'autre terme la couche MVC permet une programmation très aisé et tout les avantages connus du système MVC.
Exemple d'une méthode du Controller :


public ModelAndView enter(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("\"enter\" method called");
TopicDAO dao = (TopicDAO) (new ClassPathXmlApplicationContext("SpringIbatisapp-config.xml")).getBean("daoTopic");

Collection topics = dao.selectTopicByExample(null);
Iterator listtopic = topics.iterator();

return new ModelAndView("forum", "listtopic", listtopic);
}

Ici on voit bien l'injection DAO qui a été effectué qui permettra la lien entre le Controller et la BDD.

Pourquoi du DAO ?

Afin de rendre l'application indépendantes de la base de données, il faut implémenter un Data Access Object (DAO) pour rendre abstrait et encapsuler tous les accès à la base de données. Le DAO gère la connexion et comment restituer les données. Le DAO implémente le mécanisme d'accès à la base de données. Le composant business qui relie le DAO, utilise l'interface fournie pour les clients. Le DAO cache complètement les composants business et joue le rôle d'adaptateur entre la source de données et le composant business client.

Derniere Etape : La Sécutité

La sécutité est géré presque toute seule par Spring. En effet, il suffit de construire un fichier "security.xml" qui déclare les droits des personnes et de leurs actions. (Il faut bien sur avoir importer la librairie fournie dans l'archive de Spring)
> Exemple de security.xml :


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">

<!-- Déclaration du PropertyPlaceholderConfigurer -->

<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/db.properties</value>
</list>
</property>
</bean>
<!-- Déclaration de la DATASOURCE -->

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>


<!-- Stratégie de Sécurité : ressources et Remember me -->
<security:http auto-config="true">
<security:intercept-url pattern="/login.jsp*" filters="none"/>
<security:intercept-url pattern="/creer_utilisateur.jsp*" filters="none"/>
<security:intercept-url pattern="/createUser.htm*" filters="none"/>
<security:intercept-url pattern="/ajouterUtilisateur.jsp*" access="ROLE_ADMIN"/>
<security:intercept-url pattern="/logo*" filters="none"/>
<security:intercept-url pattern="/eisti.css" filters="none"/>
<security:intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_UTILISATEUR,ROLE_MODERATEUR"/>
<security:form-login login-page='/login.jsp'/>
</security:http>

<!-- Authentification via Database personalisée : Exemple avec tables 'employes' et 'roles'
Attention à la colonne 'enabled' à ajouter
-->
<security:authentication-provider user-service-ref='myUserDetailsService' />

<bean id="myUserDetailsService" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="usersByUsernameQuery" value="SELECT login as username, password, enabled , nom, prenom, role
FROM utilisateurs WHERE login = ?"/>
<property name="authoritiesByUsernameQuery" value="SELECT login as username, role
FROM utilisateurs WHERE login = ?"/>
</bean>

</beans>

On remarque que les droits sont définis suivant des "role" en effet en Base de données chaque utilisateur se voit attribué un champs "role" qui correspond a un des role définis dans le fichier de secutité XML. Pour chaques actions si un type d'utilisateur est requis alors il est défini comme un "filter" et cette option ne sera disponible que pour ce type d'utilisateur. Spring gére de lui même les éventuels messages d'erreur ou d'accès refusé, bien qu'il soit possible de renvoyer vers une page crée soit même.


Copyright - Site realisé par KDo, FatBen, Rom2, Prolo et Heliko