当前位置: 首页 > news >正文

JavaWeb01

1.JavaWeb介绍

什么是JavaWeb?

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

image

  1. 网页:展现数据
  2. 数据库:存储和管理数据
  3. JavaWeb程序:逻辑处理

数据库已学习

2.JDBC

  • JDBC就是使用Java语言操作关系型数据库的一套API

image

2.1、JDBC简介

JDBC概念

  • JDBC就是使用Java语言操作关系型数据库的一套API
  • 全称:(Java DataBase Connectivity)Java数据库连接

JDBC本质:

  • 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
  • 各个数据库厂商去实现这套接口,提供数据库驱动jar包
  • 我们可以使用这套接口(JDBC)编程,真正执行代码的是驱动jar包中的实现类

JDBC的好处:

  • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
  • 可随时替换底层数据库,访问数据库的Java代码基本不变

image

2.2、JDBC快速入门

步骤:

  1. 创建工程,导入驱动jar包

    image

  2. 注册驱动

    Class.forName("com.mysql.jdbc.Driver");
    
  3. 获取连接

    Connection conn = DriverManager.getConnection(url,username,password);
    
  4. 定义SQL语句

    String sql = "update..."
    
  5. 获取执行SQL对象

    Statement stmt = conn.createStatement();
    
  6. 执行SQL

    stmt.executeUpdate(sql);
    
  7. 处理返回结果

  8. 释放资源

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();}
}

image

2.3、JDBC API详解

(1)DriverManager

  • DriverManager(驱动管理类)作用:

    1. 注册驱动

      Class.forName("com.mysql.jdbc.Driver");
      
      • 查看Driver类源码

        image

        提示:

        • MySQL 5之后的驱动包,可以省略注册驱动的步骤
        • 自动加载jar包中的META-INF/services/java.sql.Driver文件中的驱动类
    2. 获取数据库连接

      image

      • 参数

        1. url:连接路径

          语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
          示例:jdbc:mysql://127.0.0.1:3306/itheima
          细节:
          1.如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对
          2.配置 useSSL = false参数,禁用安全连接方式,解决警告问题
          
        2. user:用户名

        3. 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

  1. 获取执行SQL的对象

    • 普通执行SQL对象

      Statement createStatement()
      
    • 预编译SQL的执行SQL对象:防止SQL注入

      PreparedStatement prepareStatement(sql)
      
    • 执行存储过程的对象

      CallableStatement prepareCall(sql)
      
  2. 事务管理

    • 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作用:

    1. 执行SQL语句
  • 执行SQL语句

    int executeUpdate(sql):执行DML、DDL语句返回值:(1)DML语句影响的行数(2)DDL语句执行后,执行成功也可能返回0
    
    ResultSet 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(结果集对象)作用:

    1. 封装了DQL查询语句的结果
    ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象
    
  • 获取查询结果

    boolean next():
    (1)将光标从当前位置向下移动一行 
    (2)判断当前行是否为有效行返回值:true:有效行,当前行有数据false:无效行,当前行没有数据
    
    xxx getXxx(参数):获取数据xxx:数据类型;如:int getInt(参数);String getString(参数)参数:int:列的编号,从1开始String:列的名称
    
  • 使用步骤

    1. 游标向下移动一行,并判断该行是否有数据:next()
    2. 获取数据:getXxx(参数)
    //循环判断游标是否是最后一行末尾
    while(rs.next()){//获取数据rs.getXxx(参数);
    }
    

    image

案例:

image

步骤:

  1. 定义实体类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 +'}';}
    }
  2. 查询数据,封装到Account对象中

  3. 将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();}}

image

(5)PreparedStatement

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

image

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语句可以看到:

image

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

如何解决?

image

@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();}

这样的话则登录失败~ 实质上是将敏感字符进行转移如密码中的单引号进行转义

image

http://www.jsqmd.com/news/24965/

相关文章:

  • 现代C++编程初体验
  • Delphi 利用接口实现frame窗体间的通讯(互动)
  • NRF54LM20A 芯片的优点
  • 零散点小总结(25.10.28)
  • Top Tree大学习
  • 乱学点东西目录
  • CFS任务的负载均衡(load balance)
  • EVE-NG导入华为等镜像的方法
  • (简记)一类支配点对解决区间查询问题
  • 2025 云斗
  • c++ ranges随笔
  • qoj14458. 调色滤镜
  • 第8天(中等题 不定长滑动窗口、哈希表)
  • P10259 [COCI 2023/2024 #5] Piratski kod
  • 巧用 using 作用域(IDisposable)的生命周期包装特性 实现前后置处理
  • 2025.10.27训练记录
  • 软考复习总结
  • ? #6
  • 鲜花:不会说明你有抑郁症3
  • 算法竞赛知识点速通手册
  • ROS1 go2 vlp16 局部避障--3 篇 - 教程
  • 25.10.28随笔NOIP模拟赛总结
  • 第二十八篇
  • P8269 [USACO22OPEN] Visits S
  • Luogu P13925 [POKATT 2024] 联合猫国 / The Paw-litical Game 题解 [ 蓝 ] [ 线性 DP ] [ 种类数观察 ]
  • 深入解析:【STM32项目开源】基于STM32的独居老人监护系统
  • CSP-S 41多校 9
  • 【25.10.28】模拟赛
  • CSP-S模拟41
  • Linux双中文编码笔记