JdbcUtils的三个版本

发布于:2025-06-28 ⋅ 阅读:(17) ⋅ 点赞:(0)
JDBC的工具类 1.0版本
JDBC的工具类 2.0版本(智能一些),编写properties属性文件,程序就可以读取属性文件
JDBC的工具类 3.0版本,加入连接池对象

我们封装jdbc工具类是为了减少代码重复,方便开发,JdbcUtils至少要有三个方法

1.新建驱动

2.新建连接

3.关闭资源

1.0 这里的static是为了直接调用类方法,不用new对象

public class JdbcUtils1 {



    /**
     * 加载驱动的方法  static
     */
    public static void loadDrive(){
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 连接对象conn
     */
    public static Connection getConntion(){
        loadDrive();
        Connection connection = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "root");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }


    /**
     * 获取执行sql的对象  Statement
     */
    public static Statement creatstmt() throws SQLException {
        Connection conntion = getConntion();
        Statement statement = conntion.createStatement();
        return statement;
    }


    /**
     * 关闭资源的提取
     */
    public static  void close(ResultSet rs, Statement stmt, Connection conn){
        try {
            rs.close();
            stmt.close();
            conn.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


}

2.0 可以动态修改配置,不是写死的了

 1. 驱动类
 2. 数据库地址
 3. 用户名
 4. 密码

package com.qcby.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC的工具类 1.0版本
 * JDBC的工具类 2.0版本(智能一些),编写properties属性文件,程序就可以读取属性文件
 *      1. 驱动类
 *      2. 数据库地址
 *      3. 用户名
 *      4. 密码
 */
public class JdbcUtils2 {

    private static final String driverclass;
    private static final String url;
    private static final String username;
    private static final String password;

    static{
        // 加载属性文件
        Properties pro = new Properties();
        InputStream inputStream = JdbcUtils2.class.getResourceAsStream("/db.properties");
        try {
            // 加载属性文件
            pro.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 给常量赋值
        driverclass = pro.getProperty("driverclass");
        url = pro.getProperty("url");
        username = pro.getProperty("username");
        password = pro.getProperty("password");
    }

    /**
     * 加载驱动
     */
    public static void loadDriver(){
        try {
            // 加载驱动类
            Class.forName(driverclass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 加载完驱动,获取到连接,返回连接对象
     * @return
     */
    public static Connection getConnection(){
        // 加载驱动
        loadDriver();
        // 获取到连接对象,返回
        Connection conn = null;
        try {
            // 获取到连接
            conn = DriverManager.getConnection(url,username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 关闭资源
     * @param conn
     * @param stmt
     * @param rs
     */
    public static void close(Connection conn, Statement stmt, ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭资源
     * @param conn
     * @param stmt
     */
    public static void close(Connection conn, Statement stmt){
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

3.0 加入连接池对象

package com.qcby.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC的工具类 1.0版本
 * JDBC的工具类 2.0版本(智能一些),编写properties属性文件,程序就可以读取属性文件
 * JDBC的工具类 3.0版本,加入连接池对象
 */
public class JdbcUtils3 {

    // 连接池对象
    private static DataSource DATA_SOURCE;

    static{
        // 加载属性文件
        Properties pro = new Properties();
        InputStream inputStream = JdbcUtils3.class.getResourceAsStream("/druid.properties");
        try {
            // 加载属性文件
            pro.load(inputStream);
            // 创建连接池对象
            DATA_SOURCE = DruidDataSourceFactory.createDataSource(pro);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从连接池中获取连接,返回。
     * @return
     */
    public static Connection getConnection(){
        Connection conn = null;
        try {
            conn = DATA_SOURCE.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 关闭资源
     * @param conn
     * @param stmt
     * @param rs
     */
    public static void close(Connection conn, Statement stmt, ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭资源
     * @param conn
     * @param stmt
     */
    public static void close(Connection conn, Statement stmt){
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

连接池xml配置

 <!--配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db?characterEncoding=utf8mb4" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

druid.properties配置

driverclass = com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring_db?useUnicode=true&characterEncoding=utf8
username=root
password=root

sql注入问题

/**
 * 演示SQL注入的问题,漏洞
 * 在已知用户名的情况下,通过sql语言关键字,登录系统。密码随意输入的。
 * SQL注入产生原因是SQL语句的拼接,利用SQL关键字产生效果。
 * 需要解决SQL注入的问题
 *
 * 解决SQL注入问题,采用SQL语句预编译的方式,把SQL语句中的参数使用 ? 占位符来表示,先把SQL语句编译,格式固定的。
 * 再给 ? 传入值,传入任何内容都表示值。数据库会判断SQL执行的结果。
 *
 *
 * 解决sql注入问题:
 * 1.使用预编译sql的PreparedStatement对象
 * 2.在通过PreparedStatement对象的set方法为每一个占位符赋值(避免了字符串拼接带来的关键字问题)
 * 3.执行sql方法 stmt.executeQuery(); 拿到结果集
 */
public class JdbcTest4 {

    public static void main(String[] args) {

        // 模拟登录的功能,有SQL注入的问题
        String result = new JdbcTest4().login2("aaa'or'1=1", "12309809");
        System.out.println(result);

//        String result = new JdbcTest4().login2("aaa", "123");
//        System.out.println(result);
    }


    /**
     * 采用预编译的方式,解决SQL注入的问题
     * @param username
     * @param password
     * @return
     */
    public String login2(String username,String password){
        Connection conn = null;
        // 预编译执行SQL语句对象
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            // 获取到连接
            conn = JdbcUtils3.getConnection();
            // 使用?占位符
            String sql = "select * from t_user where username = ? and password = ?";
            // 预编译SQL语句,把SQL语句固定
            stmt = conn.prepareStatement(sql);
            // 需要给 ? 设置值
            stmt.setString(1,username);
            stmt.setString(2,password);
            // 执行SQL语句
            rs = stmt.executeQuery();
            // 遍历数据
            if(rs.next()){
                // 表示存在数据,如果存在,说明用户名和密码编写正确
                return "登录成功...";
            }else{
                return "登录失败了...";
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils3.close(conn,stmt,rs);
        }
        return null;
    }

    /**
     * 模拟登录的功能,通过用户名和密码从数据库中查询
     * @param username
     * @param password
     * @return
     */
    public String login(String username,String password){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            // 获取到连接
            conn = JdbcUtils3.getConnection();
            // 编写SQL语句的拼接  '1=1' true  password = '1234sdfsce' false  true and false  整体上false
            // String sql = "select * from t_user where username = 'aaa' or '1=1' and password = '1234sdfsce'";
            // String sql = "select * from t_user where username = 'aaa' or false";
            String sql = "select * from t_user where username = '"+username+"' and password = '"+password+"'";
            // 执行sql
            stmt = conn.createStatement();
            // 执行
            rs = stmt.executeQuery(sql);
            // 遍历数据
            if(rs.next()){
                // 表示存在数据,如果存在,说明用户名和密码编写正确
                return "登录成功...";
            }else{
                return "登录失败了...";
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils3.close(conn,stmt,rs);
        }
        return null;
    }

}

数据库

sql注入导致账号密码错误也显示登录成功

使用占位符就能避免这个问题


网站公告

今日签到

点亮在社区的每一天
去签到