A partir de la spécification JSP 1.2, il est fortement recommandé d'utiliser la bibliothèque de balises standard JSP (JSTL) dans votre application Web pour réduire le besoin de scriptlets JSP dans vos pages. Les pages qui utilisent JSTL sont, en général, plus faciles à lire et à gérer.
...
Dans la mesure du possible, évitez les scriptlets JSP chaque fois que les bibliothèques de balises fournissent des fonctionnalités équivalentes. Cela rend les pages plus faciles à lire et à maintenir, aide à séparer la logique métier de la logique de présentation et rendra vos pages plus faciles à évoluer vers des pages de style JSP 2.0 (la spécification JSP 2.0 prend en charge mais met l'accent sur l'utilisation de scriptlets).
...
Dans l'esprit d'adopter le modèle de conception modèle-vue-contrôleur (MVC) pour réduire le couplage entre le niveau de présentation et la logique métier, les scriptlets JSP ne doivent pas être utilisés pour écrire la logique métier. Au lieu de cela, les scriptlets JSP sont utilisés si nécessaire pour transformer les données (également appelées "objets de valeur") renvoyées par le traitement des demandes du client dans un format approprié prêt pour le client. Même alors, cela serait mieux fait avec un servlet de contrôleur frontal ou une balise personnalisée.
Si vous souhaitez invoquer le même code Java à chaque demande, peu ou pas quelle que soit la page demandée, par exemple en vérifiant si un utilisateur est connecté, puis implémentez un filtre et écrivez le code en conséquence dans la doFilter()
méthode. Par exemple:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
} else {
chain.doFilter(request, response); // Logged in, just continue request.
}
}
Lorsqu'il est mappé sur une page appropriée <url-pattern>
couvrant les pages JSP d'intérêt, vous n'avez pas besoin de copier-coller le même morceau de code dans l'ensemble des pages JSP.
Si vous souhaitez appeler du code Java pour prétraiter une demande, par exemple en préchargeant une liste d'une base de données à afficher dans une table, si nécessaire en fonction de certains paramètres de requête, implémentez un servlet et écrivez le code en conséquence dans la doGet()
méthode. Par exemple:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
List<Product> products = productService.list(); // Obtain all products.
request.setAttribute("products", products); // Store products in request scope.
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
} catch (SQLException e) {
throw new ServletException("Retrieving products failed!", e);
}
}
Cette façon de traiter les exceptions est plus facile. La base de données n'est pas accessible au cours du rendu JSP, mais bien avant que la JSP ne soit affichée. Vous avez toujours la possibilité de modifier la réponse chaque fois que l'accès à la base de données lève une exception. Dans l'exemple ci-dessus, la page d'erreur 500 par défaut sera affichée que vous pouvez de toute façon personnaliser par un <error-page>
in web.xml
.
Si vous souhaitez invoquer du code Java pour post -traiter une demande, par exemple le traitement d'une soumission de formulaire, alors implémentez un servlet et écrivez le code en conséquence dans la doPost()
méthode. Par exemple:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
response.sendRedirect("home"); // Redirect to home page.
} else {
request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
}
}
De cette façon , traiter différentes destinations de la page de résultats est plus facile: réafficher la forme avec des erreurs de validation dans le cas d'une erreur (dans cet exemple particulier , vous pouvez réafficher à l'aide ${message}
en EL ), ou tout simplement prendre à la page cible souhaitée en cas de succès.
Si vous souhaitez invoquer du code Java pour contrôler le plan d'exécution et / ou la destination de la demande et de la réponse, implémentez un servlet conformément au modèle de contrôleur frontal du MVC . Par exemple:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Action action = ActionFactory.getAction(request);
String view = action.execute(request, response);
if (view.equals(request.getPathInfo().substring(1)) {
request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
} else {
response.sendRedirect(view);
}
} catch (Exception e) {
throw new ServletException("Executing action failed.", e);
}
}
Ou adoptez simplement un framework MVC comme JSF , Spring MVC , Wicket , etc. afin de vous retrouver avec juste une page JSP / Facelets et une classe JavaBean sans avoir besoin d'un servlet personnalisé.
Si vous souhaitez invoquer du code Java pour contrôler le flux dans une page JSP, vous devez saisir une balise de contrôle de flux (existante) comme le noyau JSTL . Par exemple, afficher List<Product>
dans un tableau:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<table>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td>${product.description}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
Avec des balises de style XML qui s'intègrent bien dans tout ce HTML, le code est mieux lisible (et donc mieux maintenable) qu'un tas de scriptlets avec diverses accolades d'ouverture et de fermeture ( "Où diable cette accolade de fermeture appartient-elle?" ). Une aide simple consiste à configurer votre application Web pour lever une exception chaque fois que des scriptlets sont toujours utilisés en ajoutant l'élément suivant à web.xml
:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
Dans Facelets , le successeur de JSP, qui fait partie du framework MVC JSF fourni par Java EE , il n'est déjà pas possible d'utiliser des scriptlets . De cette façon, vous êtes automatiquement obligé de faire les choses "dans le bon sens".
Si vous voulez invoquer du code Java pour accéder et afficher des données "backend" dans une page JSP, vous devez utiliser EL (Expression Language), ces ${}
choses-là. Par exemple, réaffichage des valeurs d'entrée soumises:
<input type="text" name="foo" value="${param.foo}" />
Le ${param.foo}
affiche le résultat de request.getParameter("foo")
.
Si vous souhaitez appeler du code Java utilitaire directement dans la page JSP (généralement des public static
méthodes), vous devez les définir en tant que fonctions EL. Il y a un taglib de fonctions standard dans JSTL, mais vous pouvez également créer facilement des fonctions vous-même . Voici un exemple de l' fn:escapeXml
utilité de JSTL pour empêcher les attaques XSS .
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
Notez que la sensibilité XSS n'est en aucun cas spécifiquement liée à Java / JSP / JSTL / EL / quoi que ce soit, ce problème doit être pris en compte dans chaque application Web que vous développez. Le problème des scriptlets est qu'ils ne fournissent aucun moyen de prévention intégrée, du moins n'utilisant pas l'API Java standard. Le successeur de JSP, Facelets, a déjà un échappement HTML implicite, vous n'avez donc pas à vous soucier des trous XSS dans Facelets.