Grails 视图在调用控制器操作时挂起

Grails view hangs when calling a controller action

我有一个 link 使用 g:link GSP 标记的视图,其中包含运行和更新大量行的操作,因此需要一些时间。与此同时,浏览器处于不确定状态并在 30 秒后超时(这是 servlet 容器上的超时)。

问题:

  1. 页面超时是一种糟糕的用户体验。
  2. 每次超时,浏览器都会提交控制器动作。我已经通过检查查询是否已经 运行 来处理这个问题,所以这不再是问题。

问题:

如何触发控制器操作并将页面重新加载到同一视图?或者有没有更好的方法来处理这个问题,比如触发异步操作?

我尝试使用js重新加载页面,但它似乎没有重新加载页面。我读过有关实现消息队列的内容,但对于一个简单的问题来说似乎需要做很多工作。任何想法都会很好。提前谢谢你。

查看:

<li>
  <a class=""
     href="${g.createLink(controller: "hello", action: "dbAction")}">Run Update on DB
  </a>
</li>

控制器操作:

def dbAction() {
        some code...
        myservice.dbAction();
        redirect(action: 'index')progress"
        }
    }

我的服务 dbAction:

def dbAction() {
    Sql sql = getSql()
    sql.executeUpdate('''
    update mytable
    set
        mydata = calculate_data,
        updated_by = 'dbAction',
        updated_at = now()
    where
        id in (1,2,3)
}

我正好遇到你的问题。查询花费了很长时间 运行,控制器无法响应浏览器。所以,浏览器超时了。

我尝试了 3 种不同的方法来解决这个问题。

简单的出路: 我正在使用 Tomcat。因此,我将连接超时值设置得更长一些。 connectionTimeout 变量在 server.xml 文件中。

偷懒的出路: 我不知道 Grails 是否有任何类型的消息队列功能。所以,我推出了自己的。当我单击提交按钮 运行 一个很长的更新查询时,该操作将在数据库 table 中插入一种更新命令以及状态。然后我使用 Quartz 安排每 10 秒读取这个 table 来检查状态。如果状态是新的,我将状态更改为“进行中”。然后我让触发器在后台 运行 更新查询。完成后,我将状态更改为 FINISH。

因此,该操作只是向数据库中添加一行,然后回复显示类似...您已发出请求的视图。系统将稍后处理您的请求。

艰难的出路: 我检查了我所有的 SQL 和操作中的函数,以计算 SQL 和代码完成查询所需的时间。我接着rearrange/rewrite的函数和程序。我对此不够好。如果我能达到 O(n),那对我来说就足够了。