Jak uniknąć kodu Java w plikach JSP?


1673

Jestem nowy w Javie EE i wiem, że coś podobnego do następujących trzech wierszy

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

jest oldskulowym sposobem kodowania, aw JSP w wersji 2 istnieje metoda unikania kodu Java w plikach JSP. Czy ktoś może mi powiedzieć alternatywne linie JSP 2 i jak nazywa się ta technika?


22
@Koray Tugay, o ile zmienna licznika jest zadeklarowana gdzieś przed jej użyciem, to z pewnością jest ważna ...
Sheldon R.

@SheldonR. Jest to poprawne: <% = counter ++%> lub to: <%! licznik int = 0; int x = counter ++; %> ale nie: <%! licznik int = 0; counter ++; %>
Koray Tugay

@KorayTugay, miałem na myśli to, że jeśli licznik zmiennych został zadeklarowany we wcześniejszym bloku skryptu, powinien być poprawny w późniejszym bloku. Ale ostatecznie programiści J2EE w dzisiejszych czasach powinni używać zmiennych EL zamiast skryptletów ...
Sheldon R.

Odpowiedzi:


1971

Używanie skryptletów (tych <% %>rzeczy) w JSP jest bardzo odradzane od czasu narodzin taglibów (takich jak JSTL ) i EL ( język wyrażeń , takie ${}rzeczy) w 2001 roku.

Główne wady skryptletów to:

  1. Wielokrotnego użytku: nie można ponownie używać skryptletów.
  2. Zastępowalność: nie można uczynić skryptletów abstrakcyjnymi.
  3. Zdolność OO: nie możesz korzystać z dziedziczenia / kompozycji.
  4. Debugowalność: jeśli skryptlet zgłasza wyjątek w połowie, otrzymujesz tylko pustą stronę.
  5. Testowalność: skryptlety nie są testowane jednostkowo.
  6. Konserwowalność: na saldo potrzeba więcej czasu na utrzymanie logiki mieszanego / zaśmieconego / powielonego kodu.

Sam Sun Oracle zaleca również w konwencjach kodowania JSP, aby unikać używania skryptletów, ilekroć taka sama funkcjonalność jest możliwa dzięki klasom (tag). Oto kilka istotnych przykładów:

Zgodnie ze specyfikacją JSP 1.2 zdecydowanie zaleca się stosowanie standardowej biblioteki znaczników JSP (JSTL) w aplikacji internetowej, aby zmniejszyć potrzebę korzystania ze skryptletów JSP na stronach. Strony korzystające z JSTL są ogólnie łatwiejsze do odczytania i obsługi.

...

W miarę możliwości unikaj skryptletów JSP gdy biblioteki znaczników zapewniają równoważną funkcjonalność. Ułatwia to czytanie i zarządzanie stronami, pomaga oddzielić logikę biznesową od logiki prezentacji i ułatwi przekształcenie stron w strony w stylu JSP 2.0 (Specyfikacja JSP 2.0 obsługuje, ale nie podkreśla użycia skryptletów).

...

W duchu przyjęcia wzorca projektowego kontrolera widoku modelu (MVC) w celu zmniejszenia sprzężenia między warstwą prezentacji z logiki biznesowej, skryptów JSP nie należy używać do pisania logiki biznesowej. Zamiast tego w razie potrzeby używane są skrypty JSP do przekształcania danych (zwanych także „obiektami wartości”) zwracanych z przetwarzania żądań klienta do odpowiedniego formatu gotowego do użycia przez klienta. Nawet wtedy lepiej byłoby to zrobić za pomocą serwletu kontrolera frontowego lub niestandardowego znacznika.


Sposób zastępowania skryptletów całkowicie zależy od wyłącznego celu kodu / logiki. Częściej ten kod należy umieścić w pełnej klasie Java:

  • Jeśli chcesz wywoływać ten sam kod Java przy każdym żądaniu, mniej więcej lub więcej, niezależnie od żądanej strony, np. Sprawdzając, czy użytkownik jest zalogowany, a następnie zaimplementuj filtr i odpowiednio napisz kod w doFilter()metodzie. Na przykład:

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

    Po zmapowaniu na odpowiednią <url-pattern>stronę interesujących stron JSP nie trzeba kopiować tego samego fragmentu kodu ogólnych stron JSP.


  • Jeśli chcesz wywołać część kodu Java w celu wstępnego przetworzenia żądania, np. Wstępne ładowanie listy z bazy danych w celu wyświetlenia w jakiejś tabeli, w razie potrzeby w oparciu o niektóre parametry zapytania, następnie zaimplementuj serwlet i napisz kod odpowiednio w doGet()metodzie. Na przykład:

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

    W ten sposób radzenie sobie z wyjątkami jest łatwiejsze. Dostęp do DB nie jest uzyskiwany w trakcie renderowania JSP, ale na długo przed wyświetleniem JSP. Nadal masz możliwość zmiany odpowiedzi za każdym razem, gdy dostęp do bazy danych zgłosi wyjątek. W powyższym przykładzie, domyślna strona błędu 500 zostaną wyświetlone które można dostosować w każdym razie przez <error-page>w web.xml.


  • Jeśli chcesz wywołać pewne kodu Java do przetworzenia żądania, np przetwarzanie formą przedstawienia, a następnie wdrożyć serwletu i napisać kod odpowiednio w doPost()metodzie. Na przykład:

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

    Ten sposób postępowania z różnych miejsc stronie Rezultatem jest łatwiejsze: ponowne wyświetlanie formularza z błędów walidacji w przypadku błędu (w tym konkretnym przypadku można ponownie wyświetlić go za pomocą ${message}w EL ), czy po prostu do żądanej strony docelowej w przypadku powodzenia.


  • Jeśli chcesz wywołać kod Java, aby kontrolować plan wykonania i / lub miejsce docelowe żądania i odpowiedzi, zaimplementuj serwlet zgodnie ze schematem kontrolera frontowego MVC . Na przykład:

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

    Lub po prostu zastosuj środowisko MVC, takie jak JSF , Spring MVC , Wicket itp., Aby uzyskać tylko stronę JSP / Facelets i klasę JavaBean bez potrzeby stosowania niestandardowego serwletu.


  • Jeśli chcesz wywołać kod Java, aby kontrolować przepływ wewnątrz strony JSP, musisz pobrać (istniejący) taglib kontroli przepływu, taki jak rdzeń JSTL . Np. Wyświetlanie List<Product>w tabeli:

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

    Dzięki znacznikom w stylu XML, które ładnie pasują do całego HTML, kod jest lepiej czytelny (a przez to łatwiejszy w utrzymaniu) niż kilka skryptletów z różnymi nawiasami otwierającymi i zamykającymi ( „Do kogo, do cholery, należy ten nawias zamykający?” ). Łatwą pomocą jest skonfigurowanie aplikacji internetowej do generowania wyjątku za każdym razem, gdy używane są skrypty, poprzez dodanie następującego elementu do web.xml:

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

    W Facelets , następca JSP, który jest częścią Java EE warunkiem MVC JSF , to już nie można używać skryptletów . W ten sposób jesteś automatycznie zmuszany do robienia rzeczy „we właściwy sposób”.


  • Jeśli chcesz wywołać jakiś kod Java, aby uzyskać dostęp do danych „zaplecza” na stronie JSP i wyświetlić je, musisz użyć EL (język wyrażeń) ${}. Np. Ponowne wyświetlenie przesłanych wartości wejściowych:

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

    W ${param.foo}wyświetla wynik request.getParameter("foo").


  • Jeśli chcesz wywołać jakiś kod Java narzędzia bezpośrednio na stronie JSP (zwykle public staticmetody), musisz zdefiniować je jako funkcje EL. W JSTL znajduje się standardowa funkcja taglib , ale możesz także łatwo tworzyć funkcje samodzielnie . Oto przykład, w jaki sposób JSTL fn:escapeXmljest przydatny w zapobieganiu atakom XSS .

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

    Należy pamiętać, że wrażliwość XSS nie jest w żaden sposób ściśle związana z Java / JSP / JSTL / EL / czymkolwiek, ten problem należy wziąć pod uwagę w każdej rozwijanej aplikacji internetowej. Problem skryptletów polega na tym, że nie zapewnia żadnych wbudowanych mechanizmów zapobiegawczych, a przynajmniej nie używa standardowego interfejsu API Java. Następca JSP, Facelets, już domyślnie ucieka HTML, więc nie musisz się martwić dziurami XSS w Facelets.

Zobacz też:


117
+1 Świetna odpowiedź. Ale nie bądź dogmatyczny, czasem używanie skryptletów jest w porządku, ale powinien to być wyjątek potwierdzający regułę.
sachachon

26
@svachon: Skrypty są przydatne do szybkiego prototypowania / testowania. O ile mi wiadomo, istnieje tylko jedno „uzasadnione” wykorzystanie skryptletu do produkcji, a mianowicie <% response.getWriter().flush(); %>pomiędzy nim </head>a w <body>celu poprawy wydajności parsowania strony w przeglądarce. Ale to użycie jest z kolei całkowicie nieistotne, gdy rozmiar bufora wyjściowego po stronie serwera jest niski (1 ~ 2 KB). Zobacz także ten artykuł .
BalusC,

5
@BalusC Kilka razy utknąłem z klasami Java, które nie były zgodne z wzorcem getter / setter. IMHO to przypadek, w którym scripltet wykonuje swoją pracę.
sachachon,

41
@svachon: Owinąłem te klasy własnymi klasami javabean i użyłem ich zamiast tego.
BalusC,

31
To była całkiem dobra odpowiedź, ale części doGet i doPost wprowadzają w błąd. Te metody służą do obsługi określonych metod żądań (HEAD, GET i POST) i nie są przeznaczone do „wstępnego przetwarzania” ani „postprocesingu”!
MetroidFan2002

225

Aby zabezpieczyć: Wyłącz Pisma na dobre

W trakcie dyskusji nad innym pytaniem możesz i zawsze powinieneś wyłączyć skryptlety w web.xmldeskryptorze aplikacji internetowej.

Zawsze robiłbym to, aby uniemożliwić programistom dodawanie skryptletów, szczególnie w większych firmach, w których prędzej czy później stracisz przegląd. Te web.xmlustawienia wyglądać następująco:

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

4
Czy to również wyłącza komentarze skryptletów ?: <%-- comment that i don't want in the final HTML --%>. Uważam, że warto używać tych komentarzy zamiast HTML.
David Lavender

16
@MrSpoon wyszukał dla ciebie odpowiedź. Zgodnie z tą odpowiedzią + komentarzem powoduje to wyłączenie skryptletów <% %>, wyrażeń <%! %>skryptletowych i deklaracji skryptletowych <%= %>. Oznacza to, że dyrektywy <%@ %>i komentarze <%-- --%>pozostają włączone i użyteczne, więc nadal możesz robić komentarze i dołączać.
Martin Carney

3
Wyłączenie dyrektyw skryptletowych byłoby straszne - przycinanie białych znaków jest nieocenione do interakcji ze starszymi systemami, które wariują z dodatkową białą spacją.
corsiKa,

108

JSTL oferuje tagi dla instrukcji warunkowych, pętli, zestawów, pobrań itp. Na przykład:

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

JSTL działa z atrybutami żądania - najczęściej są one ustawiane w żądaniu przez serwlet, który przesyła je do strony JSP.


2
Dlaczego mówisz, że JSTL działa z atrybutami żądania? Mogą pracować z atrybutami w dowolnym zakresie, prawda?
Koray Tugay,

60

Nie jestem pewien, czy dobrze to zrozumiem.

Powinieneś przeczytać coś o MVC. Spring MVC & Struts 2 to dwa najczęściej stosowane rozwiązania.


29
MVC można zaimplementować za pomocą serwletów / jsp przy użyciu wielu z powyższych technik bez sprężyny lub rozpórki.
stepanian

18
Jak odpowiada na pytanie?
xyz

54

Możesz używać znaczników JSTL razem z wyrażeniami EL, aby uniknąć mieszania kodu Java i HTML:

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

34

Istnieją również frameworki oparte na komponentach, takie jak Wicket, które generują dla Ciebie dużo kodu HTML. Znaczniki, które kończą się w HTML, są niezwykle proste i nie ma praktycznie żadnej logiki, która by się pomieszała. W rezultacie powstają prawie puste strony HTML z typowymi elementami HTML. Minusem jest to, że w interfejsie API Wicket jest wiele elementów do nauki, a niektóre rzeczy mogą być trudne do osiągnięcia przy tych ograniczeniach.


33

We wzorze architektonicznym MVC strony JSP reprezentują warstwę widoku. Osadzanie kodu Java w plikach JSP jest uważane za złą praktykę. Możesz użyć JSTL , freeMarker , velocity z JSP jako „silnik szablonów”. Dostawca danych do tych tagów zależy od struktur, z którymi masz do czynienia. Struts 2a webworkjako implementacja dla MVC Pattern wykorzystuje OGNL „bardzo interesującą technikę w celu udostępnienia właściwości fasoli JSP”.


27

Doświadczenie pokazuje, że strony JSP mają pewne wady, jedną z nich jest trudność do uniknięcia mieszania znaczników z rzeczywistym kodem.

Jeśli możesz, rozważ użycie specjalistycznej technologii do tego, co musisz zrobić. W Java EE 6 jest JSF 2.0, który zapewnia wiele fajnych funkcji, w tym klejenie ziaren Java wraz ze stronami JSF poprzez #{bean.method(argument)}podejście.


3
Stara odpowiedź, ale nie mogę się powstrzymać przed stwierdzeniem, że JSF jest jednym z najbardziej przerażających wynalazków w przestrzeni Java. Spróbuj utworzyć pojedynczy link (HTTP GET like), a zrozumiesz dlaczego.
Alex,

@Alex, ale wciąż lepiej. Nie krępuj się polecić coś jeszcze lepszego.
Thorbjørn Ravn Andersen

26

jeśli chcesz po prostu uniknąć wad kodowania Java w JSP, możesz to zrobić nawet za pomocą skryptów. Po prostu przestrzegaj dyscypliny, aby mieć minimalną Javę w JSP i prawie żadnych obliczeń i logiki na stronie JSP.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%//instantiate a JSP controller
MyController clr = new MyController(request, response);

//process action if any
clr.process(request);

//process page forwaring if necessary

//do all variable assignment here
String showMe = clr.getShowMe();%>

<html>
    <head>
    </head>
    <body>
        <form name="frm1">
            <p><%= showMe %>
            <p><% for(String str : clr.listOfStrings()) { %>
            <p><%= str %><% } %>

            // and so on   
        </form>
    </body>
</html>

26

Naucz się dostosowywać i pisać własne tagi za pomocą JSTL

Zauważ, że EL to EviL (wyjątki czasu wykonywania, refaktoryzacja).
Furtka może być również zła (wydajność, trudna dla małych aplikacji lub prosta warstwa widoku)

Przykład z java2s ,

Należy go dodać do pliku web.xml aplikacji internetowej

<taglib>
    <taglib-uri>/java2s</taglib-uri>
    <taglib-location>/WEB-INF/java2s.tld</taglib-location>
</taglib>

utwórz plik: java2s.tld w / WEB-INF /

<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<!-- a tab library descriptor -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
    <tlib-version>1.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>Java2s Simple Tags</short-name>

    <!-- this tag manipulates its body content by converting it to upper case
    -->
    <tag>
        <name>bodyContentTag</name>
        <tag-class>com.java2s.BodyContentTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
          <name>howMany</name>
        </attribute>
    </tag>
</taglib>

skompiluj poniższy kod do WEB-INF \ klas \ com \ java2s

package com.java2s;

import java.io.IOException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class BodyContentTag extends BodyTagSupport{
    private int iterations, howMany;

    public void setHowMany(int i){
        this.howMany = i;
    }

    public void setBodyContent(BodyContent bc){
        super.setBodyContent(bc);
        System.out.println("BodyContent = '" + bc.getString() + "'");
    }

    public int doAfterBody(){
        try{    
            BodyContent bodyContent = super.getBodyContent();
            String bodyString  = bodyContent.getString();
            JspWriter out = bodyContent.getEnclosingWriter();

            if ( iterations % 2 == 0 ) 
                out.print(bodyString.toLowerCase());
            else
                out.print(bodyString.toUpperCase());

            iterations++;
            bodyContent.clear(); // empty buffer for next evaluation
        }
        catch (IOException e) {
            System.out.println("Error in BodyContentTag.doAfterBody()" + e.getMessage());
            e.printStackTrace();
        } // end of catch

        int retValue = SKIP_BODY;

        if ( iterations < howMany ) 
            retValue = EVAL_BODY_AGAIN;

        return retValue;
    }
}

Uruchom serwer i załaduj plik bodyContent.jsp w przeglądarce

<%@ taglib uri="/java2s" prefix="java2s" %>
<html>
    <head>
        <title>A custom tag: body content</title>
    </head>
    <body>
        This page uses a custom tag manipulates its body content.Here is its output:
        <ol>
            <java2s:bodyContentTag howMany="3">
            <li>java2s.com</li>
            </java2s:bodyContentTag>
        </ol>
    </body>
</html>

chociaż wielokrotne
użycie

25

Wicket jest również alternatywą, która całkowicie oddziela java od html, dzięki czemu projektant i programista mogą współpracować na różnych zestawach kodu, nie rozumiejąc się nawzajem.

Spójrz na Wicket.


23

Zadałeś dobre pytanie i chociaż masz dobre odpowiedzi, sugeruję, abyś pozbył się JSP. To przestarzała technologia, która ostatecznie umrze. Zastosuj nowoczesne podejście, takie jak silniki szablonów. Będziesz miał bardzo wyraźne oddzielenie warstw biznesowych i warstw prezentacji, a na pewno nie ma kodu Java w szablonach, dzięki czemu możesz generować szablony bezpośrednio z oprogramowania do edycji prezentacji internetowych, w większości przypadków wykorzystując WYSIWYG.

I z pewnością trzymaj się z dala od filtrów i przetwarzania wstępnego i końcowego, w przeciwnym razie możesz poradzić sobie z trudnościami związanymi z obsługą / debugowaniem, ponieważ zawsze nie wiesz, skąd zmienna uzyskuje wartość.


9
JSP sam w sobie jest silnikiem szablonów
WarFox

1
-1 - Istnieje wiele całkowicie uzasadnionych powodów używania filtrów, preprocesorów i postprocesorów. Tak, możesz skończyć z wartościami, które wydają się tajemnicze, ale nie, jeśli zrozumiesz swoją architekturę.
RustyTheBoyRobot

21

w celu uniknięcia kodu java w plikach JSP java udostępnia teraz biblioteki znaczników, takie jak JSTL, java również wymyśliła JSF, w którym można zapisywać wszystkie struktury programowania w postaci znaczników


21

Bez względu na to, ile próbujesz uniknąć, pracując z innymi programistami, niektórzy z nich nadal wolą skryptlet, a następnie wstawiają zły kod do projektu. Dlatego ustawienie projektu przy pierwszym znaku jest bardzo ważne, jeśli naprawdę chcesz zmniejszyć kod skryptletu. Istnieje kilka technik, aby sobie z tym poradzić (w tym kilka ram, o których inni wspominali). Jeśli jednak wolisz czysty sposób JSP, użyj pliku znaczników JSTL. Zaletą tego jest to, że możesz również skonfigurować strony wzorcowe dla swojego projektu, aby inne strony mogły dziedziczyć strony wzorcowe

Utwórz stronę wzorcową o nazwie base.tag pod tagami WEB-INF / o następującej treści

<%@tag description="Overall Page template" pageEncoding="UTF-8"%>

<%@attribute name="title" fragment="true" %>

<html>
  <head>
    <title>  
       <jsp:invoke fragment="title"></jsp:invoke>
    </title>

  </head>
  <body>
    <div id="page-header">
       ....
    </div>
    <div id="page-body">
      <jsp:doBody/>
    </div>
    <div id="page-footer">
      .....
    </div>
  </body>
</html>

Na tej stronie materiału utworzyłem fragment o nazwie „tytuł”, dzięki czemu na stronie podrzędnej mogę wstawić więcej kodów w to miejsce strony wzorcowej. Również tag<jsp:doBody/> zostanie również zastąpiony treścią strony podrzędnej

Utwórz stronę podrzędną (child.jsp) w folderze WebContent:

<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:base>
    <jsp:attribute name="title"> 
        <bean:message key="hello.world" />
    </jsp:attribute>

    <jsp:body>
    [Put your content of the child here]
    </jsp:body>   
</t:base>

<t:base>służy do określenia strony wzorcowej, której chcesz użyć (która w tej chwili jest base.tag). Cała zawartość tagu <jsp:body>zostanie zastąpiona <jsp:doBody/>na stronie wzorcowej. Twoja strona podrzędna może również zawierać dowolny tag lib i możesz normalnie z niej korzystać, tak jak inne wymienione. Jeśli jednak użyjesz tutaj dowolnego kodu skryptletu ( <%= request.getParameter("name") %>...) i spróbujesz uruchomić tę stronę, otrzymaszJasperException because Scripting elements ( &lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) are disallowed here . Dlatego nie ma możliwości, aby inni ludzie mogli dołączyć zły kod do pliku jsp

Wywoływanie tej strony z kontrolera:

Możesz łatwo wywołać plik child.jsp ze swojego kontrolera. Działa to również dobrze z frameworkiem struts


„Bez względu na to, jak bardzo starasz się unikać, pracując z innymi programistami, niektórzy z nich nadal wolą skryptlet, a następnie wstawiają zły kod do projektu”. Zobacz odpowiedź „Jako środek ochronny: wyłącz skrypty na dobre”.
Lluis Martinez



17

Jeśli ktoś naprawdę jest przeciwny programowaniu w więcej niż jednym języku , sugeruję GWT, teoretycznie możesz uniknąć wszystkich elementów JS i HTML, ponieważ Google Toolkit przekształca cały klient i wspólny kod w JS, nie będziesz miał z nimi problemu, więc masz serwis internetowy bez kodowania w innych językach. Nawet skądś możesz skorzystać z domyślnego CSS-a, który jest nadawany przez rozszerzenia (smartGWT lub Vaadin). Nie musisz uczyć się dziesiątek adnotacji.

Oczywiście, jeśli chcesz, możesz włamać się do głębi kodu i wstrzyknąć JS i wzbogacić swoją stronę HTML, ale tak naprawdę możesz tego uniknąć, jeśli chcesz, a wynik będzie dobry, jak napisano w innych ramach. Mówię, że warto spróbować, a podstawowy GWT jest dobrze udokumentowany.

I oczywiście wielu innych programistów niniejszym opisuje lub poleca kilka innych rozwiązań. GWT jest przeznaczony dla osób, które tak naprawdę nie chcą zajmować się częścią internetową ani jej minimalizować.


1
Naprawdę nie odpowiada na pytanie PO.
Evan Donovan,

1
@EvanDonovan dobrze, praktycznie daje odpowiedź. Nie musisz zadzierać z mieszaniem kodów Java z innymi językami. Przyznaję, że używa Java do kodowania, ale zostanie przetłumaczone na JS bez wywołań Java. Ale pytanie dotyczy tego, jak uniknąć chaosu klasycznego JSP. Technologia GWT rozwiązuje to. Dodałem tę odpowiedź, ponieważ nikt jej nie wspomniał, ale jest istotny, ponieważ jest to alternatywa dla JSP. Nie chciałem odpowiadać na cały zakres pytania, ale dodać cenne informacje dla ludzi, którzy szukają alternatyw.
CsBalazsHungary

16

Dobrym pomysłem ze świata Python są języki atrybutów szablonów ; TAL został wprowadzony przez Zope (dlatego też nazywany „Zope Page Templates”, ZPT) i jest standardem, z implementacjami również w PHP, XSLT i Javie (użyłem inkarnacji Python / Zope i PHP). W tej klasie języków szablonów jeden z powyższych przykładów mógłby wyglądać następująco:

<table>
    <tr tal:repeat="product products">
        <td tal:content="product/name">Example product</td>
        <td tal:content="product/description">A nice description</td>
        <td tal:content="product/price">1.23</td>
    </tr>
</table>

Kod wygląda jak zwykły HTML (lub XHTML) plus niektóre specjalne atrybuty w przestrzeni nazw XML; można go przeglądać za pomocą przeglądarki i bezpiecznie modyfikować przez projektanta. Obsługiwane są również makra i i18n:

<h1 i18n:translate="">Our special offers</h1>
<table>
    <tr tal:repeat="product products">
        <td tal:content="product/name"
            i18n:translate="">Example product</td>
        <td tal:content="product/description"
            i18n:translate="">A nice description</td>
        <td tal:content="product/price">1.23</td>
    </tr>
</table>

Jeśli tłumaczenia treści są dostępne, są one używane.

Jednak niewiele wiem o implementacji Java .


1
JSP od grudnia 2009 r. Zastąpiła firma Facelets, która obsługuje tę funkcję. Facelets jest również oparty na języku XML. Zobacz także między innymi rozdział Facelets w samouczku Java EE 6 i ui:xxxtagi w Facelts VDL .
BalusC

Nie znam dobrze Facelets, ale IIRC polega na pisaniu klas, które implementują niestandardowe elementy XML. Metodą TAL / ZPT jest posiadanie szablonów zawierających prawdziwy (X) HTML ze specjalnymi atrybutami, które wypełniają lub zastępują oryginalne elementy; w ten sposób możesz wyświetlić działający szablon i zobaczyć prototyp z ładną, obojętną treścią. Nie jestem pewien, czy Facelets pozwalają dostosować oryginalne elementy HTML (bez dodatkowej przestrzeni nazw) przy użyciu niestandardowych atrybutów.
Tobias

Jeszcze raz rzuciłem okiem na te cechy Facelets. Zawiera wszelkiego rodzaju narzędzia do walidacji itp., A zatem kieruje się zupełnie inną filozofią niż TAL. Sposób TAL brzmi: „Trzymaj logikę poza szablonem tak czysto, jak to możliwe; niech wszystkie skomplikowane rzeczy zostaną wykonane przez kontroler, który je karmi”. Nigdy nie dasz projektantowi szablonu Facelets, aby go / ją poprawił; to po prostu niemożliwe. Jeśli chodzi o generowaną treść - to tak jak używanie tal:replace="structure (expression)"atrybutów przez cały czas.
Tobias


14

Jasne, wymień <%! counter++; %> go architekturą producent-konsument zdarzenia, w której warstwa biznesowa jest powiadamiana o potrzebie zwiększenia licznika, odpowiednio reaguje i powiadamia prezenterów, aby zaktualizowali widoki. W grę wchodzi szereg transakcji z bazami danych, ponieważ w przyszłości będziemy musieli poznać nową i starą wartość licznika, który ją zwiększył i z jakim celem. Oczywiście chodzi o serializację, ponieważ warstwy są całkowicie oddzielone. Będziesz mógł zwiększyć swój licznik w stosunku do RMI, IIOP, SOAP. Ale wymagany jest tylko HTML, którego nie implementujesz, ponieważ jest to tak przyziemny przypadek. Twoim nowym celem jest osiągnięcie 250 przyrostów na sekundę na nowym błyszczącym serwerze E7 z 64 GB pamięci RAM.

Mam ponad 20 lat programowania, większość projektów kończy się niepowodzeniem przed sekstetem: Wielokrotnego użytku Wymienność OO-zdolności Debugowalność Testowalność Potrzebna jest nawet konserwacja. Inne projekty prowadzone przez ludzi, którzy dbali tylko o funkcjonalność, odniosły ogromny sukces. Ponadto sztywna struktura obiektu, zaimplementowana zbyt wcześnie w projekcie, uniemożliwia dostosowanie kodu do drastycznych zmian specyfikacji (zwanych także zwinnymi).

Uważam więc za zwlekanie działanie polegające na definiowaniu „warstw” lub nadmiarowych struktur danych na wczesnym etapie projektu lub gdy nie jest to specjalnie wymagane.  


11

Technicznie wszystkie pliki JSP są konwertowane na serwlety podczas działania . JSP został początkowo stworzony w celu oddzielenia logiki biznesowej i logiki projektowej, zgodnie ze wzorcem MVC. Tak więc JSP są technicznie wszystkimi kodami Java w czasie wykonywania. Ale aby odpowiedzieć na pytanie, biblioteki znaczników są zwykle używane do stosowania logiki (usuwania kodów Java) na stronach JSP.


8

Jeśli użyjemy następujących rzeczy w aplikacji Java, kod Java można usunąć z pierwszego planu JSP.

  1. Użyj architektury MVC do aplikacji internetowych

  2. Użyj tagów JSP

    za. Tagi standardowe

    b. Niestandardowe tagi

  3. Język wyrażeń


8

Jak uniknąć kodu Java w plikach JSP?

Oprócz języka wyrażeń ( EL ) można używać znaczników biblioteki kart, takich jak JSTL . Ale EL nie działa dobrze z JSP. Prawdopodobnie lepiej jest całkowicie upuścić JSP i użyć Faceletów .

Facelets to pierwszy język deklaracji stron inny niż JSP zaprojektowany dla JSF (Java Server Faces), który zapewnia prostszy i bardziej wydajny model programowania dla programistów JSF w porównaniu do JSP. Rozwiązuje różne problemy występujące w JSP podczas tworzenia aplikacji internetowych.

wprowadź opis zdjęcia tutaj

Źródło


Zdecydowanie popieram tę odpowiedź. JSF z lub bez Facelets. Myślałem, że rozwój w JSP w dużej mierze przestał istnieć ponad 10 lat temu. Ostatnio napisałem strony JSP w 2000 roku!
bagaż

4

Używanie skryptów jest bardzo starym sposobem i nie jest zalecane. Jeśli chcesz bezpośrednio wyświetlać coś na swoich stronach JSP, po prostu użyj języka wyrażeń (EL) wraz z JSTL .

Istnieją również inne opcje, takie jak użycie silnika szablonów, takiego jak Velocity, Freemarker, Thymeleaf itp. Ale używanie zwykłego JSP z EL i JSTL służy mi przez większość czasu i wydaje się również najprostsze dla początkującego.

Należy również pamiętać, że logika biznesowa w warstwie widoku nie jest najlepszą praktyką, należy wykonywać logikę biznesową w warstwie usługi i przekazywać wyniki wyjściowe do widoków za pośrednictwem kontrolera.


3

Nic z tego nie jest już używane, przyjacielu, radzę oddzielić widok (css, html, javascript itp.) Od serwera.

W moim przypadku moje systemy obsługują widok za pomocą Angulara, a wszelkie potrzebne dane są pobierane z serwera za pomocą usług odpoczynku.

Uwierz mi, to zmieni sposób projektowania


3

Użyj szkieletowego, kanciastego frameworka javascript do projektowania interfejsu użytkownika i pobierz dane za pomocą interfejsu API rest. Spowoduje to całkowite usunięcie zależności Java z interfejsu użytkownika.


3

JSP 2.0 ma funkcję o nazwie „Pliki znaczników” , możesz pisać znaczniki bez zewnętrznego javakodu i tld. Musisz utworzyć .tagplik i włożyć go WEB-INF\tags, możesz nawet stworzyć strukturę katalogów do pakowania swoich tagów.

Na przykład:

/WEB-INF/tags/html/label.tag

<%@tag description="Rensders a label with required css class" pageEncoding="UTF-8"%>
<%@attribute name="name" required="true" description="The label"%>

<label class="control-label control-default"  id="${name}Label">${name}</label>

Użyj tego jak

<%@ taglib prefix="h" tagdir="/WEB-INF/tags/html"%>
<h:label  name="customer name" />

Ponadto możesz łatwo odczytać treść znacznika

/WEB-INF/tags/html/bold.tag
<%@tag description="Bold tag" pageEncoding="UTF-8"%>
<b>
  <jsp:doBody/>
</b>

Użyj tego

<%@ taglib prefix="h" tagdir="/WEB-INF/tags/bold"%>
<h:bold>Make me bold</h:bold>

Próbki są bardzo proste, ale możesz tutaj wykonać wiele skomplikowanych zadań. Pamiętaj, że możesz użyć innych tagów (np .: JSTLkontrolujących tagi, takich jak if/forEcah/chosenmanipulacja tekstem, format/contains/uppercasea nawet tagi SQL select/update), przekazać wszystkie parametry, na przykład Hashmapdostęp session,request ... w pliku tag zbyt.

Plik znaczników jest tak łatwy do opracowania, że ​​nie trzeba było restartować serwera podczas ich zmiany, np. Plików JSP. Ułatwia to ich rozwój.

Nawet jeśli używasz frameworka, takiego jak Struts 2, który ma wiele dobrych tagów, może się okazać, że posiadanie własnych tagów może znacznie zmniejszyć kod. Możesz przekazać parametry tagu do rozpórek i w ten sposób dostosować swój tag ramowy.

Możesz użyć tagu nie tylko do uniknięcia java, ale także do zminimalizowania kodów HTML. Sam próbuję często przeglądać kody HTML i budować tagi, gdy tylko na moich stronach zaczynają się duplikaty kodu.

(Nawet jeśli ostatecznie użyjesz java w kodzie JSP, co mam nadzieję, że nie, możesz umieścić ten kod w tagu)


1

Jak mówi wiele odpowiedzi, użyj JSTL lub utwórz własne tagi niestandardowe. Oto dobre wyjaśnienie dotyczące tworzenia niestandardowych tagów


1
  1. Ustaw wartości i parametry w swoich klasach serwletów
  2. Pobierz te wartości i parametry ze swojego JSP, używając JSTL / Taglib

Zaletą tego podejścia jest to, że Twój kod jest również kodem HTML!


0

Używając tagów JSTL wraz z wyrażeniem EL można tego uniknąć. Umieść następujące rzeczy na swojej stronie jsp:

<%@ 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" %>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.