有人告诉我,使用小脚本在我的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>
<% } %>
</div>
<div class="body">
<decorator:body />
</div>
</body>
</html>
感谢所有
我认为这有助于更多,如果你用自己的眼睛,它实际上可以完全没有小脚本做看看。
这里有一个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>
</div>
这里有一个更优化的重写,请注意,我用c:set
为“高速缓存”表达结果重用和我使用HTML <base>
标签来避免将上下文路径中的每一个环节(只是让所有相关的URL在网页相对于你的它--without领先的斜杠)!
<%@ 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>
</div>
如果你喜欢收集所有这些“硬编码”值,它实际上可以优化更多events
和people
,并链接文本在Map
中的应用范围,并且每个JSTL下使用<c:forEach>
显示选项卡。
至于你的实际问题,您可以禁用脚本小程序(并获得有关使用它的运行时错误),通过添加web应用程序的以下条目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教程第二部分第七章 。 需要注意的是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。
我个人比较喜欢按照所设定的规则执法的模板引擎严格的模型-视图分离的JSP开发时由特伦斯·帕尔。 本文提到的模板引擎(分离模型和视图),和良好的模板引擎的特性的目的。 它需要在JSP良好的外观,并指出方面它不是一个很好的模板引擎。 毫不奇怪,JSP基本上是太强大了,并允许开发人员做太多。 我强烈建议阅读本文,它会帮助你限制自己JSP的“好”的部分。
如果你读了该文中只有一个部分,阅读第7章,其中包括以下规则:
- 视图不能通过直接改变模型的数据对象或通过调用模型引起的副作用的方法修改模型。 也就是说,一个模板可以从模型访问数据和调用方法,但这种提法必须无副作用。 这条规则部分原因是,数据引用必须是顺序不敏感。 参见7.1节。
- 视图不能执行时依赖的数据值的计算 ,因为计算可以在将来改变和它们应该被整齐地封装在在任何情况下的模式。 例如,鉴于不能计算书的销售价格为“$价格* 0.90”。 独立于模型,视图不能对数据的含义假设。
- 视图不能比较相关的数据值 ,但可以测试如存在/不存在或一个多值数据值的长度的数据的属性。 像$血压<120测试,医生都喜欢保持reduc-荷兰国际集团对我们的最大收缩压必须移动到模型。 在视图表达式必须与测试被替换为的值simulat-荷兰国际集团的布尔如$ bloodPressureOk存在!= NULL模板输出可以是对模型数据和COM的putations条件,条件只是在该模型来计算。 即使是简单的测试,使负值红色的,应在模型计算; 抽象的适当水平是它通常一些更高层次的诸如“X部门正在赔钱。”
- 视图不能使数据类型的假设。 某些类型的假设是明显的,当观点假定数据值是一个日期,例如,但更含蓄型的假设AP-梨:如果一个模板假定$用户ID是一个整数,亲语法不能改变这个值是一个非-numeric在不破坏模板的模型。 此规则禁止数组索引诸如的ColorCode [$主题]和$ name [$ ID]视图进一步不能调用与是 - 原因参数(静态或动态)的方法有一个假定论元精神疾病类型,除非人们可以保证模型方法仅处理它们作为对象。 除了图形设计师不是程序员; 希望他们调用方法并了解传递是不现实的。
- 从模型数据必须不包含显示器或布局信息。 该模型可以不显示任何Informa的灰传递到伪装成数据值的图。 这包括不通过模板的名称适用于其他的数据值。
顺便说一句,特伦斯已经创建了一个名为自己的模板引擎字符串模板据称不执行这些规则的一个很好的工作。 我与它没有亲身经历,但很想看看我的下一个项目。
小脚本是不是世界上最糟糕的事情。 一个重要的考虑是考虑谁去要维护的代码。 如果它的网页设计师没有太多的Java经验谁做的,你可能最好用的标签库去。 但是,如果Java开发人员都在做修的,也可能是他们更容易地去与小脚本。
如果你最终使用标签库和JSTL,您所期待的维护者也学习标签库和JSTL知道。 一些开发商将被罚款用这个,因为它是他们想要或已经有本事,但对于一些开发商谁只需要处理JSP中每隔数个月左右,就可以减少很多痛苦写在漂亮的明确书面小脚本工作,熟悉的Java。
您可能需要使用标签库来启动。 您可以使用标准的标签库JSTL做大部分的,你需要scriplets的共同的东西。 有迹象表明,在Struts2框架或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}
。
你可以用做条件语句<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工具包 。