Из спецификации JSP 1.2 настоятельно рекомендуется использовать в вашем веб-приложении стандартную библиотеку тегов JSP (JSTL), чтобы помочь уменьшить потребность в JSP-скриптлетах на ваших страницах. Страницы, использующие JSTL, в общем, легче читать и поддерживать.
...
Где возможно, избегать JSP скриптлетов всякий раз, когда библиотеки тегов предоставляют эквивалентную функциональность. Это облегчает чтение и обслуживание страниц, помогает отделить бизнес-логику от логики представления и упрощает превращение ваших страниц в страницы в стиле JSP 2.0 (спецификация JSP 2.0 поддерживает, но не подчеркивает использование скриптлетов).
...
В духе принятия шаблона проектирования модель-представление-контроллер (MVC) для уменьшения связи между уровнем представления и бизнес-логикой, JSP-скриптлеты не следует использовать для написания бизнес-логики. Скорее, JSP скриптлеты используются при необходимости для преобразования данных (также называемых «объектами значений»), возвращаемых при обработке клиентских запросов, в надлежащий формат, готовый для клиента. Даже тогда это лучше сделать с помощью сервлета фронт-контроллера или пользовательского тега.
Если вы хотите вызывать тот же Java-код при каждом запросе, меньше или больше независимо от запрашиваемой страницы, например, проверяя, вошел ли пользователь в систему, затем внедрите фильтр и напишите код соответствующим образом в методе doFilter()
. E.g.:
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.
}
}
При отображении на соответствующий <url-pattern>
, охватывающий интересующие JSP-страницы, вам не нужно копировать один и тот же фрагмент кода на все страницы JSP.
Если вы хотите вызвать некоторый Java-код для предварительной обработки запроса, например, предварительно загрузив некоторый список из базы данных для отображения в некоторой таблице, при необходимости, основываясь на некоторых параметрах запроса, затем реализуйте servlet и напишите код соответствующим образом в методе doGet()
. E.g.:
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);
}
}
Таким способом легче справляться с исключениями. К БД не обращаются во время рендеринга JSP, но задолго до того, как JSP был отображен. У вас все еще есть возможность изменить ответ всякий раз, когда доступ к БД вызывает исключение. В приведенном выше примере будет отображена страница ошибки 500 по умолчанию, которую вы в любом случае можете настроить с помощью <error-page>
в web.xml
.
Если вы хотите вызвать некоторый Java-код для постпроцесс запроса, например, обрабатывая отправку формы, затем реализуйте сервлет и напишите код соответствующим образом в методе doPost()
. E.g.:
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.
}
}
Таким образом проще работать с разными адресами страниц результатов: переотобразить форму с ошибками проверки в случае ошибки (в данном конкретном примере вы можете повторно отобразить ее, используя ${message}
в EL ), или простопереход на нужную целевую страницу в случае успеха.
Если вы хотите вызвать некоторый Java-код для управления планом выполнения и / или пунктом назначениязапроса и ответа, затем реализуйте сервлет в соответствии с шаблоном Front Controller MVC.Например:
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);
}
}
Или просто используйте MVC-фреймворк, такой как JSF , Spring MVC , Wicket и т. Д., Чтобы вы в конечном итоге получилипросто страница JSP / Facelets и класс JavaBean без необходимости настраиваемого сервлета.
Если вы хотите вызвать некоторый код Java для , управляйте потоком внутри JSP-страницы вам нужно получить (существующий) taglib управления потоком, такой как JSTL core .Например, отображение List<Product>
в таблице:
<%@ 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>
С тегами в стиле XML, которые хорошо вписываются во весь этот HTML, код лучше читается (и, следовательно, лучше поддерживается), чем набор скриплетов с различным открытиеми закрывающие скобки ( «Куда, черт возьми, относится эта закрывающая скобка?» ).Простой способ - настроить ваше веб-приложение так, чтобы оно выдавало исключение всякий раз, когда скриптлеты все еще используются, добавив следующий фрагмент в web.xml
:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
В Facelets , преемник JSP, который является частью Java EE, предоставил инфраструктуру MVC JSF , уже не можно использовать скриптлетов .Таким образом, вы автоматически будете вынуждены делать все «правильным образом».
Если вы хотите вызвать некоторый код Java для доступа и отображения"backend »внутри страницы JSP, тогда вам нужно использовать EL (Expression Language), эти ${}
вещи.Например, повторное отображение введенных входных значений:
<input type="text" name="foo" value="${param.foo}" />
${param.foo}
отображает результат request.getParameter("foo")
.
Если вы хотите вызвать некоторые utility Java-код прямо на странице JSP (обычно public static
методов), тогда вам нужно определить их как EL-функции.В JSTL есть стандартные функции taglib , но вы также можете легко создавать функции самостоятельно .Вот пример того, как JSTL fn:escapeXml
полезен для предотвращения XSS атак .
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
Обратите внимание, что чувствительность XSS никак не связана конкретно с Java /JSP / JSTL / EL / что угодно, эту проблему необходимо учитывать в каждом веб-приложении, которое вы разрабатываете.Проблема скриптлетов заключается в том, что он не предоставляет никаких встроенных предупреждений, по крайней мере, не используя стандартный Java API.Преемник JSP Facelets уже неявно экранировал HTML, поэтому вам не нужно беспокоиться о дырах XSS в Facelets.