Vraag Hoe Java-code in JSP-bestanden te vermijden?


Ik ben nieuw bij Java EE en ik weet dat zoiets als de volgende drie regels

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

is een oude manier van coderen en in JSP-versie 2 bestaat een methode om Java-code in JSP-bestanden te voorkomen. Kan iemand me de alternatieve JSP 2-regels vertellen, en hoe wordt deze techniek genoemd?


1522
2017-07-05 07:24


oorsprong


antwoorden:


Het gebruik van scriptlets (die <% %> dingen) in JSP is inderdaad zeer ontmoedigd sinds de geboorte van taglibs (graag willen JSTL) en EL (Expression Language, die ${} dingen) in 2001.

De belangrijkste nadelen van scriptlets zijn:

  1. herbruikbaarheid: u kunt scriptlets niet opnieuw gebruiken.
  2. vervangbaarheid: je kunt scriptlets niet abstract maken.
  3. OO-vermogen: je kunt geen gebruik maken van overerving / compositie.
  4. Debuggability: als het scriptlet een uitzondering half werpt, is het enige dat je krijgt een lege pagina.
  5. testbaarheid: scriptlets zijn niet unit-testbaar.
  6. Onderhoudbaarheid: per saldo is meer tijd nodig om vermengde / rommelige / gedupliceerde codelogica te behouden.

Zon Oracle beveelt zelf ook aan in de JSP-coderingsconventies om gebruik van te vermijden scriptlets wanneer dezelfde functionaliteit mogelijk is door (tag) klassen. Hier zijn verschillende citaten van relevantie:

Uit de JSP 1.2-specificatie wordt ten zeerste aanbevolen dat de JSP Standard Tag Library (JSTL) wordt gebruikt in uw webtoepassing om te helpen de noodzaak van JSP-scriptlets verminderen op uw pagina's. Pagina's die JSTL gebruiken, zijn over het algemeen gemakkelijker te lezen en te onderhouden.

...

Waar mogelijk, JSP-scriptlets vermijden telkens als tagbibliotheken equivalente functionaliteit bieden. Dit maakt pagina's gemakkelijker te lezen en te onderhouden, helpt bedrijfslogica te scheiden van presentatielogica en zorgt ervoor dat uw pagina's gemakkelijker kunnen evolueren naar JSP 2.0-stijlpagina's (JSP 2.0-specificatie ondersteunt maar de nadruk legt op het gebruik van scriptlets).

...

In de geest van het aannemen van het ontwerppatroon van de model-view-controller (MVC) om de koppeling tussen de presentatiestap en de bedrijfslogica te verminderen, JSP-scriptlets mogen niet worden gebruikt voor het schrijven van bedrijfslogica. In plaats daarvan worden JSP-scriptlets gebruikt, indien nodig, om gegevens (ook wel "waardeobjecten" genoemd) te transformeren die worden geretourneerd van het verwerken van de verzoeken van de client naar een juiste indeling die geschikt is voor de client. Zelfs dan zou dit beter kunnen worden gedaan met een servlet aan de voorzijde of een aangepaste tag.


Hoe te vervangen scriptlets volledig afhankelijk van het enige doel van de code / logica. Meer dan vaak wordt deze code in een volledigwaardige Java-klasse geplaatst:

  • Als u de dezelfde Java-code ingeschakeld elk verzoek, minder of meer, ongeacht de gevraagde pagina, b.v. controleren of een gebruiker is aangemeld en vervolgens een implementeren filter en schrijf de code dienovereenkomstig in doFilter() methode. bijv .:

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

    Wanneer in kaart gebracht op een geschikte <url-pattern>voor de betreffende JSP-pagina's van belang, dan hoeft u niet hetzelfde stuk code over alle JSP-pagina's te kopiëren.


  • Als u wat Java-code wilt gebruiken voor preprocess een verzoek, b.v. Vooraf laden van een lijst uit een database om in een bepaalde tabel weer te geven, indien nodig op basis van enkele queryparameters, voer dan a uit servlet en schrijf de code dienovereenkomstig in doGet() methode. bijv .:

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

    Op deze manier is het eenvoudiger om uitzonderingen aan te pakken. De DB is niet toegankelijk in het midden van de JSP-rendering, maar ver voordat de JSP wordt weergegeven. U hebt nog steeds de mogelijkheid om het antwoord te wijzigen wanneer de DB-toegang een uitzondering genereert. In het bovenstaande voorbeeld wordt de standaardfout 500-pagina weergegeven die u in elk geval kunt aanpassen met een <error-page> in web.xml.


  • Als u wat Java-code wilt gebruiken voor postprocess een verzoek, b.v. verwerken van een formulier indienen en vervolgens implementeren servlet en schrijf de code dienovereenkomstig in doPost() methode. bijv .:

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

    Op deze manier is het eenvoudiger om verschillende bestemmingspagina-bestemmingen aan te pakken: het formulier opnieuw weergeven met validatiefouten in het geval van een fout (in dit specifieke voorbeeld kunt u het opnieuw weergeven met behulp van ${message} in EL), of door gewoon naar de gewenste doelpagina te gaan in geval van succes.


  • Als u wat Java-code wilt gebruiken voor controle het uitvoeringsplan en / of de bestemming van het verzoek en de reactie, voer dan een uit servlet volgens de MVC's Front Controller Pattern. bijv .:

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

    Of neem gewoon een MVC-raamwerk zoals JSF, Lente MVC, hekje, enz. zodat u uiteindelijk alleen een JSP / Facelets-pagina en een Javabean-klasse krijgt zonder dat u een aangepaste servlet nodig hebt.


  • Als u wat Java-code wilt gebruiken voor controleer de stroom in een JSP-pagina, dan moet je een (bestaande) flow control-taglib halen JSTL-kern. Bijv. weergeven List<Product> in een tabel:

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

    Met tags in XML-stijl die goed passen tussen al die HTML-code, is de code beter leesbaar (en dus beter te onderhouden) dan een stel scriptlets met verschillende openings- en sluitingssteunen ("Waar komt deze sluitbeugel eigenlijk toe?"). Een eenvoudig hulpmiddel is om uw webtoepassing zo te configureren dat deze altijd een uitzondering genereert scriptlets worden nog steeds gebruikt door het volgende stuk toe te voegen aan web.xml:

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

    In Facelets, de opvolger van JSP, dat deel uitmaakt van het door Java EE geleverde MVC-framework JSF, het is al niet mogelijk te gebruiken scriptlets. Op deze manier wordt je automatisch gedwongen om dingen "op de juiste manier" te doen.


  • Als u wat Java-code wilt gebruiken voor toegang en weergave "backend" -gegevens binnen een JSP-pagina, dan moet u EL (Expression Language) gebruiken, die ${} dingen. Bijv. inkomende invoerwaarden opnieuw weergeven:

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

    De ${param.foo} geeft de uitkomst weer van request.getParameter("foo").


  • Als je iets wilt aanroepen nut Java-code rechtstreeks in de JSP-pagina (meestal public static methoden), dan moet u ze definiëren als EL-functies. Er is een standaard functies taglib in JSTL, maar je kunt ook gemakkelijk zelf functies maken. Hier is een voorbeeld hoe JSTL fn:escapeXml is handig om te voorkomen XSS  aanvallen.

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

    Merk op dat de XSS-gevoeligheid op geen enkele manier specifiek gerelateerd is aan Java / JSP / JSTL / EL / wat dan ook, met dit probleem moet rekening worden gehouden in elkwebapplicatie die u ontwikkelt. Het probleem van scriptlets is dat het geen manier biedt om ingebouwde voorzorgsmaatregelen te nemen, althans niet met de standaard Java API. JSP's opvolger Facelets heeft al impliciete HTML-escaping, dus je hoeft je geen zorgen te maken over XSS-gaten in Facelets.

Zie ook:


1852
2017-07-05 14:19



Als Safeguard: Schakel Scriptlets For Good uit

Als een andere vraag discussieert, je kunt en moet altijd scriptlets uitschakelen in je web.xml webapplicatie descriptor.

Ik zou dat altijd doen om te voorkomen dat ontwikkelaars scriptlets zouden toevoegen, vooral in grotere bedrijven waar je vroeg of laat het overzicht verliest. De web.xml instellingen zien er als volgt uit:

<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 biedt tags voor conditionals, loops, sets, gets, etc. Bijvoorbeeld:

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

JSTL werkt met aanvraagattributen - deze worden meestal ingesteld in het verzoek van een Servlet, welke forwards naar de JSP.


102
2017-07-05 07:28



Ik weet niet zeker of ik dit juist begrijp.

Je moet iets over MVC lezen. Lente MVC & Stutten 2 zijn de twee meest voorkomende oplossingen.


56
2017-07-05 07:29



U kunt JSTL-tags gebruiken in combinatie met EL-uitdrukkingen om te voorkomen dat Java- en HTML-code worden vermengd:

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



Er zijn ook op componenten gebaseerde frameworks zoals hekje die veel van de HTML voor u genereren. De tags die in de HTML terechtkomen, zijn uiterst basaal en er is vrijwel geen logica die wordt ingemengd. Het resultaat is bijna lege HTML-pagina's met typische HTML-elementen. Het nadeel is dat er veel componenten in zitten hekje API om te leren en sommige dingen kunnen moeilijk te bereiken zijn onder die beperkingen.


32
2018-03-22 18:24



In het MVC-architectuurpatroon vertegenwoordigen JSP's de laag Weergeven. Het insluiten van Java-code in JSP's wordt als een slechte praktijk beschouwd. Je kunt gebruiken JSTL, Freemarker, snelheid met JSP als "sjabloonengine". De gegevensprovider voor die tags is afhankelijk van kaders waar je mee te maken hebt. Struts 2 en webwork als een implementatie voor gebruik door MVC Pattern OGNL "zeer interessante techniek om Beans Properties bloot te stellen aan JSP".


28
2018-02-04 10:41



De ervaring heeft geleerd dat JSP's een aantal tekortkomingen hebben, waarvan er één moeilijk is om te voorkomen dat men de opmaak vermengt met de werkelijke code.

Als je kunt, overweeg dan een gespecialiseerde technologie te gebruiken voor wat je moet doen. In Java EE 6 is er JSF 2.0, dat veel leuke functies biedt, zoals het lijmen van Java-bonen samen met JSF-pagina's via de #{bean.method(argument)} nadering.


25
2017-07-05 08:30