Как избежать использования скриптов на моей странице 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>

спасибо всем

7 ответов


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

вот 1 на 1 переписать с помощью среди других тегов JSTL (просто напишите jstl-1.2.jar на /WEB-INF/lib) базовый и функции 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, проверьте Java EE учебник Часть II Глава 5. Неявные объекты EL, такие как ${pageContext} описаны здесь. Чтобы узнать больше о JSTL, проверьте Java EE учебник Часть II Глава 7. Обратите внимание, что JSTL и EL-это две разные вещи. JSTL-это стандартный taglib и EL просто позволяет получить доступ к данным бэкэнда программно. Хотя он обычно используется в taglibs, таких как JSTL, он также может использоваться автономно в тексте шаблона.


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

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

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

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

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

и

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

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

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

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

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

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

  1. вид не может изменить модель либо непосредственно модель изменения объекты данных или путем вызова методов модель, вызывающая побочные эффекты. То есть шаблон может получить доступ к данным из модели и методов invoke, но такие ссылки должны иметь побочный эффект бесплатный. Это правило возникает частично поскольку ссылки на данные должны быть заказ-нечувствительны. См. Раздел 7.1.
  2. представление не может выполнять вычисления на зависимых данных значения потому что вычисления могут изменения в будущем и они должен аккуратно инкапсулируйте в модель в любой случай. Например, представление не может вычислить цены продажи книги как "$цена.*90". Быть независимым от модель, вид не может сделать предположения о значении данных.
  3. вид нельзя сравнить зависимых значений данных, но может проверить свойства данных, такие как наличие / отсутствие или продолжительность многозначное значение. Тесты как $кровяногодавления
  4. представление не может делать предположения типа данных. некоторые предположения типа очевидно, когда представление принимает данные например, value-это дата, но больше предположения тонкого типа ap-pear: если a шаблон предполагает, что $userID является целое число, программист не может измените это значение на нечисловое в модели без нарушения шаблон. Это правило запрещает array индексирование, такое как colorCode[$topic] и $name[$ID] Взгляд дальше не может методы вызова с аргументами be-cause (статически или динамически) существует предполагаемый тип аргументации, если только смогл гарантировать модельный метод просто рассматривал их как предметы. К тому же графических дизайнеров нет программисты; ожидая, что они вызовут методы и знать, что передать нереалистичный.
  5. данные модели не должны содержать информацию о дисплее или макете. Модель не может пройти любой дисплей информация на вид замаскированный значение данных. Это включает в себя не прохождение имя шаблона для применения другие значения данных.

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


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

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


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

например

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

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


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

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

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

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

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


вам нужно будет использовать некоторую веб-структуру. Или, по крайней мере, какой-то удобный taglib. Или шаблон enginge, как FreeMarker.

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

Если вам нравится способ кодирования JSP, то я бы предложил стойки 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.

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