今天我在写表单验证的时候,发现了一个离奇的问题,只要我尝试登陆超过一定次数,就会固定会出现阻塞



阻塞后,重启tomcat,总会一闪而过这些提示:
这些提示很明了了,说明是在Servlet中出现了阻塞,那我就在Servlet插桩试一下
在这里插入图片描述



我在Servlet前后都加上输出,可以看一下结果:
在这里插入图片描述



每次Servlet都可以被访问,但最后都出不来,那问题就出在Servlet里的代码了:

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("进入登录验证");

        Map<String, String[]> params = req.getParameterMap();
        User user = new User();
        user.setName(params.get("userName")[0]);
        user.setPassword(params.get("password")[0]);
        boolean flag = userService.login(user);
        if (flag) {
            // 如果登录成功,将登陆信息存入session中
            req.getSession().setAttribute("user",user);
            System.out.println("session存值");

            //登录成功,跳转到成功页面(转发)
            req.getRequestDispatcher("success.jsp").forward(req,resp);
        } else {
            //登录失败,跳转到失败页面(重定向)
            resp.sendRedirect("fail.jsp");
        }

        /**
         * 这里发现一个问题,只要前端请求登录5次以上,马上就会出现阻塞
         * 初步认为是数据库连接池的问题
         */
        System.out.println("登录验证结束!");
        System.out.println("\n\n");
    }



这里只有可能是Service代码出的问题,我又往Service找:

public boolean login(User user) {
        List<User> users = userDao.selectByName(user.getName());
        //查无此人
        if (users==null || users.size()==0) {
            return false;
        }
        User daoUser = users.get(0);
        //密码不匹配
        if (!Objects.equals(user.getPassword(),daoUser.getPassword())) {
            return false;
        }
        //匹配成功
        return true;
    }


因为这是一个测试项目,service层代码并不复杂,所以只可能是Dao层的问题:

@Override
    public List<User> selectByName(String name) {
        String sql = "select * from user where name =?";
        ArrayList params = new ArrayList();
        params.add(name);
        ResultSet rs = this.query(sql, params);
        List<User> users = ResultSetUtil.ResultSetToBean(rs, User.class);
        // close();
        return users;
    }

    @Override
    public User selectById(Integer id) {
        String sql = "select * from user where id =?";
        ArrayList params = new ArrayList();
        params.add(id);
        ResultSet rs = this.query(sql, params);
        List<User> users = ResultSetUtil.ResultSetToBean(rs, User.class);
        if (users!=null && users.size()>0) {
            return users.get(0);
        }
        // close();
        return null;
    }

    @Override
    public List<User> queryAll() {
        String sql = "select * from user";
        ResultSet res = query(sql, null);
        List<User> users = ResultSetUtil.ResultSetToBean(res, User.class);
        // close();
        return users;
    }


因为 JDBC 的操作,我用反射封装了,所以要在BaseDao中找:
这个时候我才意识到,自己写的 close()方法,从来没有用过
这个时候,我就开始思考,是不是因为自己从来没有返回数据库连接,使得前面的连接被占用,导致后面的请求,都无法使用连接?

于是,我乖乖的在Dao层实现中,加上了 close()方法的调用:

在这里插入图片描述



果然,在添加了连接池关闭操作后,现在无论请求多少次,都不会出现阻塞了!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐