【问题标题】:JSP Temporary storing Repetitive Database ResultsJSP 临时存储重复数据库结果
【发布时间】:2013-05-16 21:12:13
【问题描述】:

我在 JSP 中有以下代码,每次用户访问该页面时都会重复运行。所有访问者的数据库结果值都是相同的。该页面采用参数“服务”,并基于它执行 SQL 查询。第二个 SQL 查询是根据第一个查询生成的“id”执行的。如果有 20 个不同的服务,它会运行以下查询 20 次,然后只显示页面。那么,有什么方法可以临时存储这些结果(使用缓存或其他东西),以便这些查询只运行一次/第一次访问,然后对于其他请求不进行数据库请求?这样页面加载速度非常快,并且不消耗任何 cpu/内存。我只能在 JSP 中执行此操作,并且拥有 apache tomcat 6。

 ================= EDITED PART================

我通过执行 application.getAttribute()/setAttribute() 找到了第一个解决方案。

 if(application.getAttribute(service)==null
 {
    //do first query
    application.setAttribute(service,name);
 } 
else name=application.getAttribute(service);

现在如何在第二个查询中使用 id 参数???请指教。。

=============================================

String service=request.getParameter("service");

sqlstr = "SELECT uniqueid,name,body FROM tbl_texts WHERE 
serviceunique='"+service+"' AND webdomain='" + webdomain + "'";

  rs = DbUtils.getRs(con,sqlstr);
  if (rs.next()) {
  id = rs.getString("uniqueid");
  name = rs.getString("name");
  body=rs.getString("body");

  }
  rs.close();


  sqlstr = "SELECT animage,awidth,aheight FROM tbl_Images WHERE 
  uniqueid='" + id + " AND profile='" + imageprofile + "'";
   rs = DbUtils.getRs(con,sqlstr);
   if (rs.next()) {
    images = rs.getString("animage");
     size= (int)  (rs.getDouble(awidth) * rs.getDouble(rs.getDouble(aheight) )
   rs.close();

提前致谢!

【问题讨论】:

  • 首先,你只有一个服务参数,怎么会有20种不同的服务呢?第二:在尝试通过使架构更复杂来提高性能之前,我会确保您确实存在性能问题。最重要的是,我会先让代码干净、正确且不受 SQL 注入攻击,然后再尝试快速。 Java 代码不应该在 JSP 中,并且必须使用准备好的语句。
  • @JBNizet.. 是的,这是一个复杂的系统,我已经被赋予处理它,我不能这么快地更改为 servlet..因为这是一个紧急情况,我需要找到一些临时解决方案.此页面包含所有正文部分,例如文本、横幅和图像,并且此页面通过传递参数“服务”从另一个(索引)页面调用。有时参数的数量变成 20,就像这个页面被索引页面调用 20 次一样。但是这个页面再次执行 SQL 查询,这很重..所以任何解决方案! ?
  • 坦率地说,通过添加一些缓存使代码更加混乱并不是一个好的解决方案。首先重构和清理。然后仅在必要时进行优化。
  • @JBNizet...所以你没有任何替代解决方案@!!

标签: java database jsp


【解决方案1】:

首先,不要使用字符串连接来构建 SQL 查询。使用准备好的语句。这是一个安全漏洞,没有理由错过这一点。

然后请注意,在 JSP 页面中使用 Java 代码被认为是不好的风格。这可能会导致无法维护的代码。在大多数情况下,最好遵守该规则。但现实一点,有时在某些情况下最好打破这个规则。负责任的开发人员应在权衡利弊后做出决定。

如果您决定将 Java 编写到您的 JSP 中,那就做对了。确保安全,使用准备好的语句,验证您的输入参数(1000 char 或 null id 是有效 id 吗?)并同步并发访问。

作为穷人的缓存,您可以使用简单的 Map 实例(可能每个 SQL 查询一个)并将映射存储到应用程序范围内。使用同步来访问和更改这些地图。

为每个地图创建一个参数类和一个结果类。

例如(使用 Apache Commons Lang EqualsBuilderHashCodeBuilder):

class TextsParam {
  private String service;
  private String webdomain;

  // Getters and setters ...

  @Override 
  public boolean equals(Object obj) {
    if(obj == null) { return false; }
    if(obj == this) { return true; }
    if(obj.getClass() != getClass()) {
      return false;
    }
    TextsParam other = (TextsParam) obj;
    return new EqualsBuilder()
             .appendSuper(super.equals(obj))
             .append(service, other.service)
             .append(webdomain, other.webdomain)
             .isEquals();
  }

  @Override
  public int hashCode() {
    // you pick a hard-coded, randomly chosen, non-zero, odd number
    // ideally different for each class
    return new HashCodeBuilder(17, 37)
        .append(service)
        .append(webdomain).
        .toHashCode();
  }

}

class TextsResult {
  private String id;
  private String name;
  private String body;

  // Getters and setters ...
}

那么你的第一张地图的类型可能是Map<TextsParam, TextsResult>

在您的代码中,在您检查参数 servicewebdomain 不为空且有效后,您使用这些参数创建一个 TextsParam 实例并检查您的地图是否已包含该键。如果是,请使用相应的TextsResult 值。否则执行数据库查询并将结果存储到您的地图中以供以后使用。不要忘记将该代码放入 synchronized 块(或更好的同步方法)中。

请注意,添加到地图中的条目永远不会被删除。因此,这仅适用于可管理大小的可缓存值。下一步是使用Map 实现,它会自动删除旧值,如LRU cache

【讨论】:

  • 谢谢老兄!!你给了我绝妙的主意!!我必须暂时这样做!我正在进行重新设计过程,但在那之前..系统必须实时运行!!谢谢你的建议!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-29
  • 2018-03-09
相关资源
最近更新 更多