27 votes

Comment éviter d'utiliser des scriptlets dans ma page JSP ?

On m'a dit que l'utilisation de scriptlets (<%= ... %>) dans mes pages JSP n'était pas une très bonne idée.

Quelqu'un ayant un peu plus d'expérience en java/jsp pourrait-il me donner des indications sur la manière de modifier ce code pour qu'il soit plus conforme aux "meilleures pratiques", quelles qu'elles soient ?

Cette JSP est en fait la page principale de mon décorateur sitemesh. En fait, mon site Web comporte une bande d'onglets et un sous-menu, et je souhaite mettre en évidence l'onglet actuel et afficher le bon sous-menu en regardant l'URI de la requête actuelle.

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <link href="<%= request.getContextPath() %>/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a 
    <%= request.getRequestURI().contains("/events/") ? "class='selected'" : "" %>
    href='<%= request.getContextPath() %>/events/Listing.action'>Events</a>
  <a 
    <%= request.getRequestURI().contains("/people/") ? "class='selected'" : "" %>
    href='<%= request.getContextPath() %>/people/Listing.action'>People</a>
</div>

<div class="submenu">
  <% if(request.getRequestURI().contains("/events/")) { %>
    <a href="Listing.action">List of Events</a>
    |<a href="New.action">New Event</a>
  <% } %>
  <% if(request.getRequestURI().contains("/people/")) { %>
    <a href="Listing.action">List of People</a>
    |<a href="New.action">New Person</a>
  <% } %>  
  &nbsp;
</div>

<div class="body">
  <decorator:body />
</div>

</body>
</html>

Merci à tous

33voto

BalusC Points 498232

Je pense que cela aide plus si vous voyez de vos propres yeux que cela peut être fait entièrement. sin scriptlets.

Voici une réécriture 1 sur 1 avec l'aide de plusieurs personnes. JSTL (il suffit de déposer jstl-1.2.jar sur /WEB-INF/lib ) noyau dur y fonctions taglib :

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <link href="${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a 
    ${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/events/Listing.action">Events</a>
  <a 
    ${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}">
    <a href="Listing.action">List of Events</a>
    |<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}">
    <a href="Listing.action">List of People</a>
    |<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

Voici une réécriture plus optimisée, notez que j'ai utilisé c:set pour "mettre en cache" les résultats d'expression pour les réutiliser et que j'utilise le HTML <base> pour éviter de mettre le chemin d'accès contextuel dans chaque lien (il suffit de faire en sorte que toutes les URL relatives de votre page Web soient relatives à ce chemin d'accès - sans le slash de tête !)

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" />
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" />

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <base href="${pageContext.request.contextPath}">
  <link href="assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a>
  <a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${isEvents}">
    <a href="Listing.action">List of Events</a>|<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${isPeople}">
    <a href="Listing.action">List of People</a>|<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

Il peut en fait être optimisé davantage si vous rassemblez toutes ces valeurs "codées en dur" comme events y people et de lier les textes dans un Map dans le champ d'application et l'utilisation sous chaque JSTL <c:forEach> pour afficher les onglets.

Quant à votre réel question, vous pouvez désactiver (et obtenir des erreurs d'exécution lors de son utilisation) en ajoutant l'entrée suivante dans le fichier de configuration de l'application web web.xml . Cela peut aider à repérer les scriptlets oubliés.

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <scripting-invalid>true</scripting-invalid>
    </jsp-property-group>
</jsp-config>

Pour en savoir plus sur les EL, consultez le Tutoriel Java EE partie II chapitre 5 . Les objets EL implicites, tels que ${pageContext} sont décrites aquí . Pour en savoir plus sur JSTL, consultez la section Tutoriel Java EE partie II chapitre 7 . Notez que JSTL et EL sont deux choses distinctes. JSTL est un taglib standard et EL permet simplement d'accéder aux données du backend de manière programmatique. Bien qu'il soit normalement utilisé dans des taglibs comme JSTL, il peut également être utilisé de manière autonome dans le texte des modèles.

8voto

Thilo Points 108673

En passant, est-ce que <%= request.getContextPath() %> une utilisation acceptable des scriptlets qui ne soit pas autant désapprouvée ?

C'est peut-être une opinion impopulaire, mais si vous ne faites que de simples conditionnels et des insertions de texte, je ne peux pas trouver beaucoup de défauts dans l'utilisation des scriptlets. (Notez que le si )

J'utiliserais probablement JSTL et le langage d'expression, mais surtout parce qu'il peut être moins typographique, et que le support des IDE peut être meilleur (mais un bon IDE JSP peut aussi trouver les parenthèses fermantes manquantes et des choses comme ça).

Mais fondamentalement (comme dans "garder la logique hors des modèles"), je ne vois pas de différence entre

<% if(request.getRequestURI().contains("/events/")) { %>

y

${fn:contains(pageContext.request.requestURI, '/events/')

6voto

Jack Leow Points 11081

Ce n'est pas une réponse directe à votre question (et il y en a déjà plusieurs bonnes, donc je ne vais pas essayer d'en rajouter), mais vous l'avez mentionné :

Est-ce que quelqu'un ayant un peu plus d'expérience en java/jsp peut me donner quelques des indications sur la façon de modifier ce code ainsi c'est plus une "meilleure pratique", quelle que soit que cela puisse être ?

À mon avis, la meilleure pratique, en ce qui concerne le JSP, est qu'il doit être utilisé strictement comme un outil d'aide à la décision. moteur de modélisation et rien de plus (c'est-à-dire qu'il n'y a pas de logique commerciale). L'utilisation de JSTL, comme beaucoup l'ont souligné, vous aide certainement à y parvenir, mais même avec JSTL, il est facile d'en faire trop dans une JSP.

Personnellement, j'aime bien suivre les règles énoncées dans Appliquer une séparation stricte entre le modèle et la vue dans les moteurs de modélisation par Terence Parr lors du développement en JSP. L'article mentionne l'objectif des moteurs de modélisation (séparation du modèle et de la vue) et les caractéristiques d'un bon moteur de modélisation. Il jette un bon coup d'œil à JSP et souligne les raisons pour lesquelles ce n'est pas un bon moteur de modèle. Sans surprise, JSP est fondamentalement trop puissant et permet aux développeurs d'en faire trop. Je recommande vivement la lecture de cet article, qui vous aidera à vous limiter aux "bons" aspects de JSP.

Si vous ne lisez qu'une seule section de ce document, lisez le chapitre 7, qui comprend les règles suivantes :

  1. la vue ne peut pas modifier le modèle, soit en modifiant directement les objets de données du modèle, soit en invoquant des méthodes sur le modèle. objets de données du modèle ou en invoquant des méthodes sur le modèle qui causent des effets secondaires. C'est-à-dire qu'un modèle peut accéder aux données du modèle et invoquer des méthodes, mais ces références doivent être exemptes d'effets sans effet secondaire. Cette règle découle en partie parce que les références aux données doivent être insensibles à l'ordre. Voir la section 7.1.
  2. la vue ne peut pas effectuer de calculs sur les données dépendantes valeurs parce que les calculs peuvent changer dans le futur et ils doivent être soigneusement encapsulés dans le modèle dans modèle dans tous les cas. Par exemple, la vue ne peut pas calculer les prix de vente des livres comme "$price*.90". Pour être indépendante du modèle, la vue ne peut pas faire hypothèses sur la signification des données.
  3. la vue ne peut pas comparer des valeurs de données dépendantes mais peut tester les propriétés des données telles que la présence/absence ou la longueur d'une valeur de données à valeurs multiples. Des tests tels que $bloodPressure<120 doivent être déplacés vers le le modèle car les médecins aiment continuer à réduire la pression systolique maximale sur nous. Les expressions dans la vue doivent être remplacées par un test de présence d'une valeur valeur simulant un booléen tel que $bloodPressureOk!=null La sortie du modèle peut être conditionnelle sur les données du modèle et données du modèle et des com- putations, le conditionnel conditionnelle doit simplement être calculée dans le modèle. Même tests simples qui rendent les valeurs négatives rouge doivent être calculés dans le modèle ; Le bon niveau d'abstraction est généralement quelque chose de plus haut niveau, tel que le modèle de l'utilisateur. généralement quelque chose de plus haut niveau comme "le département x perd de l'argent".
  4. la vue ne peut pas faire d'hypothèses sur le type de données. Certaines hypothèses de type sont évidentes lorsque la vue suppose qu'une donnée données est une date, par exemple, mais des mais d'autres hypothèses de type plus subtiles apparaissent : Si un modèle suppose que $userID est un nombre entier, le pro- gramme ne peut pas changer cette valeur pour une valeur non numérique non numérique dans le modèle sans casser le modèle. Cette règle interdit l'indexation des tableaux comme colorCode[$topic] et $name[$ID] La vue ne peut pas non plus appeler des méthodes avec des arguments car (statiquement ou dynamiquement), il existe un type d'argument supposé, à moins que l'on puisse garantir que la méthode du modèle les traite simplement comme des objets. De plus, les graphistes ne sont pas des programmeurs ; attendre d'eux qu'ils invoquent des méthodes et qu'ils sachent quoi passer est irréaliste.
  5. les données du modèle ne doivent pas contenir d'informations relatives à l'affichage ou à la mise en page. Le modèle ne peut pas transmettre d'informations d'affichage à la vue déguisée en valeurs de données. valeurs de données. Cela inclut l'interdiction de transmettre le nom d'un modèle à appliquer à d'autres d'autres valeurs de données.

Par ailleurs, Terence a créé son propre moteur de templating appelé Modèle de chaîne qui est censé faire un très bon travail pour faire respecter ces règles. Je n'ai pas d'expérience personnelle avec ce système, mais j'aimerais l'utiliser pour mon prochain projet.

6voto

Spike Williams Points 3976

Les scriptlets ne sont pas la pire chose au monde. Il est important de réfléchir à qui va assurer la maintenance du code. S'il s'agit de concepteurs Web qui n'ont pas beaucoup d'expérience de Java, il est probablement préférable d'utiliser des bibliothèques de balises. En revanche, si ce sont des développeurs Java qui assurent la maintenance, il peut être plus facile pour eux d'opter pour des scriptlets.

Si vous finissez par utiliser une bibliothèque de balises et JSTL, vous attendez du mainteneur qu'il apprenne également la bibliothèque de balises et connaisse JSTL. Certains développeurs s'en accommoderont, car il s'agit d'une compétence qu'ils souhaitent ou qu'ils possèdent déjà, mais pour certains développeurs qui n'ont affaire à des JSP que tous les quelques mois environ, il peut être beaucoup moins pénible de travailler avec des scriptlets clairement écrits dans un langage Java agréable et familier.

3voto

Vincent Ramdhanie Points 46265

Vous pouvez commencer par utiliser des bibliothèques de balises. Vous pouvez utiliser la bibliothèque de balises standard JSTL pour faire la plupart des choses courantes pour lesquelles vous avez besoin de scriplets. Il existe de nombreuses autres bibliothèques de balises plus riches qui sont utilisées, comme dans le cadre de struts2 ou d'apache.

par exemple

  <c:if test="${your condition}">
       Your Content
  </c:if>

remplacerait vos instructions if.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X