MariaDB学习(四)-数据库连接池DBCP、注册、登录、将WebServer改成数据库版本

数据库连接池DBCP

  • Data Base Connection Pool: 数据库连接池

  • 作用: 因为频繁开关连接会浪费服务器资源,使用数据库连接池可以将连接重用,避免频繁开关连接,从而提高执行效率.

  • 如何使用数据库连接池

    • 在pom.xml文件中添加数据库连接池相关的依赖

    <!-- 数据库连接池 -->
    <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>druid</artifactId>
       <version>1.1.21</version>
    </dependency>

 

注册功能

  • 创建用户表

    use newdb3;

    create table user(id int primary key auto_increment,username varchar(50),password varchar(50))charset=utf8;

  • 相关代码:

    Scanner sc = new Scanner(System.in);
    System.out.println("请输入用户名");
    String username = sc.nextLine();
    System.out.println("请输入密码");
    String password = sc.nextLine();
    //获取连接
    try (Connection conn = DBUtils.getConn()){
       //创建执行SQL语句的对象
       Statement s = conn.createStatement();
       //查询是否存在
       ResultSet rs = s.executeQuery("select id from user where username='"+username+"'");
       //判断是否有查询到数据
       if (rs.next()){
           System.out.println("用户名已存在!");
           return;
      }
       //准备插入数据的SQL
       String sql = "insert into user values(null,'"+username+"','"+password+"')";
       System.out.println(sql);
       //执行SQL语句
       s.executeUpdate(sql);
       System.out.println("执行完成!");

 

登录功能

select count(*) from user where username='tom' and password='123456';
  • 相关代码:

    Scanner sc = new Scanner(System.in);
    System.out.println("请输入用户名");
    String username = sc.nextLine();
    System.out.println("请输入密码");
    String password = sc.nextLine();
    //获取连接
    try (Connection conn = DBUtils.getConn()){
       Statement s = conn.createStatement();
       //准备查询的SQL语句 把用户名和密码拼接进去
       String sql = "select count(*) from user where username='username+"' and password='"+password+"'";
       System.out.println(sql);
       ResultSet rs = s.executeQuery(sql);
       //不管用户输入什么,都会有结果,所以不用判断是否有下一条数据,直接移动游标
       rs.next();
       //取出查询到的数量
       int count = rs.getInt(1);
       if (count>0){
           System.out.println("登录成功!");
      }else{
           System.out.println("用户名或密码错误!");
      }
    } catch (SQLException throwables) {
       throwables.printStackTrace();
    }
  • 以上写法存在SQL注入漏洞

  • 什么事SQL注入?

    往SQL语句中添加值的地方,添加进去了SQL语句,导致原有SQL语句的业务逻辑发生改变,这种行为称为SQL注入

  • 通过PreparedStatement 预编译的执行SQL语句的对象解决SQL注入问题

  • 相关代码:

    // **********************解决SQL注入问题***************************
    //用? 把变量的位置占上
    String sql = "select count(*) from user where username=? and password=?";
    //创建执行SQL语句的对象
    //预编译: 由原来执行时编译 提前到创建时编译,编译SQL语句时将SQL语句的
    //业务逻辑锁死, 编译后不会被用户输入的内容所影响
    PreparedStatement ps = conn.prepareStatement(sql);
    //替换SQL语句中的?
    ps.setString(1,username);
    ps.setString(2,password);
    //执行查询
    ResultSet rs = ps.executeQuery();

 

批量操作

  • 作用: 可以将多条SQL语句进行的多次网络数据传输合并成一次传输,从而提高了执行的效率

  • Statement相关代码:

    //批量操作 三次合并成一次数据传输
    s.addBatch(sql1);//添加到批量操作
    s.addBatch(sql2);
    s.addBatch(sql3);
    s.executeBatch();//执行批量操作
  • PreparedStatement相关代码:

    String sql = "insert into user values(null,?,?)";
    //因为SQL语句中有变量所以使用预编译的对象
    PreparedStatement ps = conn.prepareStatement(sql);
    for (int i = 1; i <= 100; i++) {
       ps.setString(1,"name"+i);
       ps.setString(2,"pw"+i);
       //添加到批量操作
       ps.addBatch();
       if (i%20==0){//每隔20次执行一次 避免内存溢出
           ps.executeBatch();
      }
    }
    //执行批量操作
    ps.executeBatch();
    System.out.println("执行完成!");

 

将WebServer改成数据库版本

  • 建库建表

    create database wsdb charset=utf8;

    use wsdb;

    create table user(id int primary key auto_increment,username varchar(50),password varchar(50),nick varchar(50),age int);

  • 在之前的WebServer工程中添加com.webserver.utils把今天工程中用到的DBUtils复制到这里

  • 在pom.xml中添加数据库和连接池相关的两个依赖,刷新maven

  • 修改DBUtils工具类中的newdb3为wsdb

  • 修改注册功能:

    • 将原注册的第二步和第三步注释掉,添加以下代码

      //把上面得到的参数保存到user表里面
      //获取连接
      try (Connection conn = DBUtils.getConn()){
         String sql = "insert into user values(null,?,?,?,?)";
         PreparedStatement ps = conn.prepareStatement(sql);
         ps.setString(1,username);
         ps.setString(2,password);
         ps.setString(3,nickname);
         ps.setInt(4,age);
         ps.executeUpdate();//执行
         //给客户端返回注册成功
         File file = new File(
                "./webapps/myweb/reg_success.html");
         response.setEntity(file);
      } catch (SQLException throwables) {
         throwables.printStackTrace();
      }
  • 修改登录功能:

    • 修改登录代码

              //获取连接
             try(Connection conn = DBUtils.getConnection();){
                 //准备登录查询的SQL
                 String sql = "select count(*) from user where username=? and password=?";
                 PreparedStatement ps = conn.prepareStatement(sql);
                 ps.setString(1,username);
                 ps.setString(2,password);
                 ResultSet rs = ps.executeQuery();//执行查询
                 rs.next();//移动游标
                 //取出查询到的数量
                 int count = rs.getInt(1);
                 if(count>0){//登陆成功
                     response.setEntity(new File("./webapps/myweb/login_success.html"));
                }else{
                     response.setEntity(new File("./webapps/myweb/login_fail.html"));
                }
            } catch (SQLException e) {
                 e.printStackTrace();
            }
             System.out.println("处理登录完毕!");

      UserController代码:

      package com.webserver.controller;

      import com.webserver.core.annotation.Controller;
      import com.webserver.core.annotation.RequestMapping;
      import com.webserver.http.HttpRequest;
      import com.webserver.http.HttpResponse;
      import com.webserver.utils.DBUtils;
      import com.webserver.vo.User;

      import java.io.*;
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.ArrayList;
      import java.util.List;

      /**
      * 处理与用户业务相关的操作
      */
      @Controller
      public class UserController {
         @RequestMapping("/myweb/regUser")
         public void reg(HttpRequest request, HttpResponse response){
             System.out.println("开始处理注册...");
             //1通过request获取注册页面上表单提交上来的注册信息
             //2将该用户信息保存到硬盘(序列化到一个文件中)
             //3设置response响应注册结果页面

             //1
             /*
                 获取reg.html页面表单输入框数据时,getParameter方法参数要与
                 该输入框name属性指定的名字完全一致!
              */
             //<input name="username" type="text">对应的页面上输入框
             String username = request.getParameter("username");
             String password = request.getParameter("password");
             String nickname = request.getParameter("nickname");
             String ageStr = request.getParameter("age");
             System.out.println(username+","+password+","+nickname+","+ageStr);
             /*
                 首先要验证用户输入的注册信息。
                 要求如下:
                 四项内容都必须写,不能有null的情况。
                 并且年龄必须是一个整数格式(正则表达式验证)

                 否则直接响应注册失败提示页面:reg_info_error.html
                 该页面剧中显示一行字:注册失败,注册信息有误!请重新注册。
              */
             if(username==null||password==null||nickname==null||
                     ageStr==null||!ageStr.matches("[0-9]+")){
                 File file = new File("./webapps/myweb/reg_info_error.html");
                 response.setEntity(file);
                 return;
            }
             int age = Integer.parseInt(ageStr);
             /*
                 2 将该用户以User对象形式序列化到文件中。
                   文件名格式:用户名.obj
              */
             /*
                 重复用户的验证,如果是重复用户则直接响应重复用户的提示页面:
                 have_user.html.中显示一行字:该用户已存在,请重新注册。
              */
      //       File userFile = new File("./users/"+username+".obj");
      //       if(userFile.exists()){//如果文件存在说明是重复用户
      //           response.setEntity(new File("./webapps/myweb/have_user.html"));
      //           return;
      //       }
      //
      //       try(
      //               ObjectOutputStream oos = new ObjectOutputStream(
      //                       new FileOutputStream(
      //                               userFile
      //                       )
      //               )
      //       ){
      //           User user = new User(username,password,nickname,age);
      //           oos.writeObject(user);
      //
      //           //3
      //           File file = new File(
      //                   "./webapps/myweb/reg_success.html");
      //           response.setEntity(file);
      //
      //       }catch(IOException e){
      //           e.printStackTrace();
      //       }
             //把上面得到的参数保存到user表里面
             //获取连接
             try(Connection conn = DBUtils.getConnection();){
                 String sql = "insert into user values(null,?,?,?,?)";
                 PreparedStatement ps = conn.prepareStatement(sql);
                 ps.setString(1,username);
                 ps.setString(2,password);
                 ps.setString(3,nickname);
                 ps.setInt(4,age);
                 ps.executeUpdate();//执行
                 //给客户端返回注册成功
                 File file = new File(
                         "./webapps/myweb/reg_success.html");
                 response.setEntity(file);

            } catch (SQLException e) {
                 e.printStackTrace();
            }

             System.out.println("处理注册完毕!");
        }

         @RequestMapping("/myweb/loginUser")
         public void login(HttpRequest request,HttpResponse response){
             System.out.println("开始处理登录...");
             //1获取登录信息
             //2处理登录
             //3响应登录结果页面

             //1
             String username = request.getParameter("username");
             String password = request.getParameter("password");
             if(username==null||password==null){
                 response.setEntity(new File("./webapps/myweb/login_fail.html"));
                 return;
            }
      //       File userFile = new File("users/"+username+".obj");
      //       if(userFile.exists()){//如果该文件存在,则说明该用户存在
      //           try(
      //                   ObjectInputStream ois = new ObjectInputStream(
      //                           new FileInputStream(userFile)
      //                   )
      //           ){
      //               User user = (User)ois.readObject();
      //               if(user.getPassword().equals(password)) {
      //                   //登录成功
      //                   response.setEntity(new File("./webapps/myweb/login_success.html"));
      //               }else{
      //                   //密码不对就是登录失败
      //                   response.setEntity(new File("./webapps/myweb/login_fail.html"));
      //               }
      //           }catch (Exception e){
      //               e.printStackTrace();
      //           }
      //       }else{//用户不存在
      //           response.setEntity(new File("./webapps/myweb/login_fail.html"));
      //       }
             //获取连接
             try(Connection conn = DBUtils.getConnection();){
                 //准备登录查询的SQL
                 String sql = "select count(*) from user where username=? and password=?";
                 PreparedStatement ps = conn.prepareStatement(sql);
                 ps.setString(1,username);
                 ps.setString(2,password);
                 ResultSet rs = ps.executeQuery();//执行查询
                 rs.next();//移动游标
                 //取出查询到的数量
                 int count = rs.getInt(1);
                 if(count>0){//登陆成功
                     response.setEntity(new File("./webapps/myweb/login_success.html"));
                }else{
                     response.setEntity(new File("./webapps/myweb/login_fail.html"));
                }
            } catch (SQLException e) {
                 e.printStackTrace();
            }
             System.out.println("处理登录完毕!");
        }

         @RequestMapping("/myweb/showAllUser")
         public void showAllUser(HttpRequest request,HttpResponse response){
             System.out.println("开始生成动态页面");
             //扫描users目录中的所有.obj文件并反序列化得到所有的User对象
             File usersDir = new File("./users");
             File[] subs = usersDir.listFiles(
                     e->e.isFile()&&e.getName().endsWith(".obj")
            );
             List<User> userList = new ArrayList<>();
             for(File userFile : subs) {
                 try (
                         ObjectInputStream ois = new ObjectInputStream(
                                 new FileInputStream(userFile)
                        )
                ) {
                     //InvalidClassException
                     User user = (User)ois.readObject();
                     userList.add(user);
                } catch (Exception e) {
                     e.printStackTrace();
                }
            }
             userList.forEach(System.out::println);

             try{
                 PrintWriter pw = response.getWriter();
                 pw.println("<!DOCTYPE html>");
                 pw.println("<html lang=\"en\">");
                 pw.println("<head>");
                 pw.println("<meta charset=\"UTF-8\">");
                 pw.println("<title>用户列表</title>");
                 pw.println("</head>");
                 pw.println("<body>");
                 pw.println("<center>");
                 pw.println("<h1>用户列表</h1>");
                 pw.println("<table border=\"1\">");
                 pw.println("<tr>");
                 pw.println("<td>用户名</td>");
                 pw.println("<td>密码</td>");
                 pw.println("<td>昵称</td>");
                 pw.println("<td>年龄</td>");
                 pw.println("</tr>");
                 for(User user : userList){
                     pw.println("<tr>");
                     pw.println("<td>"+user.getUsername()+"</td>");
                     pw.println("<td>"+user.getPassword()+"</td>");
                     pw.println("<td>"+user.getNickname()+"</td>");
                     pw.println("<td>"+user.getAge()+"</td>");
                     pw.println("</tr>");
                }

                 pw.println("</table>");
                 pw.println("</center>");
                 pw.println("</body>");
                 pw.println("</html>");

                 response.setContentType("text/html");
            }catch(Exception e){
                 e.printStackTrace();
            }
             System.out.println("动态页面生成完毕!");
        }
      }
posted @ 2021-07-26 18:42  Coder_Cui  阅读(158)  评论(0编辑  收藏  举报