一次提交却发起了多次请求的一种可能的原因

后台报错

03-Mar-2018 20:39:34.260 警告 [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0] com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@57a3356 -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (2). Last acquisition attempt exception: 
 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"
    at sun.reflect.GeneratedConstructorAccessor223.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:389)
    at com.mysql.jdbc.Util.getInstance(Util.java:372)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:958)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1037)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2239)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2270)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2069)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:794)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44)
    at sun.reflect.GeneratedConstructorAccessor221.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:389)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325)
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:134)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
    at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

前台也发现了问题

在文件上传模块,出现了一个很不寻常的问题。在打开的文件上传窗口中,我填好信息,点击提交。发现发起了多次请求。把选项卡关掉,再试一下,请求次数又加一了。再关,再试,发出的又多一次(如下图)。

超级郁闷。我明明只是发起了一次请求。为什么会发出那么多个请求。如下图:

在确定后端代码无误后,我怀疑是因为前端我错误的使用了easyui的tabs选项卡。

找到问题所在

通过查看页面的元素,我发现,当我关闭选项卡后再打开新的选项卡,原本的选项卡中的元素依然还在。
我的操作如下:
1、点击左侧的菜单栏(结果是右侧出现一个选项卡)
2、关闭选项卡
3、点击左侧的菜单栏
4、关闭选项卡
5、循环执行
其中每执行一步操作都查看浏览器F12开发者工具中的页面元素源码。
结果发现,每次点击左侧的菜单栏,页面都会在尾部添加一段html代码,这段代码就是选项卡中显示的内容。而每次关闭选项卡,这段代码却没有被移除!!!
如下图:

这样,我就明白——为什么在弹窗中点击提交,会出现发起多次请求的问题了。因为每当我打开选项卡又关闭选项卡,对应的html代码段并没有被移除。

其中,被加载进来的html代码包含着表单,如:

<div id="wu-dialog" class="easyui-dialog" data-options="closed:true,iconCls:'icon-save'" style="width:400px; padding:10px;">
    <form id="wu-form" method="post" enctype="multipart/form-data">
        <table>
            <tr>
                <td width="60" align="right" hidden>id:</td>
                <td><input type="text" name="id" class="wu-text" hidden/></td>
            </tr>
            <tr>
                <td width="60" align="right">文件标题:</td>
                <td><input type="text" name="title" class="wu-text" /></td>
            </tr>
            <tr>
                <td align="right">文件描述:</td>
                <td><textarea name="remark" rows="6" class="wu-textarea" style="width:260px"></textarea></td>
            </tr>
            <tr>
                <td align="right">文件:</td>
                <td><input type="file" name="file"/></td>
            </tr>
        </table>
    </form>
</div>

因此,当我打开选项卡又关闭选项卡,打开又关闭,页面上就会有多段被加载进来的html代码,而如果我多次打开的是同一个内容,那么加载进来的html代码就是相同的。这样!就导致了页面中有包含着多个表单。

而其表单提交的相关脚本代码:

$('#wu-form').form('submit', {
    url:'/document/upload',
    success:function(data){
        if(data){
            $.messager.alert('信息提示','上传成功!','info');
            $('#wu-datagrid').datagrid('reload');
            $('#wu-dialog').dialog('close');
        }
        else
        {
            $.messager.alert('信息提示','上传失败!','info');
        }
    }
});

也就是说这是通过id选择器选中对应的控件,然后执行提交操作。而由于我页面中加载了多段一样的html代码,因此就会出现多个id都为“#wu-form”的表单,因此也就导致了发起多次请求!

ps:如果是在jsp中书写代码,是不允许出现id相同的控件。但是动态加载的方式却能实现。

解决问题

我前端框架使用的是EasyUI。

之所以会出现这个问题,我想是因为我错误的使用easyui的tabs控件。

在此之前,项目中是有这么一个bug的:当第一次点击菜单栏的其中一个选项,会出现一个选项卡,并且数据能加载出来。当点击另一个选项,会出现新的一个选项卡。但是其数据却不能正常加载出来。然后我发现,只要在打开一个新的选项卡之前,先把旧的选项卡给关闭,就不会出现这个问题了。

因此,在测试的时候,也就出现了“点击菜单栏的a选项,然后出现一个选项卡,关闭该选项卡,再点击菜单栏的a选项…”这样的循环操作了。因此,也就出现了发起多次请求的问题。

我理了一下逻辑:当点击菜单栏的其中一个选项的时候,会触发一个方法,会打开一个新的选项卡,并把相应的html代码加载到其中。

因此,我的想法就是在打开一个新的选项卡之前,调用一个方法把旧的选项卡给关掉,再调用另一个方法并把旧的html代码给移除掉。

怎么把旧代码移除呢。通过观察网页元素,发现被加载进来的这段html代码是两个div,而其中的class如combo-p和window是其独有的:

因此可以通过JQ的类选择器选中这两个控件并调用remove方法将其移除:

$(".combo-p").remove();
$(".window").remove();

这样,通过代码形式来实现打开一个新的选项卡前将旧的选项卡关闭,就不会出现新的选项卡数据加载不出来的问题。通过代码形式移除旧的html代码,就不会出现一次提交发起多次请求的问题了。

我想归根结底。还是因为我错误的使用了easyui的tabs。该界面是基于网上的一个模板自己改的,可能由于没有理解tabs的使用,因此才会出现这个怪异的现象。

总结

一次提交,发起多次请求的问题,很可能因为是因为在执行提交的时候,是通过触发一个脚本方法实现的。而脚本方法又是通过JQ来选中表单控件,如果页面中有多个表单,而多个表单控件都被JQ选择器选中,那么就会出现一次提交发起多次请求的问题。

当然了这只是其中一个可能的原因,可以参考一下。

猜你喜欢

转载自blog.csdn.net/weixin_30531261/article/details/79434364
今日推荐