Java component that extends the capabilities of a server.
https://en.wikipedia.org/wiki/Java_servlet
Partie intégrante d’une application web
-
Dans
WEB-INF, inaccessible en HTTP -
En dehors de
WEB-INF, accessible en HTTP via le chemin vers la ressource :-
/page/hello.htmlest accessible via http://domain:port/page/hello.html
-
-
Pages d’accueil
-
Déclaration de servlets
-
Déclaration de filtres
-
Paramètres d’initialisation
-
etc.
-
Situé dans répertoire
WEB-INF -
Référence un schéma XSD
-
Dépend de la version de Java EE
-
Optionnel !
-
Corrélé à une URL
-
Modèle requête réponse :
-
Activé par l’envoi d’une requête
-
Retourne (souvent) une réponse
-
-
Le cycle de vie est géré par le serveur d’applications
-
Instanciation
-
Service
-
Destruction
-
-
Il peut exister n instances à un moment t
-
On ne sait pas quelle instance est appelée
<web...>
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>ch.frankel.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web>package ch.frankel;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet { ... }Représentation Java d’une réponse HTTP :
-
Envoi d’un code erreur HTTP
-
Redirection vers une autre URL
-
Gestion des en-têtes HTTP
-
Gestion des cookies
-
Ecriture :
-
de caractères (texte)
-
d’octets (binaire)
-
public class SendErrorServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req,
HttpServletResponse res) {
res.sendError(500);
}
}-
Le navigateur reçoit un code HTTP 30x :
-
Lecture de l’URL configurée dans l’en-tête HTTP
Location -
Nouvelle requête
GETà cette URL
-
public class RedirectServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req,
HttpServletResponse resp) {
resp.sendRedirect("https://www.google.com");
}
}public class PrintServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req,
HttpServletResponse resp) {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println("<html><body>");
out.println("Hello world!");
out.println("</body></html>");
}
}Représentation Java d’une requête HTTP :
GET /java/index.html HTTP/1.1
Host: formations.github.io
Accept: image/gif, image/jpeg, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)-
Analyse de la requête :
-
Accès à l’URL (protocole, domaine, paramètres, etc.)
-
Accès aux cookies
-
Accès aux en-têtes HTTP
-
-
Accès à la session HTTP
-
Accès au
RequestDispatcher
-
Fait suivre la chaîne de traitement au prochain servlet
-
Inclut la réponse du prochain servlet dans le flux actuel
public class ForwardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
req.getRequestDispatcher("/resource")
.forward(req, resp);
}
}-
Ecrire du HTML via le
PrintWriterest laborieux -
Prévisualisation impossible pour les web designers
-
Format texte
-
Au premier appel, le container :
-
Translate la JSP en servlet
-
Compile le servlet
-
<!DOCTYPE html>
<html>
<head>
<title>Hello world</title>
<body>
<% Object n = request.getAttribute("name"); %>
Hello <% out.println(n); %>
</body><!DOCTYPE html>
<html>
<head>
<title>Hello world</title>
<body>
Hello <%= request.getAttribute("name") %>
</body><%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<title>Hello world</title>
<body>
Hello <c:out value="requestScope.name" />
</body>| Type | Exemple |
|---|---|
Import |
|
Inclusion |
|
Taglib |
|
-
Ignoré dans le processus de compilation
-
Ne sera pas disponible dans le HTML généré
-
Balisé par
<%--et--%>
-
Déclaration de méthodes et d’attributs
-
Pour information (très peu utilisé)
-
Balisé par
<%!et%>
| Variable | Type |
|---|---|
|
|
|
|
|
|
|
|
| Variable | Type |
|---|---|
|
|
|
|
|
|
|
|
|
|
| Rôle | Composant | Fonctionnalité |
|---|---|---|
Contrôleur |
Servlet |
Gère le flux de contrôle |
Vue |
JSP |
Affiche la page |
Modèle |
|
Gère les données |
-
Comment transférer des données au travers du pipeline de traitement d’une requête ?
-
Par exemple, du contrôleur (servlet) à la vue (JSP)
-
Servlet dédié au traitement des données (validation, enregistrement, etc.)
-
JSP dédiée à l’affichage du HTML
-
"Bravo M. Dupont, vous avez bien été enregistré"
-
-
Il faut transférer les données (titre et nom) du servlet à la JSP
-
A chaque
HttpServletRequestest associée uneMap<String, Object>.-
Le servlet stocke l’objet comme attribut de requête sous la clé
key -
Le servlet forward à la JSP
-
La JSP récupère l’attribut de requête sous la clé
key -
Le transtype dans le type correct
-
-
HTTP est un protocole déconnecté
-
Impossible de savoir si 2 requêtes proviennent de la même session navigateur
-
Utilisation d’un cookie
JSESSIONID
-
-
Cookie géré automatiquement par le serveur d’applications
-
Ensemble d’attributs spécifiques à une session navigateur
-
Stockés en mémoire
-
Attention :
-
Aux collections sans limite de taille
-
Aux objets de taille trop importante
-
-
Dans le modèle MVC, la JSP joue le rôle de vue
-
Mais les scriptlets permettent tout
-
Par exemple, d’accéder à la base de données
-
-
Une spécification décrit comment créer une librairie
-
La librairie comporte des fonctionnalités spécifiques
-
Intégrable dans les JSPs
Taglib |
Balise XML à laquelle est associée une classe Java compilée |
Tag file |
Balise XML à laquelle est associée un fichier |
Expression Language - EL |
Exécute du code arbitraire |
-
${sessionScope.cart.numberOfItems} -
${param['mycom.productId']} -
${requestScope['javax.servlet.forward.servlet_path']} -
${!empty param.Add} -
etc.
Spécifiée par un fichier Tag Library Descriptor
-
Dans le répertoire
META-INFdu JAR de taglib -
Référence les classes de Taglib
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="urn:foo:bar"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://foo.bar/bar.xsd"
version="2.1">
<display-name>Foo Bar</display-name>
<tlib-version>1.0</tlib-version>
<short-name>foo</short-name>
<uri>http://foo.com/bar</uri>
<tag>
<name>bar</name>
<tag-class>ch.frankel.BarTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>baz</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib><%@ taglib uri="http://foo.com/bar" prefix="foo" %>
<html>
<body>
<foo:bar baz="hello">
<h1>Title</h1>
</foo:bar>
</body>
</html>-
Core -
c -
Internationalisation -
fmt -
Tag Library Validator -
tlv -
(SQL -
sql)
<% List person = (List) request.getAttribute("persons"); %>
<% for (Person person: persons) { %>
<%= person.getName() %>
<% } %>First, they provide the ability to encapsulate recurring tasks in reusable units. […] Second, filters can be used to transform the response from a servlet or a JSP page.
http://www.oracle.com/technetwork/java/filters-137243.html
-
Authentification
-
Logging
-
Conversion d’image
-
Compression de données
-
Cryptage
-
etc.
<web...>
<filter>
<filter-name>Authenticate</filter-name>
<filter-class>ch.frankel.AuthenticateFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Authenticate</filter-name>
<url-pattern>/secure/*</url-pattern>
</filter-mapping>
</web>package ch.frankel;
@WebFilter("/secure/*")
public class AuthenticateFilter implements Filter { ... }-
Créer une classe enfant de
Filter -
Dans
doFilter():-
Appeler
chain.doFilter()pour passer à la prochaine étape -
Sinon, le flux s’arrête là
-
@Override
public void doFilter(ServletRequest req,
ServletResponse res,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpSession session = httpReq.getSession();
if (authenticated(session)) {
chain.doFilter(req, res);
} else {
HttpServletResponse httpRes = (HttpServletResponse) res;
httpRes.sendError(401, "Not authentified");
}
}-
Authentification
-
Autorisations
-
Intégrité des données
-
Confidentialité des données
-
Non-répudiation
-
Audit
-
Le modèle de sécurité en Java EE 7 est plutôt réduit
-
Authentification et autorisations d’accès à une URL
-
-
La majeure partie de la configuration est propriétaire côté serveur d’applications
-
Si une URL est protégée
-
Et le client n’est pas authentifié
-
Alors, déclenchement de la procédure d’authentification
<security-constraint> dans le descripteur de déploiement
| Type | Balise |
|---|---|
Ressource web |
|
Contrainte d’autorisation |
|
<security-constraint>
<web-resource-collection>
<web-resource-name>Partie sécurisée</web-resource-name>
<url-pattern>/secure/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>| Mode | Configuration |
|---|---|
Popup native |
|
Formulaire |
|
Certificat SSL |
|
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>| Composant | Contrainte |
|---|---|
Formulaire |
|
Champ de login |
|
Champ de mot de passe |
|
<form method=post action="j_security_check">
<input type="text" name= "j_username" />
<input type="password" name= "j_password" />
<input type="submit" value="Login" />
</form>-
Java EE implémente la Programmation Orientée Evènements
-
Divers évènements liés au cycle de vie :
-
Démarrage/arrêt de l’application
-
Gestion des attributs dans les différents contextes
-
etc.
-
-
Possibilité de s’abonner à ces évènements
| Classe associée | Evènement |
|---|---|
|
Démarrage de l’application |
Arrêt de l’application |
| Classe associée | Evènement |
|---|---|
|
Ajout d’attribut |
Suppression d’attribut |
|
Remplacement d’attribut |
| Classe associée | Evènement |
|---|---|
|
Initialisation de la requête |
Destruction de la requête |
| Classe associée | Evènement |
|---|---|
|
Ajout d’attribut |
Suppression d’attribut |
|
Remplacement d’attribut |
| Classe associée | Evènement |
|---|---|
|
Création de la session |
Destruction de la session |
| Classe associée | Evènement |
|---|---|
|
Ajout d’attribut |
Suppression d’attribut |
|
Remplacement d’attribut |
| Classe associée | Evènement |
|---|---|
|
Objet stocké en session |
Objet supprimé de la session |
| Classe associée | Evènement |
|---|---|
|
Activation de la session |
Déactivation de la session |
<web...>
<listener>
<listener-class>
ch.frankel.ASessionListener
</listener-class>
</listener>
</web>-
Gérer les exceptions qui ne sont pas traitées par le servlet
-
De manière transversale
-
A chaque type d’exception
-
Ou à chaque type d’erreur HTTP
-
Correspond une page d’erreur
-
-
Ou une page d’erreur catch all
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/WEB-INF/npe.jsp</location>
</error-page>-
i18n fait partie de Java SE
-
Mais utilisé dans Java EE
-
Via la librairie JSTL
fmt
-
| Tag | Description |
|---|---|
|
Set la locale depuis une variable |
|
Charge le bundle et le stocke dans une variable |
|
Affiche le message internationalisé |
<%@ taglib prefix="fmt"
uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:setLocale value="${request.locale}" />
<fmt:setBundle basename="ch.hesge.messages" var="msg" />
<html>
<body>
<ul>
<li><fmt:message key="key.one" bundle="${msg}" /></li>
<li><fmt:message key="key.two" bundle="${msg}" /></li>
</ul>
</body>
</html>



