JavaWeb01

news/2025/10/28 21:28:01/文章来源:https://www.cnblogs.com/Sunyn-blogs/p/19172767

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.mzph.cn/news/949149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

现代C++编程初体验

##实验任务1 ##代码#pragma once#include <string>// 类T: 声明 class T { // 对象属性、方法 public:T(int x = 0, int y = 0); // 普通构造函数T(const T &t); // 复制构造函数T(T &&t); …

Delphi 利用接口实现frame窗体间的通讯(互动)

需求说明: 程序设计:效果演示:设计思路: FrmCK 只负责发布事件,不关心谁在监听. FrmGrid 只负责响应事件,不关心事件来源. 创建过程: 一.创建接口单元FrmInterface. 全部代码如下:unit FrmInterface;interfaceusessy…

Python冒泡排序:简单易懂的算法实现

在编程的世界里,排序算法是数据处理的基础之一。冒泡排序(Bubble Sort)是一种简单且直观的排序算法,虽然它的效率不是最高的,但它非常适合初学者学习排序算法的基本概念。今天,我们就来详细探讨如何在Python中实…

SAM+ARM

一、首先是图像caption的生成。 输入的图像,被输入进BLIP的图像编码器得到图像嵌入,图像嵌入再经过(BLIP Image-grounded Text Decoder) 得到图像caption。ti表示caption的第i个单词,总共有L个单词。 但是,capti…

《代码大全2》观后感(二):需求分析——代码质量的“源头防线”

《代码大全2》观后感(二):需求分析——代码质量的“源头防线” “为什么明明按需求写的代码,最后还是要推翻重写?”这是我过去常有的困惑,直到读了《代码大全2》中“需求分析”的章节,才找到答案:很多时候,我…

NRF54LM20A 芯片的优点

多达 66 个 GPIO 7 个串行接口(SPI、TWI、UART、HS-SPI) 14 位 ADC、全局 RTC(在系统关闭状态下可用)、TDM、PDM、NFC、PWM、QDEC 等 显著降低的功耗 - 与 nRF52 系列相比,典型蓝牙低功耗应用场景下功耗降低约 30-50% …

零散点小总结(25.10.28)

今天练习了Dp,主要把Dp重新看待了一下,有以下几点Dp其实本质是一种表,用于储存子问题的答案 Dp中其实还有枚举,只是由于子问题被存入表中了,所以减少了时间复杂度 一个搜索其实就是Dp的暴力解,有很多的子问题,但…

Top Tree大学习

前言 \(Top Tree\) 用来解决 路径查询,动态 \(dp\) 等问题。 信息储存在 簇 中。 簇(\(Cluster\)) 树上一个边联通块,可以收缩成一条边,我们成这样的联通子图为 簇。 簇上的某些点与其它簇相接,我们称其为簇的 端…

乱学点东西目录

这里记录了各种各样的奇奇怪怪的算法/思路/数据结构,好玩! 乱学点东西#1 :二进制警报器可以自由转载

CFS任务的负载均衡(load balance)

前言 我们描述CFS任务负载均衡的系列文章一共三篇,第一篇是框架部分,第二篇描述了task placement和active upmigration两个典型的负载均衡场景。本文是第三篇,主要是分析各种负载均衡的触发和具体的均衡逻辑过程。 …

EVE-NG导入华为等镜像的方法

镜像下载Dynamips:思科设备真实IOS镜像,类似GNS3,电脑CPU利用率非常高。 IOL:IOU模拟器的镜像,基本完全支持思科设备二、三层功能。 QEMU:这已经不是镜像文件,而是KVM虚拟机安装操作系统后生成的磁盘文件,通常…

(简记)一类支配点对解决区间查询问题

前言:最近好像见了挺多这种题,记录一下。 支配点对 我们经常遇到树上或区间上关于 \(x,y\in[l,r]\) 一类的区间统计问题,且通常要求区间内点两两任意匹配并统计总贡献,这个贡献不具有简单可加性。我们往往通过找支…

2025 云斗

10/27 Contest 5 A:小分讨+dp C:发现是所有的数和它的倍数有限制,对于值域 \(n\) 这样的限制也只有 \(\sum\limits_{i=1}^n\frac{n}{i}=n\log n\) 个,考虑如何表示这些限制。 考虑对于限制 u,v,若两点都不是对方的…

c++ ranges随笔

ranges c++20引入,在<ranges>头文件中 建立在 std::algo 和 iterator基础上,并做了进一步的抽象集成 与之前相比更加的 安全、简洁、方便 // ranges concept template <typename T> concept range = req…

qoj14458. 调色滤镜

qoj14458. 调色滤镜 平面 \([1,10^9]\times[1,10^9]\) 上有 \(n\) 个点,点 \(i\) 位于 \((x,y)\),有颜色 \(c_i\in [0,9]\)。 有 \(q\) 次操作,每次对平面上一个矩形范围内的点的颜色作用映射 \(f:[0,9]\rightarrow…

第8天(中等题 不定长滑动窗口、哈希表)

打卡第八天 3道中等题滑动窗口相当于在维护一个队列。右指针的移动可以视作入队,左指针的移动可以视作出队。 熟练度+++ 可以十几分钟独立写出相似题了^O^/ 耗时≈一小时 明天继续

P10259 [COCI 2023/2024 #5] Piratski kod

题链 题意 首先,题目写的很抽象,模拟赛时读了半个小时才读懂 题意概括一下就是枚举长度为k的所有01串 然后对01串进行划分,每遇到两个1就进行一次划分 然后把每段提取出来单独处理 如果把提出来的01串计为\(s[1...r]\)…

巧用 using 作用域(IDisposable)的生命周期包装特性 实现前后置处理

需求:在多个方法前后输出日志 logger.Info("begin"); method(); logger.Info("end");如果需要在方法后输出日志同时加上时长 logger.Info("begin"); var sw= Stopwatch.StartNew(); me…

2025.10.27训练记录

其实是10.28晚上写的。感觉就这个题要记录一下。 上午noip模拟。喜提一道不会。 B 题外话: 7:45 开始考试,广附集训爷大吼一声我做过!声称A完全不可做,但B他场切了。于是我开场看B。 那就看B,7:50闭了一下眼睛,睁…

软考复习总结

距离软考还有不到十天,主要对学习的知识点进行总结回顾(以下知识点无顺序重点): 1.对于尾数用补码进行表示时,要注意如果机器位8位,已知补码包含一位符号位,则补码真值的范围(-2n-1,2n-1 - 1), 则将其转换为…