有人告诉我使用 scriptlet (<%= ...%>) 在我的 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>

谢谢大家

有帮助吗?

解决方案

我认为如果你亲眼看到它实际上可以完全完成,这会更有帮助 没有 小脚本。

这是在其他人的帮助下进行的一对一重写 JSTL (只需放下 jstl-1.2.jar/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>

这是一个更优化的重写,请注意,我使用了 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>

如果您收集所有这些“硬编码”值,例如 eventspeople 并链接文本 Map 在每个JSTL下的应用范围和使用 <c:forEach> 显示选项卡。

至于你的 实际的 问题,你可以 禁用 scriptlet(并获取有关使用它的运行时错误)通过在 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 教程第二部分第 5 章. 。隐式 EL 对象,例如 ${pageContext} 被描述 这里. 。要了解有关 JSTL 的更多信息,请查看 Java EE 教程第二部分第 7 章. 。请注意,JSTL 和 EL 是两个不同的东西。JSTL 是一个 标准标签库 EL 只能以编程方式访问后端数据。虽然它通常在像 JSTL 这样的标签库中使用,但它也可以在模板文本中独立使用。

其他提示

  

顺便说一句,是<%= request.getContextPath() %>未就这么多皱起眉头小脚本的可接受使用?

这可能是一个不受欢迎的意见,但如果你做的是简单的条件表达式和文本插入,我不能在使用小脚本中发现很多故障。 (注意的如果

我可能会使用JSTL和表达式语言,但主要是因为它可以打字少,和IDE支持可能会更好(但良好的JSP IDE还可以找到丢失的右括号之类的东西)。

但从根本上(如在“保持逻辑出的模板”)我看不出有什么区别

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

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

这不是对你的问题的直接答案(已经有几个很好的答案,所以我不会尝试添加它),但你确实提到:

有更多Java/JSP体验的人可以给我一些有关如何更改此代码的指示 无论是什么,它都会更加“最佳实践”?

在我看来,关于 JSP 的最佳实践是,它应该严格用作 模板引擎, ,仅此而已(即,其中没有业务逻辑)。正如许多人指出的那样,使用 JSTL 绝对可以帮助您实现这一目标,但即使使用 JSTL,在 JSP 中也可以轻松完成很多工作。

我个人喜欢遵守其中规定的规则 在模板引擎中强制执行严格的模型视图分离 由 Terence Parr 在 JSP 中开发时编写。论文提到了模板引擎的目的(模型和视图分离),以及一个好的模板引擎的特点。它仔细研究了 JSP 并指出它不是一个好的模板引擎。毫不奇怪,JSP 基本上太强大了,并且允许开发人员做太多事情。我强烈建议您阅读本文,它将帮助您将自己限制在 JSP 的“好的”部分。

如果您只阅读该论文的一节,请阅读第 7 章,其中包括以下规则:

  1. 该视图无法通过直接更改模型数据对象或在引起副作用的模型上调用模型来修改模型。也就是说,模板可以从模型中访问数据并调用方法,但是此类引用必须不含副作用。此规则之所以出现部分原因,是因为数据参考必须对订单不敏感。参见第 7.1 节。
  2. 该视图无法对依赖数据值执行计算 因为将来计算可能会发生变化,并且在任何情况下都应将它们整齐地封装在模型中。例如,该视图不能将图书销售价格计算为“ $价格*.90”。要独立于模型,该视图不能对数据的含义做出假设。
  3. 视图无法比较相关数据值, ,但可以测试数据的属性,例如存在/不存在或多值数据值的长度。$ bloodpressure <120之类的测试必须转移到模型上,因为医生喜欢不断减轻对我们的最大收缩压。视图中的表达式必须替换为模拟布尔值的值的测试,例如$ floodpressureok!= null模板输出可以在模型数据和计算机上进行有条件的条件,只需在模型中计算条件。即使是制造负值红色的简单测试也应在模型中计算。正确的抽象级别是“部门X正在损失钱”之类的更高级别。
  4. 该视图无法做出数据类型假设。 当视图假设数据值是日期时,某种类型的假设是显而易见的,但是更微妙的类型假设是:如果模板假定$ userId是一个整数,则执行程序不能将此值更改为在不破坏模板的情况下是模型中的非数字。此规则禁止索引索引,例如colorcode [$ topic]和$ name [$ id]视图进一步无法用参数调用方法(静态或动态性地),除非一个人可以保证模型方法仅将它们视为对象。除了图形设计师之外,设计师不是程序员;期望他们调用方法并知道通过什么是不现实的。
  5. 模型中的数据不得包含显示或布局信息。该模型无法将任何显示信息传递给伪装为数据值的视图。这包括不传递模板的名称以应用于其他数据值。

顺便说一句,Terence 创建了自己的模板引擎,名为 字符串模板 据称,它在执行这些规则方面确实做得很好。我对此没有个人经验,但很想在我的下一个项目中检查一下。

小脚本是不是世界上最糟糕的事情。一个重要的考虑是考虑谁去要维护的代码。如果没有太多的Java经验,谁是它的网页设计师,你可能会更好过与标签库去。但是,如果Java开发人员都在做修的,也可能是他们更容易地去与小脚本。

如果你最终使用标签库和JSTL,您所期待的维护者也学习标签库和JSTL知道。一些开发商将被罚款用这个,因为它是他们想要或已经有本事,但对于一些开发商谁只需要处理JSP中每隔数个月左右,也可以是很多工作,痛苦少写在漂亮的明确书面小脚本,熟悉的Java。

您可能想通过使用标签库来启动。您可以使用标准的标签库 JSTL 做最常见的事情,你需要scriplets。但是也有一些在Struts2框架或从apache的使用像许多其他更丰富的标记库。

e.g。

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

将取代你的if语句。

要小脚本的优选的替代方案是JSTL表达式语言; 这里是一个很好的概述rel="nofollow。你将需要添加的taglib像这样:

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

作为一个例子,JSTL提供了一堆给你的东西,你需要隐式对象;你想要的是pageContext.request

所以,你可以用<%request.getRequestURI%>替换${pageContext.request.requestURI}

您可以使用<c:if>标签做条件语句。

您将需要使用一些Web框架。或至少一些方便的taglib。或模板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的 (我的最爱)或谷歌Web工具包

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top