【问题标题】:Accessing JavaBean Methods using EL from JSP从 JSP 中使用 EL 访问 JavaBean 方法
【发布时间】:2011-07-18 08:18:57
【问题描述】:

我正在将旧应用程序从 JSP 1.1 迁移到 JSP 2.1,并尝试在没有 scriptlet 的情况下完成所有工作。我有一个 JavaBean,我通过 CustomTag 创建、填充并插入到页面范围中。该 JavaBean 公开了一些基于其实例变量转换数据、生成 HTML sn-ps 等的方法。

当我需要访问我使用的 JavaBean 中的属性时:

${mybean.property}

但由于 JSP 2.1/EL 2.1 不支持在您的 bean 上调用方法(这需要 JSP 2.2/EL 2.2),我正在尝试确定将此类实用程序方法公开给我的 JSP 页面而不诉诸于脚本。

这是我需要访问的 JavaBean 上的方法示例:

public String getThumbColor() {
   String tbgcolor = "#FF0000";
   if (this.getJavaBuildTotal() > 0 && 
        this.getJavaBuildBroke() == 0 && 
        this.getCeeBuildBroke() == 0 && 
        this.getJavaBuildInvalid() == 0 && 
        !this.hasBuildException()) {
      tbgcolor = "#00FF00";
   }
   else if (this.getJavaBuildTotal() == 0 && this.getCeeBuildTotal() == 0) {
      tbgcolor = "#f7f814";
   }
   return tbgcolor;
}

感觉在 JSP 中将这个(以及大约 10 个类似的方法)完全转换为 JSTL 会弄乱我的 JSP 页面。

由于我已经在进行大型重构,我不介意进行剧烈的更改;但无论如何我都想不出消除我对某些使用条件来决定返回值、生成小型 HTML sn-ps 等方法的需求。

【问题讨论】:

  • 我可以假设你说的是public static方法当你说实用方法
  • 好吧,它们目前不是公共静态的。由于这些方法存在于现在已成为从 JSP 访问的 javabean 的 java 类中。他们根据类中的实例变量做出决定并做出相应的响应。我确实理解一种解决方案是将这些“实用程序”方法从 javabean 中移出,并作为将 java bean 作为参数的静态方法移到自定义标记中。

标签: java jsp jakarta-ee jsp-tags el


【解决方案1】:

看看JSTL。它至少提供了一组基本的core 标签来控制页面中的流程。在 scriptlets 中使用它来代替 if/else/switch。它还在functions taglib 中提供了几种实用方法。它提供了基本的String 操作,例如子字符串等。您还可以自己开发自定义 EL 函数,这些函数可以使用参数调用 public static 方法。

另见:


更新根据评论中的信息

他们根据类中的实例变量做出决定并做出相应的反应

您可以为这些变量添加 getter 并在 <c:if> 或其他任何地方使用它。

<c:if test="${bean.property == 'somevalue' && bean.otherproperty != 'foo'}">

如果这些值例如是常量,您甚至可以将其包装在 bean 中的布尔 getter 中。

public boolean isCondition() {
    return "somevalue".equals(property) && !"foo".equals(otherproperty);
}

你使用如下:

<c:if test="${bean.condition}">

有很多方法取决于具体的功能要求,这在你的问题中仍然很模糊。

另见:


更新 2:根据您问题中的新示例,演示文稿的细节应该放在视图 (JSP) 中。 bgcolor 是演示文稿的一部分。我建议用枚举替换它。

public enum Status {
    OK, FAIL, NONE;
}

public Status getStatus() {
   if (this.getJavaBuildTotal() > 0 && 
        this.getJavaBuildBroke() == 0 && 
        this.getCeeBuildBroke() == 0 && 
        this.getJavaBuildInvalid() == 0 && 
        !this.hasBuildException()) {
      return OK;
   }
   else if (this.getJavaBuildTotal() == 0 && this.getCeeBuildTotal() == 0) {
      return NONE;
   }
   return FAIL;
}

并在视图中声明颜色

<c:set var="bgcolor" value="${(build.status == 'OK') ? '#00ff00' : (build.status == 'FAIL') ? '#ff0000' : '#f7f814'}" />
...
<tr bgcolor="${bgcolor}">

或者,更好的是,为它创建一个 CSS 类

<tr class="build ${build.status}">

在样式(工作表)中

tr.build.OK { background: #00ff00; }
tr.build.FAIL { background: #ff0000; }
tr.build.NONE { background: #f7f814; }

【讨论】:

  • 这是一个很好的建议,而且我肯定已经使用它通过了。所以我的 JSP 不再使用 scriptlet 进行控制或循环。我改用 JSTL 核心标签。但是我仍然发现需要访问我的 JavaBean 上的某些非静态方法。如果我要将这些方法中的条件逻辑移动到使用 JSTL 核心的 JSP,我觉得我会弄脏我的 JSP。一种可能性是将这些方法移出 JavaBean 并将它们作为公共静态放入 CustomTag 中,使它们成为适当的 taglib 函数。但这似乎有点矫枉过正。
  • 当您谈到将我的决策逻辑包装在 getter 中时,您只提到值是静态的吗?那么里面有一些决策逻辑的getter,只能对静态变量进行操作吗?
  • 否,当值是常量,因此对变化不敏感时。
  • 是的,一旦创建并填充了 bean,它就不会再改变。特别是因为它只存储在页面的上下文中。每个页面请求都会根据请求参数创建和填充一个新 bean。
  • 我注意到您更新的问题。我在答案中添加了第二次更新。
【解决方案2】:

根据您的应用程序服务器/框架等,您也许可以覆盖 EL2.2 的默认 EL 实现(我已在 Tomcat 6.0.20 / JSF 2.0 Web 应用程序上成功使用 Tomcat 7 EL 2.2) .除此之外,您可以创建一个&lt;call-method object="..." method=""&gt;&lt;param=".."/&gt;...&lt;/call-method&gt; 标记并替换脚本。

无论如何,如果您不介意进行剧烈的更改,您应该消除来自您的 JSP 的这些调用,并使用 MVC architecture。你会:

  • 控制器组件(通常是 servlet/过滤器)接收客户端请求,对其进行解码并调用更新应用程序模型的适当操作。

  • 查看组件(通常是 JSP 页面)在 Action 完成后转发请求,因此它们只需读取更新后的模型并将其转储到对客户端的响应中。

大多数流行的 Java Web 框架都支持这种架构(Struts、JSF、Spring MVC,...)

【讨论】:

  • 我很欣赏使用 MVC,这可能是我的目标,但我看不出 MVC 将如何解决我的核心问题...防止我的 JSP 与 scriptlet 混淆,同时仍然允许 JSP 调用 HTML sn-ps 的复杂方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 2011-06-24
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多