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.
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 static
metody), 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:escapeXml
jest 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.