如何避免在我的 JSP 页面中使用脚本小工具?

2022-09-01 06:33:29

有人告诉我,在我的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核心函数taglib:/WEB-INF/lib

<%@ 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>

这是一个更优化的重写,请注意,我曾经“缓存”表达式结果以供重用,并且我使用HTML标记来避免将上下文路径放在每个链接中(只需使网页中所有相对URL相对于它 - 没有前导斜杠!c:set<base>

<%@ 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>

如果您收集所有这些“硬编码”值(如和)并在应用程序范围内链接文本并在每个JSTL下使用JSTL来显示选项卡,则实际上可以对其进行更多优化。eventspeopleMap<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 对象,如此处所述。要了解有关 JSTL 的更多信息,请查看 Java EE 教程第 II 部分第 7 章。请注意,JSTL 和 EL 是两个不同的东西。JSTL是一个标准的taglib,EL只是能够以编程方式访问后端数据。虽然它通常用于像JSTL这样的taglibs中,但它也可以在模板文本中单独使用。${pageContext}


答案 2

顺便说一句,是否可以接受脚本的使用,而不是那么多的皱眉头?<%= request.getContextPath() %>

这可能是一个不受欢迎的观点,但是如果你所做的只是简单的条件和文本插入,我在使用scriptlet时找不到太多的错误。(请注意)

我可能会使用JSTL和表达式语言,但主要是因为它可以减少类型,并且IDE支持可能更好(但是一个好的JSP IDE也可以找到缺少的右括号和类似的东西)。

但从根本上说(如“将逻辑排除在模板之外”)我没有看到任何区别

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

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