forked from fabienfelix/formation-programmation-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcours-javaee.html
More file actions
361 lines (339 loc) · 48.1 KB
/
Copy pathcours-javaee.html
File metadata and controls
361 lines (339 loc) · 48.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="author" content="Arnaud Tournier"><title>Java EE</title><meta content="yes" name="apple-mobile-web-app-capable"><meta content="black-translucent" name="apple-mobile-web-app-status-bar-style"><meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" name="viewport"><link href="reveal.js/css/reveal.css" rel="stylesheet"><link rel="stylesheet" href="reveal.js/css/theme/beige.css" id="theme"><link href="reveal.js/lib/css/zenburn.css" rel="stylesheet"><script type="text/javascript">document.write( '<link rel="stylesheet" href="reveal.js/css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );</script></head><body><div class="reveal"><div class="slides"><section><h1>Java EE</h1><p><small>Arnaud Tournier</small></p></section><section><section id="_java_ee"><h2>Java EE</h2><div class="paragraph"><p><strong>Définition</strong>, serveur d’application.</p></div><div class="paragraph"><p>Plateforme Java Enterprise Edition, sur ensemble de la plateforme standard.</p></div><div class="paragraph"><p>Facilite le développement et le déploiement d’applications web distribuées exécutées au sein des serveurs d’application.</p></div></section><section id="_quelques_implémentations"><h2>Quelques implémentations</h2><div class="paragraph"><p>JavaEE est une norme, il faut choisir l’implémentation : Tomcat, JBoss, Glassfish, …​</p></div>
<div class="paragraph"><p>Application divisées en couches, souvent trois (presentation, business, data).</p></div>
<div class="paragraph"><p>En pratique on a des pages htmls + servlets + jsp en frontal et ejb dans les couches internes (métier, processus et données).</p></div></section><section id="_structure_d_une_application_java_ee"><h2>Structure d’une application Java EE</h2><div class="listingblock"><div class="content"><pre class="highlight"><code>/
|- fichiers publiques **.html**, **.jsp**, **.css**, **.js**, ...
|- WEB-INF/ (_cachés à l'utilisateur_)
|- classes
|- fichiers **.class**
|- lib
|- fichiers **.jar**
|- **web.xml** : C'est un fichier de configuration de l'application</code></pre></div></div></section></section>
<section id="_développement_avec_eclipse"><h2>Développement avec Eclipse</h2><div class="paragraph"><p>Installation de Tomcat, déclaration dans Eclipse, création d’un projet Dynamic Web Application et du serveur dans Eclipse.</p></div>
<div class="paragraph"><p>Démarrage d’une application avec un fichier index.html dedans.</p></div></section>
<section id="_http"><h2>HTTP</h2><div class="paragraph"><p>Rappels HTTP, requête, méthode (GET, POST), headers, cookies.</p></div></section>
<section><section id="_servlet"><h2>Servlet</h2><div class="paragraph"><p>Une classe qui traite les requêtes HTTP.</p></div></section><section id="_mise_en_place"><h2>Mise en place</h2><div class="paragraph"><p>Une servlet est une simple classe Java…​</p></div>
<div class="ulist"><ul><li><p>Elle hérite de <code>javax.servlet.http.HttpServlet</code>,</p></li><li><p>On implémente une des méthodes choisies <code>doGet</code>, <code>doPost</code> (l’implémentation par défaut renvoie une page 404).</p></li><li><p>On indique au serveur quels sont l(es) URL(s) traitées par la servlet. Ceci se fait dans le fichier <code>web.xml</code> ou par annotation.</p></li></ul></div></section><section id="_httpservletrequest"><h2>HttpServletRequest</h2><div class="paragraph"><p>Représente la requête</p></div>
<div class="paragraph"><p>Paramètres, cookies</p></div>
<div class="paragraph"><p>Attributs…​</p></div></section><section id="_httpservletresponse"><h2>HttpServletResponse</h2><div class="paragraph"><p>Représente la réponse.</p></div></section><section id="_cycle_de_vie"><h2>Cycle de vie</h2><div class="paragraph"><p>Le cycle de vie est géré par le serveur d’application (<em>d’où son nom</em>).</p></div>
<div class="paragraph"><p>Celui-ci <em>crée</em> et <em>détruit</em> des instances de la classe.</p></div></section><section id="_exemple"><h2>Exemple</h2><div class="listingblock"><div class="content"><pre class="highlight"><code>class MaServlet extends HttpServlet
{
protected void doGet( HttpServletRequest r, HttpServletResponse re )
{
re.setContentType( "text/html; charset=utf8" );
re.getWriter().print( "Hello world !" );
}
}</code></pre></div></div></section></section>
<section><section id="_jsp"><h2>JSP</h2></section><section id="_définition"><h2>Définition</h2><div class="paragraph"><p>L’écriture de la vue (en HTML) est <em>pénible</em> dans un fichier Java. Les <code>JSP</code> permet au contraire d’écrire en HTML et d’injecter du Java.</p></div></section><section id="_fonctionnement"><h2>Fonctionnement</h2><div class="paragraph"><p>Vous écrivez des fichiers <code>.jsp</code>.</p></div>
<div class="paragraph"><p>Ces fichiers sont compilés vers des servlets Java.</p></div>
<div class="paragraph"><p>La servlet est accessible à l’URL correspondant au nom du fichier JSP (sauf quand il est dans <code>WEB-INF</code>).</p></div>
<div class="paragraph"><p>Les variables <code>request</code>, <code>response</code> sont accessibles.</p></div></section><section id="_exercice"><h2>Exercice</h2><div class="paragraph"><p>Faire une page de login.</p></div>
<div class="admonitionblock note"><table><tr><td class="icon"><div class="title">Note</div></td><td class="content">Mettre <code><%@ page pageEncoding="UTF-8" %></code> pour utf8.</td></tr></table></div>
<div class="paragraph"><p>Poser du code : <code><% …​ %></code></p></div>
<div class="paragraph"><p>Faire un echo : <code><%= …​ %></code></p></div>
<div class="paragraph"><p>Commentaires : <code><%-- …​ --%></code></p></div>
<div class="paragraph"><p>Directive : <code><%@ page import="package.class"%></code>, …​</p></div></section><section id="_délégation_1"><h2>Délégation 1</h2><div class="paragraph"><p>Délégation à partir d’une servlet :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code>void doGet( HttpServletRequest request, HttpServletResponse response )
{
this.getServletContext()
.getRequestDispatcher( "/WEB-INF/test.jsp" )
.forward( request, response );
}</code></pre></div></div></section><section id="_délégation_2"><h2>Délégation 2</h2><div class="paragraph"><p>Transmission d’information. Dans la servlet :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">request.setAttribute( "test", message );</code></pre></div></div>
<div class="paragraph"><p>Dans la JSP, on écrira :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="jsp language-jsp"><% String attribut = (String) request.getAttribute("test"); out.println( attribut );%></code></pre></div></div></section><section id="_formulaires"><h2>Formulaires</h2><div class="paragraph"><p>L’envoi de données au moment de la requête se fait grâce aux formulaires HTML.</p></div>
<div class="paragraph"><p>Les valeurs des formulaires sont récupérées grâce à la méthode <code>getParameter( String name )</code> de la classe <code>HttpServletRequest</code>.</p></div></section><section id="_méthode_get_et_post"><h2>Méthode GET et POST</h2></section><section id="_pattern_mvc"><h2>Pattern MVC</h2><div class="paragraph"><p>Le meilleur : peu de Java dans la JSP et peu de HTML dans le Java.</p></div>
<div class="paragraph"><p>On arrive naturellement au pattern <em>MVC</em> ou apparentés.</p></div></section><section id="_les_opérations_crud"><h2>Les opérations CRUD</h2><div class="paragraph"><p>En exercice, implémenter sur un type de données :</p></div>
<div class="ulist"><ul><li><p>l’affichage (<strong>D</strong>isplay),</p></li><li><p>la création de nouveaux éléments (<strong>C</strong>reate),</p></li><li><p>la suppression d’éléments (<strong>R</strong>emove),</p></li><li><p>la modification d’éléments (<strong>U</strong>pdate).</p></li></ul></div></section><section id="_les_jstl"><h2>Les JSTL</h2><div class="paragraph"><p>Il est possible d’étendre le <em>vocabulaire</em> des balises utilisables dans un ficher JSP.</p></div>
<div class="paragraph"><p>Cette fonctionnalité est fournie par les <em>tag lib</em> JSTL.</p></div>
<div class="paragraph"><p><a href="https://openclassrooms.com/courses/creez-votre-application-web-avec-java-ee/objectifs-et-configuration">OpenClassRooms</a></p></div></section><section id="_importation_d_une_tag_lib"><h2>Importation d’une tag lib</h2><div class="paragraph"><p><em>Au préalable, il faut avoir le jar <code>jstl-1.2.jar</code> dans le projet</em>.</p></div>
<div class="paragraph"><p>Import dans une JSP : <code><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %></code>, ceci définit le <em>namespace</em> XML <code>c</code>.</p></div></section><section id="_jstl_exemple_1"><h2>JSTL Exemple 1</h2><div class="paragraph"><p>Ceci est l’équivalent de la directive <code><%@ include file="…​" %></code> :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code><jsp:include page="<%= jspPageName %>" /></code></pre></div></div></section><section id="_jstl_exemple_2"><h2>JSTL Exemple 2</h2><div class="paragraph"><p>Nous souhaitons réécrire le code suivant :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="jsp language-jsp"><%
List<Integer> list = (ArrayList<Integer>) request.getAttribute( "tirage" );
for( int i = 0; i < list.size(); i++ ) {
out.println( list.get( i ) );
}
%></code></pre></div></div></section><section id="_jstl_exemple_2_2"><h2>JSTL Exemple 2</h2><div class="paragraph"><p>Voici l’équivalent avec la JSTL :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="jsp language-jsp"><c:forEach var="i" begin="0" end="7" step="1"> <b>(1)</b>
<tr>
<td><c:out value="${i}"/></td> <b>(2)</b>
<td><c:out value="${i * i * i}"/></td>
</tr>
</c:forEach></code></pre></div></div>
<div class="colist arabic"><ol><li><p>le noeud <code>forEach</code> crée une variable EL <code>i</code>.</p></li><li><p>la variable <code>i</code> est utilisée dans des expressions EL.</p></li></ol></div></section><section id="_expression_language"><h2>Expression Language</h2><div class="paragraph"><p><a href="https://openclassrooms.com/courses/creez-votre-application-web-avec-java-ee/la-technologie-jsp-2-2">OpenClassRooms</a>.</p></div>
<div class="paragraph"><p>Quelques éléments du langage :</p></div>
<div class="ulist"><ul><li><p><code>${ expression }</code> : <em>expression</em> va être interprêtée…​</p></li><li><p><code>${ true && true }</code> : …​</p></li><li><p><code>${ 10 mod 4 }</code> : …​</p></li><li><p><code>${ requestScope['nom'] }</code> : request.getAttribute( "nom" )</p></li><li><p><code>${ sessionScope['nom'] }</code> : session.getAttribute( "nom" )</p></li><li><p><code>${ param['id'] }</code> : request.getParameter( "id" )</p></li></ul></div></section><section id="_el_exemple"><h2>EL exemple</h2><div class="listingblock"><div class="content"><pre class="highlight"><code><%
List<String> legumes = new ArrayList<String>();
legumes.add( ... );
request.setAttribute( "legumes" , legumes );
%>
${ legumes.get(1) }
${ legumes[1] }
${ legumes["1"] }</code></pre></div></div></section><section id="_scope"><h2>Scope</h2><div class="paragraph"><p>JSP définit quatre <em>scopes</em> (portées ou cycles de vie) pour les objets :</p></div>
<div class="paragraph"><p><code>application</code>, <code>session</code>, <code>request</code> et <code>page</code>.</p></div>
<div class="paragraph"><p>Ceux-ci sont implémentés grâce aux attributs de requête, de session, et de contexte applicatif.</p></div></section><section id="_scope_2"><h2>Scope</h2><table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:33.3333%"><col style="width:33.3333%"><col style="width:33.3334%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Portée</th><th class="tableblock halign-left valign-top">Servlet</th><th class="tableblock halign-left valign-top">JSP</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>application</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><code>getServletContext()</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><code>applicationScope[]</code></p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>session</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><code>request.getSession()</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><code>sessionScope[]</code></p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>request</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><code>request</code></p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><code>requestScope[]</code></p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock"><strong>page</strong></p></td><td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td><td class="tableblock halign-left valign-top"><p class="tableblock"><code>pageScope[]</code></p></td></tr></tbody></table></section></section>
<section id="_javabean"><h2>JavaBean</h2><div class="paragraph"><p>Une convention pour exprimer la notion de <em>propriété</em>. En écriture et/ou lecture.</p></div>
<div class="paragraph"><p>Exemple, la propriété <code>Longueur</code> :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">int getLongueur() { ... }
void setLongueur( int valeur ) { ... }</code></pre></div></div>
<div class="paragraph"><p>Il peut y avoir une notion d’abonnement (pattern <em>Observer</em>).</p></div></section>
<section><section id="_jsf"><h2>JSF</h2></section><section id="_introduction"><h2>Introduction</h2><div class="paragraph"><p>C’est un framework MVC pour simplifier l’écriture d’interface graphiques Web.</p></div>
<div class="paragraph"><p>Fonctionne au dessus de l’api Servlet. Stable et utilisable depuis la version 2.0 en 2009.</p></div></section><section id="_facesservlet"><h2>FacesServlet</h2><div class="paragraph"><p>Une seule servlet prend en charge toutes les requêtes et maintient l’état de la vue de <em>chaque</em> client.</p></div>
<div class="paragraph"><p><code>javax.faces.webapp.FacesServlet</code></p></div></section><section id="_facelet"><h2>Facelet</h2><div class="paragraph"><p>La programmation des vues repose sur <em>Facelet</em>, description XML des composants de la vue.</p></div>
<div class="paragraph"><p>Fichiers <code>*.xhtml</code></p></div></section><section id="_controlleur"><h2>Controlleur</h2><div class="paragraph"><p>La programmation des actions (<em>controlleur</em>) s’écrit dans des <em>Java Beans</em>.</p></div>
<div class="paragraph"><p><code>@ManagedBean</code>, <code>@RequestScoped</code>, <code>@ViewScoped</code>, <code>@SessionScoped</code>, <code>@ApplicationScoped</code>, <code>@CustomScope</code> et <code>@NoneScoped</code>…​</p></div></section><section id="_modèle"><h2>Modèle</h2><div class="paragraph"><p>Les données attachées aux échanges HTTP sont stockées dans des <em>Java Beans</em> attachés aux différents scopes.</p></div></section><section id="_avantage"><h2>Avantage</h2><div class="paragraph"><p>Facilite la gestion conversationnelle grâce au modèle par composant.</p></div>
<div class="paragraph"><p>Gère par ex. état des vues, maj des modèles, invocation des actions métiers, génération de la réponse, évènements, validation, internationnalisation…​</p></div></section><section id="_contrepartie"><h2>Contrepartie</h2><div class="paragraph"><p>On ne maîtrise pas vraiment le HTML généré car la génération de celui-ci est encapsulée dans le code des composants.</p></div></section><section id="_structure_d_une_application_jsf"><h2>Structure d’une application JSF</h2><div class="ulist"><ul><li><p>Vue : Facelet (un fichier <strong>xhtml</strong>),</p></li><li><p>Modèle : entité JPA ou JavaBean,</p></li><li><p>Controlleur : des `@ManagedBean`s</p></li></ul></div>
<div class="paragraph"><p>Configuration en plus de <code>web.xml</code> dans <code>faces-config.xml</code>.</p></div></section><section id="_les_fichiers_facelet"><h2>Les fichiers Facelet</h2><div class="paragraph"><p>Ce ne sont que des fichiers XHTML (HTML conforme au XML). On utilise les extensions : <strong>.jsf</strong> ou <strong>.xhtml</strong> ou <strong>.faces</strong>.</p></div>
<div class="paragraph"><p>Références des balises JSF : <a href="http://docs.oracle.com/javaee/6/javaserverfaces/2.1/docs/vdldocs/facelets/">ici</a>, <a href="http://www.jsftoolbox.com/documentation/help/12-TagReference/index.jsf">ici</a> et sur <a href="http://stackoverflow.com/tags/jsf/info">stack overflow</a>.</p></div></section><section id="_exemple_2"><h2>Exemple</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="xml language-xml"><!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Bienvenue</title>
<h:outputStylesheet library="default" name="cartes.css"></h:outputStylesheet>
</h:head>
<h:body>
<h:form>
<h:inputText value="#{utilisateur.nom}" />
<h:commandButton value="Valider" action="bienvenue" />
</h:form>
</h:body>
</html></code></pre></div></div></section><section id="_expression_language_pour_jsf"><h2>Expression Language pour JSF</h2><div class="paragraph"><p>L’évolution technique d’expression language fait que pour JSF, on utilise la syntaxe du type :</p></div>
<div class="literalblock"><div class="content"><pre>#{inscrireBean.utilisateur.motDePasse}</pre></div></div>
<div class="paragraph"><p>On voit donc que <code>$</code> est remplacé par <code>#</code>. Ceci correspond au fait que l’expression language pour JSF permet d’appeler des <strong>setters</strong> sur les java beans, ce qui n’est pas permis avec <code>$</code>.</p></div>
<div class="paragraph"><p>Depuis Java EE 6, expression language a été unifié et il est maintenant possible d’utiliser <code>#</code> dans les JSP.</p></div></section><section id="_les_6_étapes_du_traitement_d_une_requête_1_2"><h2>Les 6 étapes du traitement d’une requête (1/2)</h2><div class="ulist"><ul><li><p><strong>Restauration de la vue</strong> : si c’est un premier accès JSP crée une donnée de vue (l’arbre des composants) dans <code>FacesContext</code>. Sinon JSF recharge simplement les données de la vue.</p></li><li><p><strong>Application des paramètres</strong> de la requête : JSF fait automatiquement le lien entre les paramètres présents dans la requête et les champs du modèle à modifier.</p></li><li><p><strong>Validation des données</strong> : si la validation échoue, on passe directement à la dernière étape.</p></li></ul></div></section><section id="_les_6_étapes_du_traitement_d_une_requête_2_2"><h2>Les 6 étapes du traitement d’une requête (2/2)</h2><div class="ulist"><ul><li><p><strong>Mise à jour du modèle</strong> : si la validation s’est bien déroulée, cette étape consiste à mettre à jour les données du modèle avec les données validées.</p></li><li><p><strong>Appel au code métier</strong> de l’application : les actions déclarées dans les formulaires sont exécutées, sous la forme d’appels aux méthodes des Beans.</p></li><li><p><strong>Rendu de la réponse</strong> : l’arbre des composants est appelé afin de générer le HTML résultat. Il est mémorisé pour la prochaine <em>Restauration de vue</em>.</p></li></ul></div></section><section id="_configuration"><h2>Configuration</h2><div class="paragraph"><p>Dans <code>web.xml</code> on ajoute :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="xml language-xml"><context-param>
<!-- autres noms possibles : STATE_SAVING_METHOD, INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL ... -->
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping></code></pre></div></div></section><section id="_tutoriel"><h2>Tutoriel</h2><div class="paragraph"><p><a href="https://openclassrooms.com/courses/creez-votre-application-web-avec-java-ee/premiers-pas-avec-jsf" class="bare">https://openclassrooms.com/courses/creez-votre-application-web-avec-java-ee/premiers-pas-avec-jsf</a></p></div></section><section id="_gestion_de_formulaires"><h2>Gestion de formulaires</h2><div class="paragraph"><p><a href="https://openclassrooms.com/courses/creez-votre-application-web-avec-java-ee/la-gestion-d-un-formulaire-avec-jsf" class="bare">https://openclassrooms.com/courses/creez-votre-application-web-avec-java-ee/la-gestion-d-un-formulaire-avec-jsf</a></p></div></section></section>
<section><section id="_jpa"><h2>JPA</h2></section><section id="_systèmes_de_gestion_de_base_de_données_relationnelles"><h2>Systèmes de gestion de base de données relationnelles</h2><div class="paragraph"><p>Un outil pour :</p></div>
<div class="ulist"><ul><li><p><strong>structurer</strong>,</p></li><li><p><strong>stocker</strong>,</p></li><li><p><strong>interroger</strong>,</p></li><li><p>et garantir l'<strong>intégrité</strong> des données.</p></li></ul></div></section><section id="_service"><h2>Service</h2><div class="paragraph"><p>Le SGBD est un processus actif sur une machine. Il ouvre des ports de communication.</p></div>
<div class="paragraph"><p>Et les applications s’y connectent.</p></div></section><section id="_table"><h2>Table</h2><div class="paragraph"><p>Nous stockons les <strong>enregistrements</strong> dans des <strong>tables</strong> possédant une ou plusieurs <strong>colonnes</strong> :</p></div>
<table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:50%"><col style="width:50%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Nom</th><th class="tableblock halign-left valign-top">Prénom</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock">Tournier</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Arnaud</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">Dupont</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Jean</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">Serres</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Mélanie</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">Dupont</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Jean</p></td></tr></tbody></table></section><section id="_clé"><h2>Clé</h2><div class="paragraph"><p>Les enregistrements sont repérés de façon sûre grâce aux <strong>identifiants</strong> aussi appelés <strong>clés primaire (PK)</strong>.</p></div>
<div class="paragraph"><p>Chaque identifiant est <strong>unique</strong>.</p></div>
<table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:33.3333%"><col style="width:33.3333%"><col style="width:33.3334%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">ID</th><th class="tableblock halign-left valign-top">Nom</th><th class="tableblock halign-left valign-top">Prénom</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Tournier</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Arnaud</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Dupont</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Jean</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Serres</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Mélanie</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Dupont</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Jean</p></td></tr></tbody></table></section><section id="_clé_étrangère"><h2>Clé étrangère</h2><div class="paragraph"><p>Pour relier les enregistrements entre eux, on utilise les <strong>clés étrangères</strong> :</p></div>
<table class="tableblock frame-all grid-all" style="width:100%"><colgroup><col style="width:25%"><col style="width:25%"><col style="width:25%"><col style="width:25%"></colgroup><thead><tr><th class="tableblock halign-left valign-top">ID</th><th class="tableblock halign-left valign-top">Entreprise_ID</th><th class="tableblock halign-left valign-top">Nom</th><th class="tableblock halign-left valign-top">Prénom</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">44</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Tournier</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Arnaud</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Dupont</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Jean</p></td></tr><tr><td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">44</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Serres</p></td><td class="tableblock halign-left valign-top"><p class="tableblock">Mélanie</p></td></tr></tbody></table></section><section id="_ddl"><h2>DDL</h2><div class="paragraph"><p>Langage permettant de définir la structure des données dans la base de données.</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="sql language-sql">CREATE TABLE IF NOT EXISTS `personne` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nom` text COLLATE utf8_bin NOT NULL,
`prenom` varchar(50) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1;</code></pre></div></div></section><section id="_sql"><h2>SQL</h2><div class="paragraph"><p>Langage permettant d’interroger, de créer, supprimer et manipuler les données, en fonction de la structure définie.</p></div>
<div class="paragraph"><p>Quelques exemples…​</p></div></section><section id="_insert"><h2>Insert</h2><div class="paragraph"><p>Insérer un enregistrement dans une table :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="sql language-sql">INSERT INTO `personne` (`nom`, `prenom`) VALUES ('Tournier', 'Arnaud');</code></pre></div></div>
<div class="paragraph"><p>Dans cette table, l’identifiant est généré automatiquement…​</p></div></section><section id="_update"><h2>Update</h2><div class="paragraph"><p>Mise à jour d’un ou des enregistrements :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="sql language-sql">UPDATE `personne` SET `nom`="Toto", `prenom`="Titi" WHERE id=1;</code></pre></div></div></section><section id="_delete"><h2>Delete</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="sql language-sql">DELETE FROM `personne` WHERE nom LIKE "To%";</code></pre></div></div></section><section id="_select"><h2>Select</h2><div class="paragraph"><p>L’opération la plus utilisée : pour consulter la base de données</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="sql language-sql">SELECT * FROM `personne` WHERE prenom LIKE "a%";</code></pre></div></div></section><section id="_jointure"><h2>Jointure</h2><div class="paragraph"><p>Il est possible de <em>combiner</em> des tables en faisant un select :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="sql language-sql">SELECT * FROM `personne` p LEFT JOIN `entreprise` e ON p.entreprise_id=e.id;
SELECT p.id, p.nom, e.nom, e.adresse FROM `personne` p LEFT JOIN `entreprise` e ON p.entreprise_id=e.id;</code></pre></div></div></section><section id="_transactions"><h2>Transactions</h2><div class="paragraph"><p>On souhaite pouvoir exécuter une suite d’instruction de manière <strong>atomique</strong> et <strong>cohérente</strong> (voir les propriétés <em>ACID</em>).</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="sql language-sql">START TRANSACTION;
COMMIT; // on valide ou...
ROLLBACK; // on annule</code></pre></div></div>
<div class="paragraph"><p><em>Interblocage ?</em></p></div></section><section id="_bien_plus"><h2>Bien plus…​</h2><div class="paragraph"><p>Le langage SQL est extrêmement riche, nous avons à peine gratté la surface…​</p></div>
<div class="paragraph"><p>Voici un <a href="http://sql.sh/">cours et tutoriel</a> pour aller plus loin.</p></div></section><section id="_quelques_serveurs_sql"><h2>Quelques serveurs SQL</h2><div class="paragraph"><p>De nombreuses implémentations existent, avec parfois quelques variantes dans le <em>dialecte</em> SQL : MySQL, MariaDB, Oracle, PostgreSQL, Microsoft SQL Server, SQLite, …​</p></div></section><section id="_important"><h2>Important !</h2><div class="ulist"><ul><li><p>Un SGBD peut gérer plusieurs <em>bases de données</em>,</p></li><li><p>Une base de données peut contenir plusieurs <em>tables</em>,</p></li><li><p>Une table possède plusieurs <em>colonnes</em>.</p></li><li><p>Les enregistrements sont repérés par leur <em>clé primaire</em>,</p></li><li><p>On référence un enregistrement à partir d’un autre avec une <em>clé étrangère</em>.</p></li><li><p>SQL garantit la cohérence des données avec les <em>transactions</em>.</p></li></ul></div></section><section id="_accès_depuis_un_programme_java"><h2>Accès depuis un programme Java</h2><div class="paragraph"><p>L’accès le plus bas niveau avec Java se fait à travers le <em>driver JDBC</em> adapté au serveur auquel on se connecte.</p></div></section><section id="_charger_le_driver_adapté"><h2>Charger le driver adapté</h2><div class="paragraph"><p>La classe doit être présente dans le <em>classpath</em>…​</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">try
{
Class.forName( "com.mysql.jdbc.Driver" );
}
catch( ClassNotFoundException e )
{
...
}</code></pre></div></div></section><section id="_se_connecter_au_serveur_sql"><h2>Se connecter au serveur SQL</h2><div class="paragraph"><p>Il faut connaître l’URL de connexion…​</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">try
{
Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/cartes", "root", "password" );
}
catch( SQLException e )
{
...
}</code></pre></div></div></section><section id="_exécuter_des_requêtes"><h2>Exécuter des requêtes</h2><div class="paragraph"><p>Exemple de <code>SELECT</code> :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery( "SELECT id, nom, couleur from carte" ); <b>(1)</b>
while( rs.next() )
{
String id = rs.getString( "id" );
String nom = rs.getString( "nom" );
String couleur = rs.getString( "couleur" );
System.out.printf( "%s %s %s\n", id, nom, couleur );
}</code></pre></div></div>
<div class="colist arabic"><ol><li><p>Il existe aussi <code>execute()</code> et <code>executeUpdate()</code></p></li></ol></div></section><section id="_les_transactions"><h2>Les transactions</h2><div class="paragraph"><p>Les instructions de transactions sont accessibles directement en Java :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">// on désactive l'auto-commit
conn.setAutoCommit( false );
// on joue la transaction...
Statement statement = conn.createStatement();
// ...
// on valide la transaction
conn.commit();
// on aurait pu l'annuler avec 'conn.rollback()'</code></pre></div></div></section><section id="_plus_de_jdbc"><h2>Plus de JDBC</h2><div class="paragraph"><p>Pour aller plus loin avec JDBC, consulez la <a href="https://docs.oracle.com/javase/tutorial/jdbc/basics/">documentation officielle</a>.</p></div></section><section id="_orm"><h2>ORM</h2><div class="paragraph"><p>L’écriture du code SQL et DDL est fastidieuse et répétitive. Les _ORM_s sont une sur-couche qui permettent un accès au SGBD plus conforme à la vision objet.</p></div>
<div class="paragraph"><p>L’ORM prend en charge la communication avec le SGBD et fourni à l’application une <em>API</em> de plus haut niveau.</p></div></section><section id="_jpa_2"><h2>JPA</h2><div class="ulist"><ul><li><p>Java Persistence API,</p></li><li><p><a href="https://jcp.org/en/jsr/detail?id=317">JSR 317</a>,</p></li><li><p><em>Entity manager</em> et <em>Entités</em>,</p></li><li><p>langage <em>JPQL</em>…​</p></li><li><p>package <code>javax.persistence</code>.</p></li></ul></div></section><section id="_fournisseurs"><h2>Fournisseurs</h2><div class="paragraph"><p>Plusieurs implémentations : Hibernate, Toplink, DataNucleus, …​</p></div></section><section id="__entity"><h2>@Entity</h2><div class="ulist"><ul><li><p>Classe dont l’état est sauvegardé dans une <em>table</em>.</p></li><li><p>Chaque instance correspond à un <em>enregistrement</em>.</p></li><li><p>Les attributs correspondent aux colonnes.</p></li><li><p>Les relations sont exprimées avec des annotations (ou xml).</p></li></ul></div></section><section id="__id"><h2>@Id</h2><div class="paragraph"><p>Dénote l’attribut utilisé comme clé primaire.</p></div>
<div class="paragraph"><p>On précise la stratégie de génération des identifiants.</p></div></section><section id="_exemple_3"><h2>Exemple</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">@Entity
public class Utilisateur implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Integer id;
@NotNull
private String nom;
// méthodes, getters, setters
}</code></pre></div></div></section><section id="_entity_manager"><h2>Entity Manager</h2><div class="paragraph"><p>Une instance de la classe <code>EntityManager</code> fait le lien entre les données de la base et les objets <em>entités</em>.</p></div>
<div class="paragraph"><p>Opérations essentielles : <code>persist</code>, <code>merge</code>, <code>remove</code>, <code>find</code>, <code>createQuery</code>…​</p></div>
<div class="paragraph"><p>Objets détachés…​</p></div></section><section id="_persist"><h2>Persist</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">public void add( Utilisateur utilisateur )
{
em.persist( utilisateur );
}</code></pre></div></div></section><section id="_merge"><h2>Merge</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">public Utilisateur save( Utilisateur utilisateur )
{
return em.merge( utilisateur );
}</code></pre></div></div></section><section id="_find"><h2>Find</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">public Utilisateur findById( int id )
{
return em.find( Utilisateur.class, id );
}</code></pre></div></div></section><section id="_remove"><h2>Remove</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">public void delete( Utilisateur utilisateur )
{
em.remove( utilisateur );
}</code></pre></div></div></section><section id="_jpql"><h2>JPQL</h2><div class="paragraph"><p>Langage inspiré par SQL qui est pensé avec le paradigme objet.</p></div></section><section id="_create_query"><h2>Create Query</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">public Utilisateur findByLogin( String login, String motDePasse )
{
Query query = em.createQuery( "from Utilisateur u where u.login=:login and u.motDePasse=:motDePasse" );
query.setParameter( "login", login );
query.setParameter( "motDePasse", motDePasse );
Utilisateur u = (Utilisateur) query.getSingleResult();
return u;
}</code></pre></div></div></section><section id="_create_query_2"><h2>Create Query</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">public List<Utilisateur> getUtilisateurs()
{
Query query = em.createQuery( "from Utilisateur" );
List<Utilisateur> result = (List<Utilisateur>) query.getResultList();
return result;
}</code></pre></div></div></section><section id="_criteria_api"><h2>Criteria API</h2><div class="paragraph"><p>Il y a aussi une <a href="http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html">API</a> pour éviter le <em>JPQL</em> et construire les requêtes programmatiquement.</p></div></section><section id="_requêtes_nommées"><h2>Requêtes nommées</h2></section><section id="_relations"><h2>Relations</h2><div class="paragraph"><p>JPA gère les relations entre enregistrements et donc entre entités.</p></div>
<div class="paragraph"><p><a href="http://docs.oracle.com/javaee/7/tutorial/persistence-intro001.htm#BNBQA">voir ce site</a></p></div></section><section id="__onetoone"><h2>@OneToOne</h2></section><section id="__onetomany"><h2>@OneToMany</h2></section><section id="__manytoone"><h2>@ManyToOne</h2></section><section id="__manytomany"><h2>@ManyToMany</h2></section><section id="_utilisation_standalone"><h2>Utilisation standalone</h2><div class="paragraph"><p>Il est possible d’utiliser JPA indépendamment d’un serveur d’application Java EE.</p></div></section><section id="_dans_une_application_javaee"><h2>Dans une application JavaEE</h2><div class="paragraph"><p>JPA est totalement intégré au fonctionnement d’une application Java EE.</p></div>
<div class="paragraph"><p>Plusieurs éléments de configuration sont nécessaires…​</p></div></section><section id="_sources_de_données"><h2>Sources de données</h2><div class="paragraph"><p>Les <em>Data source</em> sont configurées dans le serveur d’application. On y précise le <em>driver</em>, l'<em>url de connexion</em> et les information d'<em>authentification</em>.</p></div>
<div class="paragraph"><p>Chaque implémentation se configure différemment.</p></div></section><section id="_fichier_persistence"><h2>Fichier persistence</h2><div class="paragraph"><p><code>META-INF/persistence.xml</code></p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="xml language-xml"><?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="Cartes" transaction-type="JTA"> <b>(1)</b>
<jta-data-source>CartesDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
</properties>
</persistence-unit>
</persistence></code></pre></div></div>
<div class="colist arabic"><ol><li><p>Type de transaction JTA</p></li></ol></div></section><section id="_ejb"><h2>EJB</h2><div class="ulist"><ul><li><p><strong>Composants</strong> logiciels (métier) de base de Java EE.</p></li><li><p>Naturellement <strong>distribué</strong>.</p></li><li><p>Evoluent dans un milieu <strong>transactionnel</strong>.</p></li></ul></div></section><section id="_plusieurs_types"><h2>Plusieurs types</h2><div class="ulist"><ul><li><p><code>@Local</code> ou <code>@Remote</code>,</p></li><li><p><code>@Stateful</code> ou <code>@Stateless</code>,</p></li><li><p>EJB Message.</p></li><li><p>Enregistré dans JNDI.</p></li></ul></div></section><section id="_création_d_un_ejb"><h2>Création d’un EJB</h2><div class="paragraph"><p>Soit une interface (<code>@Remote</code> ou <code>@Local</code>) et une classe, soit depuis EJB 3 une seule classe :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">// un EJB de session sans état
@Stateless
public class MonEJB {
// par exemple :
@PostConstruct
void onInit() {
}
}</code></pre></div></div></section><section id="_injection_de_dépendances"><h2>Injection de dépendances</h2><div class="paragraph"><p>Le serveur d’application peut injecter des composants en utilisant les annotations :</p></div>
<div class="ulist"><ul><li><p><code>@EJB</code> : un autre EJB,</p></li><li><p><code>@Resource</code> : une resource JNDI (EntityManager, UserTransaction, SessionContext, …​),</p></li></ul></div></section><section id="_exemple_4"><h2>Exemple</h2><div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">@Stateless( mappedName = "MarinService" )
public class MarinServiceImpl implements MarinService {
@Resource
private UserTransaction transaction;
@Resource( mappedName = "jdbc/CartesDS" )
private DataSource dataSource;
@PersistenceContext( unitName = "CartesDS" )
private EntityManager em;
// ...
}</code></pre></div></div></section><section id="_injection_de_l_unité_de_persistence"><h2>Injection de l’unité de persistence</h2><div class="paragraph"><p>Au sein d’un <em>EJB</em>, on peut injecter une instance de l'`EntityManager` :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">@Stateless
public class ProduitDao
{
@PersistenceContext( name = "SiteDeVente" )
EntityManager em;
// ...
// utilisation de l'EntityManager
}</code></pre></div></div></section><section id="_injection_du_dao"><h2>Injection du DAO</h2><div class="paragraph"><p>Au sein d’une servlet ou d’un <em>Managed Bean</em>, il est possible d’injecter une instance de l’EJB :</p></div>
<div class="listingblock"><div class="content"><pre class="highlight"><code class="java language-java">@ManagedBean
@ViewScoped
public class ProduitsBean implements Serializable
{
@EJB
ProduitDao produitDao;
// ...
// utilisation du DAO
}</code></pre></div></div></section><section id="_gestion_de_la_transaction"><h2>Gestion de la transaction</h2><div class="paragraph"><p>Les méthodes EJB s’exécutent dans un contexte <em>transactionnel</em>. Une transaction est (toujours) ouverte (automatiquement).</p></div>
<div class="paragraph"><p>Le comportement est modifiable avec <code>@TransactionAttribute</code>.</p></div>
<div class="paragraph"><p>Si une exception surgit hors de la méthode, la transaction est abandonnée (<em>rollback</em>).</p></div></section><section id="_pattern_dao"><h2>Pattern DAO</h2><div class="dlist"><dl><dt class="hdlist1">DAO</dt><dd><p>Data Access Object ayant la responsabilité de fournir les données.
C’est lui qui accède à l'`EntityManager`.</p></dd></dl></div></section><section id="_organisation_en_couches"><h2>Organisation en couches</h2><div class="paragraph"><p>Données, Métier, Présentation…​</p></div></section></section></div></div><script src="reveal.js/lib/js/head.min.js"></script><script src="reveal.js/js/reveal.js"></script><script type="text/javascript">// See https://github.com/hakimel/reveal.js#configuration for a full list of configuration options
Reveal.initialize({
// Display controls in the bottom right corner
controls: true,
// Display a presentation progress bar
progress: true,
// Display the page number of the current slide
slideNumber: false,
// Push each slide change to the browser history
history: true,
// Enable keyboard shortcuts for navigation
keyboard: true,
// Enable the slide overview mode
overview: true,
// Vertical centering of slides
center: true,
// Enables touch navigation on devices with touch input
touch: true,
// Loop the presentation
loop: false,
// Change the presentation direction to be RTL
rtl: false,
// Turns fragments on and off globally
fragments: true,
// Flags if the presentation is running in an embedded mode,
// i.e. contained within a limited portion of the screen
embedded: false,
// Number of milliseconds between automatically proceeding to the
// next slide, disabled when set to 0, this value can be overwritten
// by using a data-autoslide attribute on your slides
autoSlide: 0,
// Stop auto-sliding after user input
autoSlideStoppable: true,
// Enable slide navigation via mouse wheel
mouseWheel: false,
// Hides the address bar on mobile devices
hideAddressBar: true,
// Opens links in an iframe preview overlay
previewLinks: false,
// Theme (e.g., beige, black, league, night, serif, simple, sky, solarized, white)
// NOTE setting the theme in the config no longer works in reveal.js 3.x
//theme: Reveal.getQueryHash().theme || 'beige',
// Transition style (e.g., none, fade, slide, convex, concave, zoom)
transition: Reveal.getQueryHash().transition || 'slide',
// Transition speed (e.g., default, fast, slow)
transitionSpeed: 'default',
// Transition style for full page slide backgrounds (e.g., none, fade, slide, convex, concave, zoom)
backgroundTransition: 'fade',
// Number of slides away from the current that are visible
viewDistance: 3,
// Parallax background image (e.g., "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'")
parallaxBackgroundImage: '',
// Parallax background size in CSS syntax (e.g., "2100px 900px")
parallaxBackgroundSize: '',
// The "normal" size of the presentation, aspect ratio will be preserved
// when the presentation is scaled to fit different resolutions. Can be
// specified using percentage units.
width: 960,
height: 700,
// Factor of the display size that should remain empty around the content
margin: 0.1,
// Bounds for smallest/largest possible scale to apply to content
minScale: 0.2,
maxScale: 1.5,
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'reveal.js/lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'reveal.js/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'reveal.js/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'reveal.js/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'reveal.js/plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: 'reveal.js/plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
]
});</script></body></html>