Как избежать использования сценариев на моей странице JSP?

Мне сказали, что использование скриптовлетов (<% =...% > ) на моих страницах JSP - не такая прекрасная идея.

Может ли кто-нибудь с немного более java/jsp опытом, пожалуйста, дайте мне несколько указаний относительно того, как изменить этот код, чтобы его более "лучшая практика", что бы это ни было?

Этот JSP на самом деле является моей главной страницей декоратора sitemesh. В основном мой веб-дизайн имеет вкладку и подменю, и я хочу как-то выделить текущую вкладку и показать правильное подменю, посмотрев на текущий URI запроса.

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <link href="<%= request.getContextPath() %>/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a 
    <%= request.getRequestURI().contains("/events/") ? "class='selected'" : "" %>
    href='<%= request.getContextPath() %>/events/Listing.action'>Events</a>
  <a 
    <%= request.getRequestURI().contains("/people/") ? "class='selected'" : "" %>
    href='<%= request.getContextPath() %>/people/Listing.action'>People</a>
</div>

<div class="submenu">
  <% if(request.getRequestURI().contains("/events/")) { %>
    <a href="Listing.action">List of Events</a>
    |<a href="New.action">New Event</a>
  <% } %>
  <% if(request.getRequestURI().contains("/people/")) { %>
    <a href="Listing.action">List of People</a>
    |<a href="New.action">New Person</a>
  <% } %>  
  &nbsp;
</div>

<div class="body">
  <decorator:body />
</div>

</body>
</html>

Спасибо всем

Ответ 1

Я думаю, что это помогает больше, если вы видите своими глазами, что на самом деле это можно сделать полностью без скриптлетов.

Здесь 1 на 1 переписывается с помощью других JSTL (просто снимите jstl-1.2.jar в /WEB-INF/lib) core и функции taglib:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <link href="${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a 
    ${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/events/Listing.action">Events</a>
  <a 
    ${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}">
    <a href="Listing.action">List of Events</a>
    |<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}">
    <a href="Listing.action">List of People</a>
    |<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

Здесь более оптимизированная переписывание, обратите внимание, что я использовал результаты выражения c:set для "кеша" для повторного использования и что я использую тэг HTML <base>, чтобы не помещать путь контекста в каждую ссылку (просто сделайте все относительные URL-адреса в своем веб-страница по отношению к ней - без ведущей косой черты!):

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" />
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" />

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <base href="${pageContext.request.contextPath}">
  <link href="assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a>
  <a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${isEvents}">
    <a href="Listing.action">List of Events</a>|<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${isPeople}">
    <a href="Listing.action">List of People</a>|<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

Его можно фактически оптимизировать, если вы соберете все эти "жестко закодированные" значения, такие как events и people, и тексты ссылок в Map в области приложения и используйте под каждым JSTL <c:forEach>, чтобы отобразить вкладки.

Что касается вашего актуального вопроса, вы можете отключить скрипты (и получить ошибки времени выполнения для его использования), добавив следующую запись в webapp web.xml. Это может помочь выявить наблюдаемые скриптлеты.

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

Чтобы узнать больше об EL, просмотрите часть 2 главы 5 Java EE, глава 5. Неявные EL-объекты, такие как ${pageContext}, описываются здесь здесь. Чтобы узнать больше о JSTL, просмотрите часть 7 главы 7 учебного курса Java EE. Обратите внимание, что JSTL и EL - это две разные вещи. JSTL является стандартным taglib, и EL просто позволяет программно получить доступ к данным на бэкэнд. Хотя он обычно используется в taglib, например JSTL, его также можно использовать автономно в тексте шаблона.

Ответ 2

Как в стороне, является <%= request.getContextPath() %> приемлемым использованием сценариев, на которых не так много хмурено?

Это может быть непопулярное мнение, но если все, что вы делаете, это простые условности и текстовые вставки, я не могу найти много ошибок в использовании скриптлетов. (Обратите внимание на if)

Я бы, вероятно, использовал JSTL и язык выражений, но в основном потому, что это может быть меньше набрав, а поддержка IDE может быть лучше (но хорошая JSP IDE также может найти отсутствующие закрывающие скобки и тому подобное).

Но в принципе (как в "держать логику из шаблонов" ) я не вижу никакой разницы между

<% if(request.getRequestURI().contains("/events/")) { %>

и

${fn:contains(pageContext.request.requestURI, '/events/') 

Ответ 3

Это не прямой ответ на ваш вопрос (и уже есть несколько хороших, поэтому я не буду пытаться добавить к нему), но вы упомянули:

Может ли кто-нибудь с немного больше java/jsp опыт, пожалуйста, дайте мне немного указатели относительно того, как изменить этот код поэтому его более "наилучшая практика", независимо от того, что это может быть?

На мой взгляд, лучшая практика в отношении JSP заключается в том, что ее следует использовать строго как механизм шаблонов, и не более (т.е. нет бизнес-логики). Использование JSTL, как многие из них указывают, определенно помогает вам туда добраться, но даже с JSTL это легко сделать в JSP.

Мне лично нравится следовать правилам, изложенным в "Принудительное строчное разделение модели" в Templating Engines от Terence Parr при разработке в JSP. В документе упоминается цель шаблонов двигателей (разделение модели и вида) и характеристики хорошего шаблонизатора. Он хорошо разбирается в JSP и указывает, что это не хороший шаблонный движок. Неудивительно, что JSP в основном слишком силен и позволяет разработчикам делать слишком много. Я настоятельно рекомендую прочитать эту статью, и это поможет вам ограничить себя "хорошими" частями JSP.

Если вы читаете только один раздел в этой статье, прочитайте главу 7, которая включает следующие правила:

  • представление не может изменить модель либо путем изменения модели объектов данных или путем вызова методов на модель, вызывающая побочные эффекты.То есть шаблон может получить доступ к данным из модели и методов вызова, но такие ссылки должны быть побочными свободно. Это правило возникает частично потому что ссылки на данные должны быть порядок учета регистра. См. Раздел 7.1.
  • представление не может выполнять вычисления по зависимым данным значения, поскольку вычисления могут изменения в будущем, и они должны быть аккуратно инкапсулирован в модели в любой случай. Например, представление не может рассчитать цены продажи книг в качестве "$ Цена * 0,90". Чтобы быть независимым от модель, представление не может предположения о значении данных.
  • представление не может сравнивать значения зависимых данных, но может протестировать свойства данных, таких как наличие/отсутствие или продолжительность многозначное значение данных. Тесты типа $bloodPressure < 120 необходимо перенести на модель, как врачи любят держать снижение максимального систолического давления на нас. Выражения в представлении должны быть заменен испытанием на наличие значение, сопоставляющее логическое значение, такое как $bloodPressureOk!= null Выход шаблона может быть обусловлено данными модели и компиляции, условное просто должен быть вычислен в модели. Даже простые тесты, которые делают отрицательные значения красный должен быть вычислен в модели; правильный уровень абстракции - кто-то более высокий уровень, такой как "Отдел х теряет деньги".
  • представление не может делать предположения типа данных. Некоторые предположения типа очевидно, когда представление предполагает данные Значение - это дата, например, но больше появляются тонкие допущения: если шаблон предполагает, что $userID является integer, программа не может измените это значение на нечисловую в модели, не нарушая шаблон. Это правило запрещает массив индексирование, такое как colorCode [$ topic] и $name [$ ID] В дальнейшем просмотр не может методы вызова с аргументами (статически или динамически) существует предполагаемый тип аргумента, если только один может гарантировать модельный метод просто рассматривали их как объекты. Кроме того, графические дизайнеры не программисты; ожидая, что они будут ссылаться методы и знать, что пройти нереально.
  • данные из модели не должны содержать информацию о дисплее или макете.Модель не может передавать какой-либо дисплей информация, представленная в представлении, замаскированном под значения данных. Это включает в себя не прохождение имя шаблона для применения к другие значения данных.

Кстати, Теренс создал свой собственный механизм шаблонов под названием String Template, который, как утверждается, действительно помогает выполнять эти правила. У меня нет личного опыта с ним, но мне бы хотелось проверить его в следующем проекте.

Ответ 4

Сценарии не самое худшее в мире. Важное соображение - подумать о том, кто будет поддерживать код. Если у его веб-дизайнеров, у которых не так много опыта Java, вам, вероятно, лучше идти с библиотеками тегов. Однако, если разработчики Java выполняют техническое обслуживание, им может быть проще использовать скриптлеты.

Если вы закончите использовать библиотеку тегов и JSTL, вы ожидаете, что сопровождающий также узнает библиотеку тегов и узнает JSTL. Некоторые разработчики будут в порядке с этим, поскольку это умение, которое они хотят или уже имеют, но для некоторых разработчиков, которым приходится иметь дело только с JSP каждые несколько месяцев или около того, может быть намного менее болезненно работать с четко написанными сценариями, написанными в приятном, знакомая Java.

Ответ 5

Вы можете начать с использования библиотек тегов. Вы можете использовать стандартную библиотеку тегов JSTL для выполнения большинства распространенных вещей, для которых вам нужны скрипты. Существует множество других более богатых библиотек тегов, которые используются как в структуре struts2, так и apache.

например.

  <c:if test="${your condition}">
       Your Content
  </c:if>

заменит ваши операторы if.

Ответ 6

Предпочтительной альтернативой сценариям является язык выражения JSTL; здесь хороший обзор. Вам нужно добавить taglib так:

<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>

В качестве примера JSTL предоставляет кучу неявных объектов, которые дают вам нужный материал; тот, который вы хотите, - pageContext.request.

Итак, вы можете заменить <%request.getRequestURI%> на ${pageContext.request.requestURI}.

Вы можете делать условные выражения, используя теги <c:if>.

Ответ 7

Вам понадобится использовать некоторые веб-фреймворки. Или, по крайней мере, некоторый удобный taglib. Или templating enginge, как FreeMarker.

Рамки объявлений:

Если вам нравится способ кодирования JSP, я бы предложил Struts 2.

<s:if test="%{false}">
    <div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
    <div>Will Be Executed</div>
</s:elseif>
<s:else>
    <div>Will Not Be Executed</div>
</s:else>

Тогда существует компонентно-ориентированный JSF.

Если вам нравится OOP и кодирование всего на Java, попробуйте Apache Wicket (мой любимый) или Инструмент Google Web Toolkit.