1.JavaWeb介绍
什么是JavaWeb?
- Web:全球广域网,也称万维网(www),能够通过浏览器访问的网站
- JavaWeb:使用Java技术来解决相关web互联网领域的技术栈

- 网页:展现数据
- 数据库:存储和管理数据
- JavaWeb程序:逻辑处理
数据库已学习
2.JDBC
- JDBC就是使用Java语言操作关系型数据库的一套API

2.1、JDBC简介
JDBC概念
- JDBC就是使用Java语言操作关系型数据库的一套API
- 全称:(Java DataBase Connectivity)Java数据库连接
JDBC本质:
- 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
- 各个数据库厂商去实现这套接口,提供数据库驱动jar包
- 我们可以使用这套接口(JDBC)编程,真正执行代码的是驱动jar包中的实现类
JDBC的好处:
- 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
- 可随时替换底层数据库,访问数据库的Java代码基本不变

2.2、JDBC快速入门
步骤:
-
创建工程,导入驱动jar包
![image]()
-
注册驱动
Class.forName("com.mysql.jdbc.Driver"); -
获取连接
Connection conn = DriverManager.getConnection(url,username,password); -
定义SQL语句
String sql = "update..." -
获取执行SQL对象
Statement stmt = conn.createStatement(); -
执行SQL
stmt.executeUpdate(sql); -
处理返回结果
-
释放资源
package com.itheima.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;public class JDBCDemo {public static void main(String[] args) throws Exception {// 1.注册驱动Class.forName("com.mysql.jdbc.Driver");// 2.获取连接String url = "jdbc:mysql://127.0.0.1:3306/itheima";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);// 3.定义sqlString sql = "update account set money = 2000 where id = 1";// 4.获取执行sql的对象 StatementStatement stmt = conn.createStatement();// 5.执行sqlint count = stmt.executeUpdate(sql);//受影响的行数// 6.处理返回结果System.out.println(count);// 7.释放资源stmt.close();conn.close();}
}

2.3、JDBC API详解
(1)DriverManager
-
DriverManager(驱动管理类)作用:
-
注册驱动
Class.forName("com.mysql.jdbc.Driver");-
查看Driver类源码
![image]()
提示:
- MySQL 5之后的驱动包,可以省略注册驱动的步骤
- 自动加载jar包中的META-INF/services/java.sql.Driver文件中的驱动类
-
-
获取数据库连接
![image]()
-
参数
-
url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2... 示例:jdbc:mysql://127.0.0.1:3306/itheima 细节: 1.如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对 2.配置 useSSL = false参数,禁用安全连接方式,解决警告问题 -
user:用户名
-
password:密码
-
package com.itheima.jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement;/*** JDBC API详解:DriverManager*/ public class JDBCDemo2_DriverManager {public static void main(String[] args) throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///itheima?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);// 3.定义sqlString sql = "update account set money = 2000 where id = 1";// 4.获取执行sql的对象 StatementStatement stmt = conn.createStatement();// 5.执行sqlint count = stmt.executeUpdate(sql);//受影响的行数// 6.处理返回结果System.out.println(count);// 7.释放资源stmt.close();conn.close();} } -
-
(2)Connection
-
获取执行SQL的对象
-
普通执行SQL对象
Statement createStatement() -
预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql) -
执行存储过程的对象
CallableStatement prepareCall(sql)
-
-
事务管理
-
MySQL事务管理
开启事务:begin;/start transaction; 提交事务:commit 回滚事务:rollback;MySQL默认自动提交事务 -
JDBC事务管理:Connection接口中定义了3个对应的方法
开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务;false为手动提交事务,即为开启事务 提交事务:commit() 回滚事务:rollback()
package com.itheima.jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;/*** JDBC API详解:Connection*/ public class JDBCDemo3_Connection {public static void main(String[] args) throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///itheima?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);// 3.定义sqlString sql1 = "update account set money = 3000 where id = 1";String sql2 = "update account set money = 3000 where id = 2";// 4.获取执行sql的对象 StatementStatement stmt = conn.createStatement();try {//开启事务conn.setAutoCommit(false);// 5.执行sqlint count1 = stmt.executeUpdate(sql1);//受影响的行数// 6.处理返回结果System.out.println(count1);// 5.执行sqlint count2 = stmt.executeUpdate(sql2);//受影响的行数// 6.处理返回结果System.out.println(count2);//提交事务conn.commit();} catch (Exception throwables) {//事务回滚conn.rollback();throwables.printStackTrace();}// 7.释放资源stmt.close();conn.close();} }使用try catch 来捕捉异常,一旦在sql语句执行过程中出现异常,进行事务回滚。
如:
try {//开启事务conn.setAutoCommit(false);// 5.执行sqlint count1 = stmt.executeUpdate(sql1);//受影响的行数// 6.处理返回结果System.out.println(count1);int i = 3/0;// 5.执行sqlint count2 = stmt.executeUpdate(sql2);//受影响的行数// 6.处理返回结果System.out.println(count2);//提交事务conn.commit();} catch (Exception throwables) {//事务回滚conn.rollback();throwables.printStackTrace();}在第9行代码中 出现int i= 3/0 异常,account表中还是保持原来的数据不变,若没有开启事务,则会将第一条数据改为3000;
-
(3)Statement
-
Statement作用:
- 执行SQL语句
-
执行SQL语句
int executeUpdate(sql):执行DML、DDL语句返回值:(1)DML语句影响的行数(2)DDL语句执行后,执行成功也可能返回0ResultSet executeQuery(sql):执行DQL语句返回值:ResultSet结果集对象- 执行DML语句
package com.itheima.jdbc;import org.junit.Test;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;/*** JDBC API详解:Statement*/ public class JDBCDemo4_Statement {@Testpublic void testDML() throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///itheima?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url, username, password);// 3.定义sqlString sql1 = "update account set money = 3000 where id = 2";String sql2 = "insert into account values (3,'王五',1000)";// 4.获取执行sql的对象 StatementStatement stmt = conn.createStatement();// 5.执行sqlint count1 = stmt.executeUpdate(sql1);//执行完DML语句,受影响的行数int count2 = stmt.executeUpdate(sql2);//执行完DML语句,受影响的行数// 6.处理返回结果//System.out.println(count);if (count1 > 0) {System.out.println("修改成功");} else {System.out.println("修改失败");}if (count2 > 0) {System.out.println("添加成功");} else {System.out.println("添加失败");// 7.释放资源stmt.close();conn.close();}} }-
执行DQL语句
![image]()
(4)ResultSet
-
ResultSet(结果集对象)作用:
- 封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象 -
获取查询结果
boolean next(): (1)将光标从当前位置向下移动一行 (2)判断当前行是否为有效行返回值:true:有效行,当前行有数据false:无效行,当前行没有数据xxx getXxx(参数):获取数据xxx:数据类型;如:int getInt(参数);String getString(参数)参数:int:列的编号,从1开始String:列的名称 -
使用步骤
- 游标向下移动一行,并判断该行是否有数据:next()
- 获取数据:getXxx(参数)
//循环判断游标是否是最后一行末尾 while(rs.next()){//获取数据rs.getXxx(参数); }![image]()
案例:

步骤:
-
定义实体类Account
package com.itheima.pojo;public class Account {private int id;private String name;private double money;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';} } -
查询数据,封装到Account对象中
-
将Account对象存入ArrayList集合中
package com.itheima.jdbc;import com.itheima.pojo.Account;
import org.junit.Test;import java.sql.*;
import java.util.ArrayList;
import java.util.List;/*** JDBC API详解:ResultSet*/
public class JDBCDemo5_ResultSet {/*** 执行DQL* @throws Exception*/@Testpublic void testResultSet() throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///itheima?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);//3.定义SQLString sql = "select * from account";//4.获取statement对象Statement stmt = conn.createStatement();//5.执行sqlResultSet rs = stmt.executeQuery(sql);//6.处理结果,遍历rs中所有数据// 6.1光标向下移动一行,并判断该行是否有数据while(rs.next()){//6.2获取数据 getXxx()int id = rs.getInt(1);String name = rs.getString(2);double money = rs.getDouble(3);System.out.println(id);System.out.println(name);System.out.println(money);System.out.println("------------------------");}//7.释放资源rs.close();stmt.close();conn.close();}/*** 查询account账户表数据,封装为Account对象中,并且存储到Arraylist集合中* 1.定义实体类Account* 2.查询数据,封装到Account对象中* 3.将Account对象存入ArrayList集合中* @throws Exception*/@Testpublic void testResultSet2() throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///itheima?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);//3.定义SQLString sql = "select * from account";//4.获取statement对象Statement stmt = conn.createStatement();//5.执行sqlResultSet rs = stmt.executeQuery(sql);//创建集合List<Account> list = new ArrayList<>();//6.处理结果,遍历rs中所有数据// 6.1光标向下移动一行,并判断该行是否有数据while(rs.next()){Account account = new Account();//6.2获取数据 getXxx()int id = rs.getInt(1);String name = rs.getString(2);double money = rs.getDouble(3);//赋值account.setId(id);account.setName(name);account.setMoney(money);// 存入集合list.add(account);}System.out.println(list);//7.释放资源rs.close();stmt.close();conn.close();}}

(5)PreparedStatement
- PrepareStatement作用:
- 预编译SQL语句并执行:预防SQL注入问题
- SQL注入
- SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。

package com.itheima.jdbc;import org.junit.Test;import java.sql.*;/*** 用户登录*/
public class JDBCDemo6_UserLogin {@Testpublic void testLogin() throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///test?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);//接受用户输入的用户名和密码String name = "zhangsan";String pwd = "123";String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";//获取stmt对象Statement stmt = conn.createStatement();//执行sqlResultSet rs = stmt.executeQuery(sql);//判断登录是否成功if(rs.next()){System.out.println("登陆成功");}else {System.out.println("登陆成功");}// 7.释放资源rs.close();stmt.close();conn.close();}@Testpublic void testLogin_inject() throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///test?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);//接受用户输入的用户名和密码String name = "sajdhsad";String pwd = "'or '1' = '1";String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";System.out.println(sql);//获取stmt对象Statement stmt = conn.createStatement();//执行sqlResultSet rs = stmt.executeQuery(sql);//判断登录是否成功if(rs.next()){System.out.println("登陆成功");}else {System.out.println("登陆成功");}// 7.释放资源rs.close();stmt.close();conn.close();}}
第一个测试用例是输入正常的用户名和密码 显示登陆成功
但是第二个测试,用户名和密码并不正确,为何会显示登陆成功呢?
我们通过打印sql语句可以看到:

where条件后 username = 'sajdhsad' and password = ''这个条件为false。'1' = '1'恒等式 为true 则'sajdhsad' and password = ''or '1' = '1'为true 所以也显示登录成功,这就是SQL注入。PreparedStatement这个接口就是为了解决SQL注入的。
如何解决?

@Testpublic void testPreparedStatement() throws Exception {// 1.注册驱动//Class.forName("com.mysql.jdbc.Driver");// 2.获取连接 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,可以简化书写String url = "jdbc:mysql:///test?useSSL=false";String username = "root";String password = "wwh030705";Connection conn = DriverManager.getConnection(url,username,password);//接受用户输入的用户名和密码String name = "zhangsan";String pwd = "'or '1' = '1";//定义sql语句,其中的参数用?来代替String sql = "select * from tb_user where username = ? and password = ? ";//通过Connection对象获取,并传入对应的sql语句PreparedStatement pstmt = conn.prepareStatement(sql);//设置参数pstmt.setString(1,name);pstmt.setString(2,pwd);//执行sqlResultSet rs = pstmt.executeQuery();//判断登录是否成功if(rs.next()){System.out.println("登陆成功");}else {System.out.println("登陆失败");}// 7.释放资源rs.close();pstmt.close();conn.close();}
这样的话则登录失败~ 实质上是将敏感字符进行转移如密码中的单引号进行转义





