Frage Wie vermeidet man Java-Code in JSP-Dateien?


Ich bin neu in Java EE und ich weiß, dass etwas wie die folgenden drei Zeilen

<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>

ist eine altmodische Art zu schreiben und in JSP Version 2 gibt es eine Methode Java Code in JSP Dateien zu vermeiden. Kann mir bitte jemand die alternativen JSP 2-Linien nennen, und wie heißt diese Technik?


1522
2017-07-05 07:24


Ursprung


Antworten:


Die Verwendung von Scriptlets (jene <% %> Dinge in JSP ist in der Tat seit der Geburt von sehr stark entmutigt Taglibs (mögen JSTL) und EL (Ausdruckssprache, jene ${} Dinge) im Jahr 2001.

Die Hauptnachteile von Scriptlets sind:

  1. Wiederverwendbarkeit: Sie können Scriptlets nicht erneut verwenden.
  2. Austauschbarkeit: Sie können Scriptlets nicht abstrakt machen.
  3. OO-Fähigkeit: Sie können keine Vererbung / Komposition verwenden.
  4. Debuggability: Wenn Scriptlet eine Ausnahme auf halbem Wege auslöst, erhalten Sie nur eine leere Seite.
  5. Testbarkeit: Scriptlets sind nicht testbar.
  6. Wartbarkeit: Pro Saldo wird mehr Zeit benötigt, um die Logik von vermengten / überfüllten / duplizierten Code zu erhalten.

Sonne Oracle selbst empfiehlt auch in der JSP-Kodierungskonventionen die Verwendung von vermeiden Scriptlets wann immer die gleiche Funktionalität von (tag) -Klassen möglich ist. Hier sind einige wichtige Beispiele:

Aus der JSP 1.2-Spezifikation wird dringend empfohlen, die JSP-Standard-Tag-Bibliothek (JSTL) in Ihrer Webanwendung zu verwenden Reduzieren Sie die Notwendigkeit von JSP-Scriptlets in deinen Seiten. Seiten, die JSTL verwenden, sind im Allgemeinen einfacher zu lesen und zu pflegen.

...

Wo möglich, Vermeiden Sie JSP-Scriptlets Wann immer Tag-Bibliotheken äquivalente Funktionalität bereitstellen. Dies erleichtert das Lesen und Verwalten von Seiten, hilft bei der Trennung von Geschäftslogik und Präsentationslogik und erleichtert die Weiterentwicklung Ihrer Seiten zu Seiten im JSP 2.0-Stil (die JSP 2.0-Spezifikation unterstützt jedoch die Verwendung von Scriptlets).

...

Im Geiste der Übernahme des MVC-Entwurfsmusters (Model-View-Controller), um die Kopplung zwischen der Präsentationsschicht und der Geschäftslogik zu reduzieren, JSP-Skriptlets sollten nicht verwendet werden zum Schreiben von Geschäftslogik. Stattdessen werden JSP-Scriptlets verwendet, um Daten (auch "Wertobjekte" genannt), die bei der Verarbeitung der Clientanforderungen zurückgegeben werden, in ein geeignetes clientfähiges Format zu transformieren. Selbst dann wäre dies besser mit einem Front-Controller-Servlet oder einem benutzerdefinierten Tag möglich.


Wie man ersetzt Scriptlets hängt ganz von dem alleinigen Zweck des Codes / der Logik ab. Mehr als oft wird dieser Code in eine vollwertige Java-Klasse eingefügt:

  • Wenn Sie das aufrufen möchten gleich Java-Code an jeden Anfrage, weniger oder mehr unabhängig von der angeforderten Seite, z. Überprüfen Sie, ob ein Benutzer angemeldet ist, und implementieren Sie dann a Filter und schreiben Sie entsprechend Code in doFilter() Methode. Z.B.:

    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.
        }
    }
    

    Wenn auf einem geeigneten zugeordnet <url-pattern>Wenn Sie die JSP-Seiten von Interesse abdecken, müssen Sie nicht denselben Code über alle JSP-Seiten kopieren.


  • Wenn Sie einen Java-Code aufrufen möchten Vorverarbeitung eine Anfrage, z.B. Vorabladen einer Liste aus einer Datenbank zur Anzeige in einer Tabelle, ggf. basierend auf einigen Abfrageparametern, dann Implementieren von a Servlet und schreiben Sie entsprechend Code in doGet() Methode. Z.B.:

    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);
        }
    }
    

    Auf diese Weise ist der Umgang mit Ausnahmen einfacher. Auf die Datenbank wird nicht mitten im JSP-Rendering zugegriffen, sondern weit bevor die JSP angezeigt wird. Sie haben immer noch die Möglichkeit, die Antwort zu ändern, wenn der DB-Zugriff eine Ausnahme auslöst. Im obigen Beispiel wird die Standardfehler-500-Seite angezeigt, die Sie ohnehin per anpassen können <error-page> im web.xml.


  • Wenn Sie einen Java-Code aufrufen möchten Nachbearbeitung eine Anfrage, z.B. ein Formular submit verarbeiten, dann a implementieren Servlet und schreiben Sie entsprechend Code in doPost() Methode. Z.B.:

    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.
        }
    }
    

    Auf diese Weise ist es einfacher, mit verschiedenen Zielseitenzielen zu arbeiten: Im Fehlerfall wird das Formular mit Validierungsfehlern erneut angezeigt (in diesem Beispiel können Sie es mit ${message} im EL) oder im Erfolgsfall nur auf die gewünschte Zielseite.


  • Wenn Sie einen Java-Code aufrufen möchten Steuerung der Ausführungsplan und / oder das Ziel der Anfrage und die Antwort, dann a Servlet nach der MVCs Front Controller Pattern. Z.B.:

    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);
        }
    }
    

    Oder nehmen Sie einfach ein MVC-Framework wie JSF, Frühling MVC, Wicketusw., sodass Sie nur mit einer JSP / Facelets-Seite und einer JavaBean-Klasse enden, ohne dass ein benutzerdefiniertes Servlet erforderlich ist.


  • Wenn Sie einen Java-Code aufrufen möchten kontrolliere den Fluss innerhalb einer JSP-Seite, dann müssen Sie eine (vorhandene) Flow-Control-Taglib wie greifen JSTL-Kern. Z.B. anzeigen List<Product> in einer Tabelle:

    <%@ 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>
    

    Mit XML-style-Tags, die gut zu allem HTML passen, ist der Code besser lesbar (und damit besser wartbar) als eine Reihe von Scriptlets mit verschiedenen öffnenden und schließenden Klammern ("Wo zum Teufel gehört diese schließende Klammer?"). Eine einfache Hilfe besteht darin, Ihre Webanwendung so zu konfigurieren, dass immer eine Ausnahme ausgelöst wird Scriptlets werden noch verwendet, indem das folgende Stück hinzugefügt wird web.xml:

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

    Im Facelets, der Nachfolger von JSP, der Teil des Java-EE-MVC-Frameworks ist JSF, es ist schon nicht möglich zu verwenden Scriptlets. Auf diese Weise werden Sie automatisch gezwungen, "den richtigen Weg" zu gehen.


  • Wenn Sie einen Java-Code aufrufen möchten Zugriff und Anzeige "Backend" Daten innerhalb einer JSP-Seite, dann müssen Sie EL (Expression Language), diese verwenden ${} Dinge. Z.B. Gesendete Eingabewerte erneut anzeigen:

    <input type="text" name="foo" value="${param.foo}" />
    

    Das ${param.foo} Zeigt das Ergebnis von request.getParameter("foo").


  • Wenn Sie einige aufrufen möchten Nützlichkeit Java-Code direkt in der JSP-Seite (normalerweise public static Methoden), dann müssen Sie sie als EL-Funktionen definieren. Es gibt einen Standard funktioniert taglib in JSTL, aber Sie können Funktionen auch einfach selbst erstellen. Hier ist ein Beispiel wie JSTL fn:escapeXml ist nützlich, um zu verhindern XSS  Anschläge.

    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    ...
    <input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
    

    Beachten Sie, dass die XSS-Empfindlichkeit in keiner Weise speziell mit Java / JSP / JSTL / EL / was auch immer verwandt ist, dieses Problem muss in berücksichtigt werden jedenWebapplikation, die Sie entwickeln. Das Problem von Scriptlets ist, dass es keine eingebauten Vorbeugemaßnahmen bietet, zumindest nicht mit der Standard-Java-API. JSPs Nachfolger-Facelets hat bereits implizites HTML-Escaping, sodass Sie sich keine Sorgen über XSS-Lücken in Facelets machen müssen.

Siehe auch:


1852
2017-07-05 14:19



Als Schutz: Scriptlets für immer deaktivieren

Wie eine andere Frage Diskutieren Sie, Sie können und sollten Scriptlets immer deaktivieren web.xml Web-Anwendungs-Deskriptor.

Ich würde das immer tun, um jeden Entwickler daran zu hindern, Skripte hinzuzufügen, besonders in größeren Unternehmen, in denen Sie früher oder später den Überblick verlieren. Das web.xml Einstellungen sehen so aus:

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

207
2017-08-14 21:59



JSTL bietet Tags für Bedingungen, Schleifen, Sets, Gets usw. an. Zum Beispiel:

<c:if test="${someAttribute == 'something'}">
   ...
</c:if>

JSTL arbeitet mit Anforderungsattributen - sie werden meistens in der Anfrage von einem Servlet gesetzt, das vorwärts an die JSP.


102
2017-07-05 07:28



Ich bin mir nicht sicher, ob ich das richtig verstehe.

Sie sollten etwas über MVC lesen. Frühling MVC & Streben 2 sind die zwei häufigsten Lösungen.


56
2017-07-05 07:29



Sie können JSTL-Tags zusammen mit EL-Ausdrücken verwenden, um eine Vermischung von Java- und HTML-Code zu vermeiden:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
    <head>
    </head>
    <body>

        <c:out value="${x + 1}" />
        <c:out value="${param.name}" />
    // and so on

    </body>
</html>

48
2017-07-05 08:45



Es gibt auch komponentenbasierte Frameworks wie Wicket das erzeugt viel HTML für dich. Die Tags, die im HTML enden, sind extrem einfach und es gibt praktisch keine Logik, die eingemischt wird. Das Ergebnis sind fast leere HTML-Seiten mit typischen HTML-Elementen. Der Nachteil ist, dass es eine Menge Komponenten in der Wicket API zu lernen und einige Dinge können unter diesen Einschränkungen schwierig zu erreichen sein.


32
2018-03-22 18:24



Im MVC Architectural-Muster repräsentieren JSPs die View-Ebene. Das Einbetten von Java-Code in JSPs wird als eine schlechte Vorgehensweise angesehen. Sie können verwenden JSTL, Freimarker, Geschwindigkeit mit JSP als "Vorlagen-Engine". Der Datenanbieter für diese Tags hängt von Frameworks ab mit denen du es zu tun hast. Struts 2 und webwork als eine Implementierung für MVC Pattern verwendet OGNL "Eine sehr interessante Technik, um die Eigenschaften von Beans JSP zugänglich zu machen".


28
2018-02-04 10:41



Die Erfahrung hat gezeigt, dass JSPs einige Mängel aufweisen, von denen einer schwer zu vermeiden ist, Markup mit tatsächlichem Code zu mischen.

Wenn Sie können, dann überlegen Sie sich, eine spezielle Technologie für das zu verwenden, was Sie tun müssen. In Java EE 6 gibt es JSF 2.0, das viele nette Funktionen bietet, wie das Kleben von Java - Beans mit JSF - Seiten über die #{bean.method(argument)} Ansatz.


25
2017-07-05 08:30