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+"'";// 執行sqlstmt = 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注入導致賬號密碼錯誤也顯示登錄成功
使用占位符就能避免這個問題