登录模块点击一次登录按钮发起了两次请求

前言

我还在想这个情况会不会跟上一篇博文一样,是因为某种问题导致页面生成了多个id一样的表单,但是发现并不是这样。目前这个问题暂时通过提交前禁用按钮提交功能,返回结果后恢复按钮提交功能来解决。根本原因还没找到。

问题描述

使用360浏览器

通过浏览器地址栏发起一个能登录成功的请求:

http://localhost:8080/user/login?loginId=liweizhi&password=liweizhi

查看后台,发现,只发起了一次访问:

09:09:28.246 [http-nio-8080-exec-32] INFO  hrm.controller.UserController - 进到了login方法
09:09:28.247 [http-nio-8080-exec-32] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
09:09:28.247 [http-nio-8080-exec-32] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@71c627a5] was not registered for synchronization because synchronization is not active
09:09:28.248 [http-nio-8080-exec-32] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@72dd5e26] will not be managed by Spring
09:09:28.249 [http-nio-8080-exec-32] DEBUG h.d.E.queryByLoginIdAndPassword - ==>  Preparing: SELECT login_id,password,identity FROM employee_inf WHERE login_id=? AND password = ?; 
09:09:28.250 [http-nio-8080-exec-32] DEBUG h.d.E.queryByLoginIdAndPassword - ==> Parameters: liweizhi(String), liweizhi(String)
09:09:28.253 [http-nio-8080-exec-32] DEBUG h.d.E.queryByLoginIdAndPassword - <==      Total: 1
09:09:28.254 [http-nio-8080-exec-32] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@71c627a5]
09:09:28.254 [http-nio-8080-exec-32] INFO  hrm.controller.UserController - 登录成功,准备跳往主界面

通过浏览器地址栏发起登录不成功的请求:

http://localhost:8080/user/login?loginId=liweizhi1&password=liweizhi1

却发起了两次访问:

09:11:24.892 [http-nio-8080-exec-38] INFO  hrm.controller.UserController - 进到了login方法
09:11:24.893 [http-nio-8080-exec-38] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
09:11:24.893 [http-nio-8080-exec-38] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67e3089a] was not registered for synchronization because synchronization is not active
09:11:24.894 [http-nio-8080-exec-38] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6d1b63ea] will not be managed by Spring
09:11:24.894 [http-nio-8080-exec-38] DEBUG h.d.E.queryByLoginIdAndPassword - ==>  Preparing: SELECT login_id,password,identity FROM employee_inf WHERE login_id=? AND password = ?; 
09:11:24.895 [http-nio-8080-exec-38] DEBUG h.d.E.queryByLoginIdAndPassword - ==> Parameters: liweizhi1(String), liweizhi1(String)
09:11:24.903 [http-nio-8080-exec-38] DEBUG h.d.E.queryByLoginIdAndPassword - <==      Total: 0
09:11:24.903 [http-nio-8080-exec-38] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67e3089a]
09:11:24.904 [http-nio-8080-exec-38] INFO  hrm.controller.UserController - 登录失败,账号密码错误
09:11:25.499 [http-nio-8080-exec-39] INFO  hrm.controller.UserController - 进到了login方法
09:11:25.500 [http-nio-8080-exec-39] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
09:11:25.500 [http-nio-8080-exec-39] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5281d24e] was not registered for synchronization because synchronization is not active
09:11:25.501 [http-nio-8080-exec-39] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@5879b93e] will not be managed by Spring
09:11:25.501 [http-nio-8080-exec-39] DEBUG h.d.E.queryByLoginIdAndPassword - ==>  Preparing: SELECT login_id,password,identity FROM employee_inf WHERE login_id=? AND password = ?; 
09:11:25.503 [http-nio-8080-exec-39] DEBUG h.d.E.queryByLoginIdAndPassword - ==> Parameters: liweizhi1(String), liweizhi1(String)
09:11:25.506 [http-nio-8080-exec-39] DEBUG h.d.E.queryByLoginIdAndPassword - <==      Total: 0
09:11:25.506 [http-nio-8080-exec-39] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5281d24e]
09:11:25.507 [http-nio-8080-exec-39] INFO  hrm.controller.UserController - 登录失败,账号密码错误

如果url参数为空:

http://localhost:8080/user/login?loginId=1&password=

如果上一次发起的是带参数值的url请求访问了两次,那么这次带参数值的url请求也是发起两次访问。

09:26:34.607 [http-nio-8080-exec-50] INFO  hrm.controller.UserController - 进到了login方法
09:26:34.607 [http-nio-8080-exec-50] INFO  hrm.controller.UserController - 账号或密码为空,不访问数据库,直接返回null
09:26:34.851 [http-nio-8080-exec-44] INFO  hrm.controller.UserController - 进到了login方法
09:26:34.852 [http-nio-8080-exec-44] INFO  hrm.controller.UserController - 账号或密码为空,不访问数据库,直接返回null

如果上一次访问url请求参数为空,那么这次请求参数为空的url请求就只访问一次:

09:29:16.214 [http-nio-8080-exec-48] INFO  hrm.controller.UserController - 进到了login方法
09:29:16.214 [http-nio-8080-exec-48] INFO  hrm.controller.UserController - 账号或密码为空,不访问数据库,直接返回null

上面那一段我并不能很好的表达,因为出现的情况很怪异,为什么会这样。

也就是说,只有账号密码填写正确的情况,才能确定只发起一次请求。其他情况均不能确定。通常是发起两次请求。

一开始我以为是前端的问题,但是我通过url直接访问也会出现这个问题,说明不是前端代码的问题。这就让我很郁闷了。

但是假如前端代码我在执行提交方法时,先禁用按钮点击功能,等返回结果后再恢复按钮的点击功能,就能保证只发起一次请求:

<script>
    function submitForm() {
        //$("#btn").attr("disabled",true);//禁用按钮
        $('#form').form('submit',{
            url:'/user/login',
            success:function (data) {
                if(data){
                    window.location.href=data;//页面跳转
                }else{
                    $('#p').text("您输入的账号或密码不正确,请重新输入");//给出提示
                }
                //$("#btn").attr("disabled",false);//恢复按钮
            }
        });
    }
</script>

郁闷。。。为什么会这样。。。

这是我的表单:

<div class="easyui-window" title="Login" style="width:320px;height:220px;" collapsible="false" minimizable="false" maximizable="false" closable="false" draggable="false" resizable="false">
    <form id="form" method="post" style="padding:10px 20px 10px 40px;">
        <p id="p">欢迎登录</p>
        <p>账号:<input class="easyui-textbox" name="loginId" data-options="prompt:'请输入账号'"></p>
        <p>密码:<input class="easyui-textbox" name="password" data-options="prompt:'请输入密码'" type="password"></p>
        <div style="padding:5px;text-align:center;">
            <button id="btn" class="easyui-linkbutton" onclick="submitForm()">登录</button>
        </div>
    </form>
</div>

这是我的后台代码:

    @ResponseBody
    @RequestMapping(value = "/login")
    public String login(@RequestParam("loginId") String loginId,
                              @RequestParam("password") String password,
                              //@RequestParam("token") String clientToken,
                              HttpSession session){
        logger.info("进到了login方法");

        if("".equals(loginId) || "".equals(password)) {
            logger.info("账号或密码为空,不访问数据库,直接返回null");
            return null;
        }
        User user = employeeService.getUserByLoginIdAndPassword(new User(loginId,password));
        if(user!=null){
            logger.info("登录成功,准备跳往主界面");
            session.setAttribute("user_session",user);
            return "/user/main";//login方法用@ResponseBody注解修饰了,因此这里是直接返回字符串到浏览器
        }else{
            logger.info("登录失败,账号密码错误");
            return null;
        }
    }

我想这也不是前端easyui框架的bug吧,毕竟我通过浏览器直接访问url是没有涉及到前端的。但是上面又说了前端代码提交前禁用按钮请求返回结果后恢复按钮功能就不会发起多次请求。

使用其他浏览器

我又换了火狐浏览器,发现,在火狐浏览器上通过url进行访问,任何情况都是发起一次请求!!!(ps:我上面的例子用的是360浏览器)

但是用火狐浏览器访问登录界面,当账号密码填写错误,出现的结果跟使用360浏览器一样,都是页面变成一片空白,如图:

奇怪的是!!!!当账号密码填写正确,没有进行页面的跳转,如图:

很不理解,我的脚本代码是这么写的:

    function submitForm() {
        //$("#btn").attr("disabled",true);//禁用按钮
        $('#form').form('submit',{
            url:'/user/login',
            success:function (data) {
                if(data){
                    window.location.href=data;//页面跳转
                }else{
                    $('#p').text("您输入的账号或密码不正确,请重新输入");//给出提示
                }
                //$("#btn").attr("disabled",false);//恢复按钮
            }
        });
    }

控制台也没报错说,无法识别window.location.href,没有报错。但是却莫名其妙的将后台返回的结果显示在界面上。

而使用谷歌浏览器,通过url进行访问的话,任何情况都是发起一次请求。但是如果通过登录界面进行访问的话,如果账号密码填写正确,是能进到主界面的。如果账号密码填写错误的情况,就会发起两次请求。跟360浏览器一样,页面变得一片空白。

整理一下

我使用url进行访问,就没涉及到前端,使用360登录成功的话就只发起一次请求,失败的话就发起两次请求。使用火狐、谷歌,账号密码正确与否都只发起一次请求。

通过界面进行访问,就涉及到前端。360和谷歌,账号密码正确的话能正确跳转到主界面,而火狐却只是返回返回的字符串。账号密码填写错误,三种浏览器都一样,发起两次请求,且页面变得一片空白。

目前解决方案

通过在脚本方法中,提交前禁用按钮点击功能,返回结果后恢复点击功能,就能实现只发起一次请求:

function submitForm() {
    $("#btn").attr("disabled",true);//禁用按钮
    $('#form').form('submit',{
        url:'/user/login',
        success:function (data) {
            if(data){
                window.location.href=data;//页面跳转
            }else{
                $('#p').text("您输入的账号或密码不正确,请重新输入");//给出提示
            }
            $("#btn").attr("disabled",false);//恢复按钮
        }
    });
}

但是火狐浏览器却还是有问题,当账号密码正确时,界面没有跳转到主界面,而是返回一个字符串显示在界面上。

我的看法

当我发现通过上面的脚本代码可以解决问题的时候,我猜想问题是出在前端。可是当我通过直接url进行进行访问,就没涉及到前端,但通过360浏览器的地址栏发起请求,在登录失败的时候也会发起两次请求。这又让我觉得问题不是出在前端。

我觉得问题就只能出在浏览器了,这锅暂时就让浏览器背着吧。暂时就这样吧。

至于为什么通过上面的脚本代码就能避开那个问题,我也不知道。这是我在前端处理表单”由于网络延迟重复点击提交按钮造成的发起多次请求“问题时碰巧解决的。

最后

记下这个问题,看看什么时候才有能力去解决。

猜你喜欢

转载自blog.csdn.net/weixin_30531261/article/details/79435423