第2.3式. 在JSP中使用常数
问题
不通过scriptlets, 你想要在JSP中使用Java类中定义的应用常数public static字段。
动作要领
使用Jakarta Taglibs的unstandard标签库提供的bind标签来创建包含常数字段的JSTL变量:
<%@ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %>
<un:bind var="constantValue"
type="com.foo.MyClass"
field="SOME_CONSTANT"/>
<bean:write name="constantValue"/>
<%@ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %><un:bind var="constantValue"type="com.foo.MyClass"field="SOME_CONSTANT"/><bean:write name="constantValue"/>
动作变化
大多数团队都费力地通过使用publicstatic字段(常数)来避免在Java类中使用硬编码的字符串。不幸的是,不过是 Struts 还是 JSP都没有提供相应的手段来在JSP中不借助scriptlet 而使用这些常数,如:
<%= com.foo.MyClass.SOME_CONSTANT %>
但是有许多开发团队禁止,或者至少不赞成在JSP中使用scriptlet 。
Scriptlets (<% . . . %>)
和运行时表达式
(<%= . . . %>)
都直接在
JSP
中置入
Java
代码。它们不是与生俱来的恶人,但是它们因为使得你的页面中混合
HTML,JSP
和
Java
代码变得纷繁复杂,从而使开发效率大大降低。需要找到一种方法来避免使用
scriptlets
。你将发现
JSTL
的引入就是为了解决这个可怕的
scriptlet
的问题。
|
这种方法通过使用定制JSP标签来提供一种方式来解决这个窘境,即使用un:bind标签。该标签是unstandard标签库的一部分,unstandard标签库则是Jakarta Taglibs中的一个组件。unstandard标签库包含已经用于或者正在考虑用于标准标签库的标签。标准标签库是JSTL 规范的Jakarta Taglibs 的实现。
unstandard标签库可以从下面的地方下载: http://cvs.apache.org/builds/jakarta-taglibs-sandbox/nightly/projects/unstandard/. 为了使用这个库,你需要将unstandard.jar和unstandard.tld文件拷贝到应用的WEB-INF/lib目录。
un:bind标签提供了一种方法来创建JSP页面上下文变量,它一般引用java类中的一个字段。字段可以是实例变量或者静态变量。良好设计的Java 类一般都不会将实例变量暴露为公共字段,而大多数都将静态变量暴露为公共字段。
你可以创建一个使用Struts提供的静态字段的简单JSP页面来看看这种方法是否可行。从Struts 1.1开始, Struts 所用的常数都放在org.apache.struts.Globals类中。这些常数的值指定了各种存储在请求、会话、应用上下文中的Struts相关实体的关键字值。Example 2-5 中的JSP页面使用了un:bind标签来显示这些值:
Example 2-5. 使用bind 标签来访问Struts全局常数
<% @ page contentType="text/html;charset=UTF-8" language="java" %>
<% @ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %>
<% @ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
<% @ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<head>
<title>Struts Cookbook - Chapter 4 : Using Bind</title>
</head>
<body>
<un:bind var="servletKey"
type="org.apache.struts.Globals"
field="SERVLET_KEY"/>
<p>
Field name: SERVLET_KEY<br />
Field value: <bean:write name="servletKey"/>< br />
Attribute Value: <c:out value="${applicationScope[servletKey]}"/>< br />
</p>
</body>
</html>
此页面使用un:bind来从Struts Globals类中获取SERVLET_KEY字段的值。SERVLET_KEY字段的值被用于servlet 上下文属性关键字,在其下存储了为Struts controller servlet 定义的映射(如. /action/*或*.do)。
在你需要以一种特殊的方式访问常数时,un:bind标签是一个不错的选择。但是它还是有些麻烦,因为你需要首先使用un:bind标签来创建变量,然后使用bean:write或者c:out标签来显示值。假定JSP显示Globals类中的所有常数,而这足有17 个之多。许多应用严重依赖于常数并且可能有很多类,每一个类都包含很多字段。对每一个字段都使用一个单独的标签是多么的麻烦。
你可以使用一种替代方法,虽然需要一些额外的Java 代码,它可以将常数绑定到一个JavaBean 的一个Map属性之中。你可以将这个bean 存储在servlet 上下文中。然后就可以通过bean:write和c:out标签直接访问这些值了。Example 2-6中的Constants类定义了一个包含Struts Globals类中的常数的map属性的JavaBean 。Example 2-7 中的ConstantsPlugin则将Constants的一个实例载入到servlet context中。
Example 2-6. 包含Struts全局常数的JavaBean
package com.oreilly.strutsckbk.ch04;
import java.util.HashMap;
import java.util.Map;
import org.apache.struts.Globals;
public class Constants {
private Map strutsGlobals;
public Constants( ) {
strutsGlobals = new HashMap( );
strutsGlobals.put( "ACTION_SERVLET_KEY",
Globals.ACTION_SERVLET_KEY );
strutsGlobals.put( "SERVLET_KEY", Globals.SERVLET_KEY );
}
public Map getStrutsGlobals( ) {
return strutsGlobals;
}
public void setStrutsGlobals(Map strutsGlobals) {
this.strutsGlobals = strutsGlobals;
}
}
Example 2-7. 将常数载入到servlet context中的插件
package com.oreilly.strutsckbk.ch04;
import javax.servlet.ServletException;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
public class ConstantsPlugin implements PlugIn {
public void destroy( ) {
}
public void init(ActionServlet servlet, ModuleConfig module)
throws ServletException {
Constants constants = new Constants( );
servlet.getServletContext( ).setAttribute("Constants", constants);
}
}
Example 2-8 (globals_test.jsp) 则展示了一个访问和显示ConstantsPlugin载入的常数的JSP页面。第一个常数使用Struts bean:write标签,第二个则使用JSTL c:out标签。
Example 2-8. 使用Struts 和JSTL访问常数
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<head>
<title>Struts Cookbook - Chapter 4 : Accessing Constants</title>
</head>
<body>
<p>
Field name: ACTION_SERVLET_KEY<br />
Field value: <bean:write name="Constants"
property="strutsGlobals(ACTION_SERVLET_KEY)"/><br />
</p>
<p>
Field name: SERVLET_KEY<br />
Field value: <c:out value="${Constants.strutsGlobals.SERVLET_KEY}"/><br />
</p>
</body>
</html>
这种方式的最大缺点是你必须手动创建持有常数值的map。如果类中添加了新的常数,你必须修改Constants类的源代码以便能够获取它。
相关招式
关于Jakarta Taglibs 项目的详细信息可以访问 http://jakarta.apache.org/taglibs.
第5.4式提供了如何从Struts 和JSTL访问map的方法。
Struts plug-ins 我们在第2.1式讨论过。
Kris Schneider 建立了一个类似于Example 2-6中的Constants类,使用反射来访问特定类的公开静态字段。源代码可以从归档的struts-user mailing list 中找到: http://marc.theaimsgroup.com/?l=struts-user&m=108929374300664&w=2.
原文链接: http://www.dlog.cn/nicholascoder/diary/8934