MVC Cedric Dumoulin Plan Bibliographie Injecter des composants Spring et JEE Header Footer et Body Internationalization Validation Gestion des erreurs Bibliographie Spring Framework ID: 257486
Download Presentation The PPT/PDF document "Spring" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Spring MVC
Cedric
DumoulinSlide2
Plan
Bibliographie
Injecter des composants
Spring
et JEE
Header
Footer
et Body
Internationalization
Validation
Gestion des erreursSlide3
Bibliographie
Spring
Framework
http://docs.spring.io/spring/docs/3.2.5.RELEASE/spring-framework-reference/htmlsingle/#overview
Designing and Implementing a Web Application with Spring
http://spring.io/guides/tutorials/web/Slide4
Bibliographie
Spring IO
http://spring.io/
Developing a Spring Framework MVC application step-by-step (2.5)
http://docs.spring.io/docs/Spring-MVC-step-by-step/
Spring
MVC Framework Tutorial
http://www.tutorialspoint.com/spring/spring_web_mvc_framework.htm
Wikipedia
http://en.wikipedia.org/wiki/Spring_Framework
Quick
start
http://projects.spring.io/spring-framework/#quick-startSlide5
Bibliographie
Spring
3.x
tutorials
http://www.roseindia.net/spring/spring3/index.shtml
http://yannart.developpez.com/java/spring/tutoriel/
http://www.theserverside.com/tutorial/Spring-30-Tutorial-Setting-Up-Configuring-The-EnvironmentSlide6
Guides
Accessing
Data
with
JPA
http://spring.io/guides/gs/accessing-data-jpa/
Designing and Implementing a Web Application with Spring
http://spring.io/guides/tutorials/web/Slide7
Injection d’objetSlide8
Spring
fournit la notion de composant
On peut injecter des composants dans d’autre composant
Même principe que JEE
Declarer un
composant
: @Component, @Named
Injecter
un
composant
:
@Inject, @
AutowiredSlide9
Déclarer un composant
Par défaut, le nom est le nom simple de la classe (commençant par une minuscule)
2 tags équivalent: @Component et @
Named
On peut spécifier le nom
@Component
(
"
injectedComponent
"
)
/**
* A simple bean that will be injected elsewhere
*/
@Component
public
class
InjectedBean {private String firstname = "John";private String lastname = "Doe";//.. Getter an setter ..}
Déclare un composantSlide10
Injecter un composant
@
Inject
Peut se faire sur un attribut, un setter, …
On peut spécifier le nom
@
Inject
(
"
injectedComponent
"
)
@Controller
public
class
HomeController
{/** * Try to inject a bean */@Injectprotected InjectedBean injectedBean;// ..}
Spring
injecte le
bean
du bon typeSlide11
EJB integrationSlide12
Webographie
22.2
Accessing
EJBs
http://docs.spring.io/spring/docs/4.0.0.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#ejbSlide13
Injecter des EJB Session
dans
Spring
C’est possible !
En deux temps:
déclarer le
bean
Session en tant que Component
Spring
injecter le component
SpringSlide14
Déclarer le bean
session en tant que Component
Dans le fichier de configuration
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
beans:beans
xmlns
=
"http://www.springframework.org/schema/mvc"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:beans="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:jee="http://www.springframework.org/schema/jee"xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"
>
<
jee:remote-slsb
id
=
"
myComponent
"
jndi-name="java:global/ipint13.springetejb.ear/ipint13.springetejb.domain/MyServiceBean" business-interface="ipint13.springetejb.domain.MyService"/></beans:beans>
declaration
du
namespace
la location de la
def du namespace
le nom jndi est affiché par le serveur dans ses logs
le nom spring
l’interface du
bean
JEESlide15
Injecter le bean
Methode
classique
@Controller
public
class
HomeController
{
@
Inject
protected
MyService
injectedBean
;
/** * Simply selects the home view to render by returning its name. */@RequestMapping(value = "/", method = RequestMethod.GET)public String home(Locale locale, Model model
) {
// …
if
(
injectedBean
==
null
) {
logger
.info(
"The bean is not injected !."
);
return
"home";}// Injection works !model.addAttribute("myInjectedBean", injectedBean );return "success";}Slide16
Accéder à un objet JNDI ou EJB
<
jee:jndi-lookup
>
Acces
par JNDI
<
jee:local-slsb
>
Acces
a un
bean
local
<
jee:remote-slsb
>
Acces
à un
bean distant<jee:local-slsb id="myComponent" jndi-name="ejb/myBean"business-interface="com.mycom.MyComponent"/>
<
bean
id
=
"
myController
"
class
=
"
com.mycom.myController
"
><property name="myComponent" ref="myComponent"/></bean>Slide17
Accéder à un objet JNDI ou EJB
Autre
methode
Permet d’utiliser le nom
jndi
directement dans les annotations
A tester
<
bean
class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<
property
name
="
alwaysUseJndiLookup
" value="
true
" /></bean>Slide18
Header, footer, body …Slide19
Tous les sites proposent
des pages cohérentes
Avec un header, un
footer
, un body, un menu …
Faut-il coder ces éléments dans toutes les pages ?
Et si on doit modifier le
footer
, faut-il alors modifier toutes les pages ?
Solution :
Utiliser un
framework
permettant de
separer
le header, le
footer
, le body et le menu …
Ex:
TilesSlide20
Principe
Définir une seule fois les parties communes:
Un header, un
footer
un main menu
Assembler les pages
Seule le body change
il faut coder celui-ci à part.
Une page == body + partie commune
Vous définissez le body
Le
framework
ce charge de construire la page en assemblant les parties pour vousSlide21
Webographie
Spring 3 MVC: Tiles
Plugin
Tutorial with Example in Eclipse
http://viralpatel.net/blogs/spring-3-mvc-tiles-plugin-tutorial-example-eclipse/
Tiles
https://tiles.apache.org/Slide22
Internationalisation i18nSlide23
Webographie
http://viralpatel.net/blogs/spring-3-mvc-internationalization-i18n-localization-tutorial-example/Slide24
Principe
Utilise la notion de « Locale »
Pays_langue
FR_fr
,
US_en
Dans le code, on utilise des constantes à la place du texte
Les constantes sont définies dans des fichiers
Pair nom=valeur
Un fichier par langue
Un fichier par défaut
Tous les fichiers ont le même nom
Mais des extensions en fonction du locale:
messages.properties
messages_FR_fr.propertiesSlide25
Alternatives:
Des pages différentes en fonction du locale
Possible avec
TilesSlide26
Spring MVC
Les fichiers
properties
Permet d’utiliser des constantes dans les pages
Les définitions sont dans des fichiers .
properties
fichier par défaut
fichier local =
fr
pas définit = venant du fichier par défautSlide27
La déclaration dans la page
<%@
taglib
uri
=
"http://java.sun.com/jsp/jstl/core"
prefix
=
"c"
%>
<%@
taglib
uri
=
"http://www.springframework.org/tags"
prefix
=
"spring"%><%@ page session="false" %><html><head><title><spring:message
code
=
"
page.home.title
"
/></
title
>
</
head
>
<
body
><h1><spring:message code="page.home.hello"/></h1><P> <spring:message code=
"page.home.timeOnServer
"/> ${serverTime
}. </P></body>
</html>
La
taglib
utilisée
Le messageSlide28
La configuration
Dans le fichier de configuration
Spring
[
servlet
]-config.xml
Spécifier que l’on veut utiliser les messages de
properties
<!-- Specify the source for i18n -->
<
beans:bean
id
=
"
messageSource
"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <beans:property name="basename" value="classpath:messages" /> <beans:property name
=
"
defaultEncoding
"
value
=
"UTF-8"
/>
</
beans:bean
>Slide29
Atelier
Créer un nouveau projet
Spring
.
Spring
génère une page « home ». Internationaliser cette page.Slide30
Laisser l’utilisateur
choisir sa langue
Il faut ajouter un choix du local
Il faut prendre en compte le changement
voir
tuto
http://viralpatel.net/blogs/spring-3-mvc-internationalization-i18n-localization-tutorial-example/Slide31
ValidationSlide32
Documentation
http://docs.spring.io/spring/docs/3.2.5.RELEASE/spring-framework-reference/htmlsingle/#validation
7.8.4
Spring
MVC 3 ValidationSlide33
Que valider ?
Il faut valider pour se garantir :
De
mauvaises saisies
dans les formulaires
De
données saisies non valables pour le métier
Les mauvaises saisies peuvent être détectés par:
la conversion de la requête http
objet command
Les contraintes métiers peuvent être détectés par:
des objets de validation
Spring
3.xSlide34
Erreur de conversion
@
ModelAttribute
permet de récupérer l’objet command.
Il est peuplé à partir de la
requete
, donc avec les valeurs saisies dans le formulaire.
Il y a conversion implicite String -> type dans l’objet commande
Il peut y avoir
plusieur
s @
ModelAttribute
BindingResult
result
contient
les
éventuelles
erreurs de conversiondoit être placé immédiatement après le @ModelAttribute auquel il se réfere@RequestMapping(method = RequestMethod.POST)protected String onSubmit( @ModelAttribute("commandAjout"
)
CommandAjout
commandAjout
,
BindingResult
result,
SessionStatus
status )
throws
Exception {
if
( result.hasErrors()) { return "formulaire";}groupe.addMembre(commandAjout.getNouveauMembre());status.setComplete();return "confirmation";}
retourne au formulaire en cas d’erreurs
efface la session si ok
Spring
3.xSlide35
Validation
Action de valider des données en fonction du métier
ex: 0<=
age
<150
Plusieurs possibilités avec
Spring
les technique se sont empilées avec le temps
Les plus récentes:
Validation explicite
@
Valid
JSR-303 Bean Validation APISlide36
Validation explicite
Nécessite un objet
validator
/**
Declare
a
validator
object
*/
Validator
contactValidator
=
new
ContactValidator
();
@RequestMapping(value = "/addContact2.html", method = RequestMethod.POST) public String addContact2(@ModelAttribute("command") Contact
contact
,
BindingResult
result
, Model
model
) {
contactValidator.validate
(contact,
result
); // Check the binding results. Binding and validations errors are contained // in the BindingResult object. // If there is some binding or validation errors, stop and return // to the form. if( result.hasErrors()) { System.err.println("
errors encountered !!"
); return
"contact"; } …}
Déclare un validator
appel la validation, Utilise le BindResult
Verifie le résultatSlide37
Exemple de Validator
public
class
ContactValidator
implements
Validator
{
/*
* This
Validator
validates
*
just Contact instances */ public boolean supports(Class clazz) { return Contact.class.equals(
clazz
);
}
public
void
validate
(Object
obj
,
Errors
e) { ValidationUtils.rejectIfEmptyOrWhitespace(e, "firstname", "firstname.empty", "First Name is required"); ValidationUtils.rejectIfEmptyOrWhitespace(e, "
lastname", "
lastname.empty", "Last Name is required"
); Contact p = (Contact) obj; if
(p.getAge() < 0) {
e.rejectValue("age", "negativevalue"
, "Age should be >0"); } else
if (p.getAge() > 110) { e.rejectValue
(
"age"
,
"
too.darn.old
"
,
"Age seem too old"
);
}
}
}
(
attributeName
,
errorCode
,
defaultMsg
)
errorCode
i18nSlide38
Spring et @
Valid
Préparation
Annotation JSR-303
nécessite validation-api.jar
Peut être utilisé avec
Spring
MVC
nécessite de déclarer les
validators
(dans le
controller
par exemple)
/**
* Register a
validator
that will be lookup when a parameter is
binded
to a handler * argument (with @ModelAttribute() for example). * @param binder */ @InitBinder protected void initBinder(WebDataBinder binder) {
// register the
ContactValidator
used to validate objects of type Contact.
binder.setValidator
(
new
ContactValidator
() );
}Slide39
Spring et @
Valid
Utilisation
/**
Handler called when
theform
is submitted.
* The
@Valid
annotation is used to validate the input model. Spring lookup for a
*
validator
accepting
the class.
*/
@RequestMapping(value = "/addContact.html", method = RequestMethod.POST) public String addContact(@Valid @ModelAttribute("command")
Contact
contact
,
BindingResult
result
, Model
model
) {
// Check the binding results. Binding and validations errors are contained
// in the BindingResult object. // If there is some binding or validation errors, stop and return // to the form. if( result.hasErrors()) { System.err.println("errors encountered !!"
); return
"contact"; }…
}
Un validator pour ce type doit être accessible !Slide40
JSR-303 Bean validation API
Annotation JSR-303
nécessite validation-api.jar
Nécessite une implémentation du standard !
Les contraintes de validation sont directement dans l’objet à valider
Voir doc
SpringSlide41
Gestion des erreursSlide42
Documentation
18.2 JSP & JSTL
http://docs.spring.io/spring/docs/4.0.0.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#view-jspSlide43
Comment afficher
les erreurs dans la page ?
Spring
renvoie l’objet
Errors
dans la réponse
Cet objet contient toutes les erreurs
Chaque erreur est identifiées par un id
le nom de la propriété en général
Le tag
<
form:errors
…>
utilise cet objet pour afficher des messages
On indique l’id de l’erreur à vérifier
le nom de la propriété en général …Slide44
L’objet Error
est remplie par le
Validator
public
class
ContactValidator
implements
Validator
{
/*
* This
Validator
validates *just Contact instances */ public boolean supports(Class clazz) { return Contact.class.
equals
(
clazz
);
}
public
void
validate
(Object
obj
, Errors e) { ValidationUtils.rejectIfEmptyOrWhitespace(e, "firstname", "firstname.empty", "First Name is required"); ValidationUtils.rejectIfEmptyOrWhitespace(e,
"lastname", "
lastname.empty", "Last Name is required"
); Contact p = (Contact) obj; if
(p.getAge() < 0) {
e.rejectValue("age", "negativevalue", "Age should be >0"
); } else if (
p.getAge() > 110) { e.rejectValue("age", "
too.darn.old
"
,
"Age seem too old"
);
}
}
}
(
attributeName
,
errorCode
,
defaultMsg
)
errorCode
i18nSlide45
Le <form:form
…> déclare où doivent être placé les messages d’erreurs
<%@
taglib
uri
=
"http://www.springframework.org/tags/form"
prefix
=
"form"
%>
<
html
>
<
head
>
<title>Spring 3 MVC Series - Contact Manager</title></head><body><h2>Contact Manager</h2>
<
form:form
method
=
"post"
action
=
"addContact.html"
>
<
table> <tr> <td><form:label path="firstname">First Name</form:label></td>
<td><form:input
path="firstname
" /></td> <%-- Show errors for
firstname field --%> <
td><form:errors path=
"firstname" /></td
> </tr>
<
tr
>
<
td
><
form:label
path
=
"
lastname
"
>
Last Name
</
form:label
></
td
>
<
td
><
form:input
path
=
"
lastname
"
/></
td
>
<%-- Show errors for
lastname
field --%>
<
td
>
<
form:errors
path
=
"
lastname
"
/></
td
>
</
tr
>
…
Affiché uniquement si l’erreur existe !