Ab der JSP 1.2-Spezifikation wird dringend empfohlen, die JSP Standard Tag Library (JSTL) in Ihrer Webanwendung zu verwenden, um den Bedarf an JSP-Scriptlets auf Ihren Seiten zu verringern . Seiten, die JSTL verwenden, sind im Allgemeinen einfacher zu lesen und zu pflegen.
...
Wenn möglich, vermeiden JSP Scriptlets , wenn Tag - Bibliotheken entsprechende Funktionalität bereitzustellen. Dies erleichtert das Lesen und Verwalten von Seiten, hilft, Geschäftslogik von Präsentationslogik zu trennen, und erleichtert die Entwicklung Ihrer Seiten zu Seiten im JSP 2.0-Stil (JSP 2.0-Spezifikation unterstützt die Verwendung von Scriptlets, betont sie jedoch nicht).
...
Im Sinne der Übernahme des MVC-Entwurfsmusters (Model View Controller), um die Kopplung zwischen der Präsentationsebene und der Geschäftslogik zu verringern, sollten JSP-Scriptlets nicht zum Schreiben von Geschäftslogik verwendet werden. Stattdessen werden JSP-Scriptlets bei Bedarf verwendet, um Daten (auch als "Wertobjekte" bezeichnet), die von der Verarbeitung der Clientanforderungen zurückgegeben wurden, in ein geeignetes Client-fähiges Format umzuwandeln. Selbst dann wäre dies besser mit einem Front-Controller-Servlet oder einem benutzerdefinierten Tag möglich.
Wenn Sie bei jeder Anforderung denselben Java-Code aufrufen möchten, unabhängig von der angeforderten Seite, weniger oder mehr, z. B. prüfen, ob ein Benutzer angemeldet ist, implementieren Sie einen Filter und schreiben Sie den Code entsprechend in die Methode. Z.B:doFilter()
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 Sie einem geeigneten Titel zugeordnet sind <url-pattern>
, der die interessierenden JSP-Seiten abdeckt, müssen Sie nicht denselben Code für die gesamten JSP-Seiten kopieren.
Wenn Sie einige Java - Code aufrufen möchten vorverarbeiten eine Anfrage, zB Vorbelastung einige Liste aus einer Datenbank in irgendeiner Tabelle anzuzeigen, falls erforderlich auf einigen Abfrageparameter basiert, implementieren dann ein Servlet und Schreibcode entsprechend in doGet()
Verfahren. 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 während des JSP-Renderings zugegriffen, sondern lange bevor die JSP angezeigt wird. Sie haben weiterhin die Möglichkeit, die Antwort zu ändern, wenn der DB-Zugriff eine Ausnahme auslöst. Im obigen Beispiel wird die Seite mit dem Standardfehler 500 angezeigt, die Sie ohnehin durch ein <error-page>
In anpassen können web.xml
.
Wenn Sie Java-Code aufrufen möchten, um eine Anforderung nachzubearbeiten , z. B. die Verarbeitung eines Formulars, dann implementieren Sie ein Servlet und schreiben Sie den entsprechenden Code in die 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 der Umgang mit verschiedenen Zielseitenzielen einfacher: erneutes Anzeigen des Formulars mit Validierungsfehlern im Fehlerfall (in diesem Beispiel können Sie es ${message}
in EL erneut anzeigen ) oder bei Erfolg einfach zur gewünschten Zielseite wechseln.
Wenn Sie Java-Code aufrufen möchten, um den Ausführungsplan und / oder das Ziel der Anforderung und der Antwort zu steuern , implementieren Sie ein Servlet gemäß dem Front Controller-Muster der MVC . 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 verwenden Sie einfach ein MVC-Framework wie JSF , Spring MVC , Wicket usw., sodass Sie nur eine JSP / Facelets-Seite und eine JavaBean-Klasse erhalten, ohne dass ein benutzerdefiniertes Servlet erforderlich ist.
Wenn Sie Java-Code aufrufen möchten, um den Fluss innerhalb einer JSP-Seite zu steuern , müssen Sie eine (vorhandene) Taglib zur Flusssteuerung wie den JSTL-Kern abrufen . ZB Anzeige 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-Tags, die gut zu all dem HTML passen, ist der Code besser lesbar (und damit besser zu warten) als eine Reihe von Scriptlets mit verschiedenen öffnenden und schließenden Klammern ( "Wo zum Teufel gehört diese schließende Klammer hin?" ). Eine einfache Hilfe besteht darin, Ihre Webanwendung so zu konfigurieren, dass eine Ausnahme ausgelöst wird, wenn noch Scriptlets verwendet werden, indem Sie Folgendes hinzufügen web.xml
:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
In Facelets , dem Nachfolger von JSP, das Teil des von Java EE bereitgestellten MVC-Frameworks JSF ist , können Scriptlets bereits nicht verwendet werden . Auf diese Weise werden Sie automatisch gezwungen, die Dinge "richtig" zu machen.
Wenn Sie Java-Code aufrufen möchten, um auf "Backend" -Daten innerhalb einer JSP-Seite zuzugreifen und diese anzuzeigen , müssen Sie EL (Expression Language) verwenden ${}
. ZB erneutes Anzeigen der übermittelten Eingabewerte:
<input type="text" name="foo" value="${param.foo}" />
Das ${param.foo}
zeigt das Ergebnis von request.getParameter("foo")
.
Wenn Sie Java-Code für Dienstprogramme direkt auf der JSP-Seite aufrufen möchten (normalerweise public static
Methoden), müssen Sie diese als EL-Funktionen definieren. In JSTL gibt es eine Taglib für Standardfunktionen , aber Sie können Funktionen auch einfach selbst erstellen . Hier ist ein Beispiel, wie JSTL fn:escapeXml
nützlich ist, um XSS- Angriffe zu verhindern .
<%@ 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 zusammenhängt. Dieses Problem muss in jeder von Ihnen entwickelten Webanwendung berücksichtigt werden . Das Problem von Scriptlets ist, dass sie keine Möglichkeit zur integrierten Verhinderung bieten, zumindest nicht unter Verwendung der Standard-Java-API. Der Nachfolger von JSP, Facelets, hat bereits implizites HTML-Escape-Verfahren, sodass Sie sich keine Gedanken über XSS-Lücken in Facelets machen müssen.