Java基础入门--第十一章--JDBC(Java Database Connection)Java数据库连接

JDBC

  • 11.1 什么是JDBC
    • 11.1.1 JDBC概述
    • 11.1.2 JDBC驱动程序
  • 11.2 JDBC的常用API
  • 11.3 JDBC编程
    • 11.3.1 JDBC 编程步骤
    • 11.3.2 实现第一个JDBC程序

我的MySQL的root密码: root

11.1 什么是JDBC

11.1.1 JDBC概述

JDBC的全称是Java数据库连接(Java Database Connectivity),它是一套用于执行SQL语句的JavaAPI。应用程序可通过这套JavaAPI连接到关系数据库,并使用SQL语句完成对数据库中数据的查询、新增、更新和删除等操作。不同的数据库(如MySQL、Oracle等)处理数据的方式是不同的,如果直接使用数据库厂商提供的访问接口操作数据库,应用程序的可移植性就会变得很差。例如,用户在当前程序中使用的是MySQL提供的接口操作数据库,如果换成Oracle数据库,则需要重新使用Oracle数据库提供的接口,这样代码的改动量会非常大。如果使用JDBC,上述问题就不复存在了,因为JDBC要求各个数据库厂商按照统一的规范提供数据库驱动程序,在程序中由JDBC和具体的数据库驱动程序联系,用户不必直接与底层的数据库交互,使得代码的通用性更强。

11.1.2 JDBC驱动程序

JDBC本身提供的是一套数据库操作标准,而JDBC中提供的这些标准又需要由各个数据库厂商实现,每一个数据库厂商都会为其数据库产品提供一个JDBC驱动程序。目前比较常见的JDBC驱动程序可以分为以下4类。

1.JDBC-ODBC桥驱动程序
JDBC-ODBC桥驱动程序由Sun公司开发,是JDK提供的数据库操作标准API,这种类型的驱动程序实际是把所有JDBC的调用传递给ODBC(Open Database Connectivity,开放数据库连接),再由ODBC调用本地数据库驱动程序代码,操作数据库中的数据。通过JDBC-ODBC桥驱动程序操作数据库的方式如图11-2所示。由于JDBC-ODBC桥驱动程序经过几次中间调用,所以执行效率比较低。
在这里插入图片描述
2.本地API驱动程序
本地API驱动程序直接将JDBCAPI映射成数据库特定的客户端API。这种驱动程序包含特定数据库的本地API,通过它可以访问数据库的客户端。通过本地API驱动程序操作数据库的方式如图11-3所示。通过本地API驱动程序访问数据库减少了ODBC的调用环节,提高了数据库访问的效率。
在这里插入图片描述
3.网络协议驱动程序
网络协议驱动是用纯Java语言编写的。JDBC把对数据库的访问请求传递给网络上的中间件服务器;中间件服务器先把请求转换为数据库通信协议请求,然后再与数据库进行交互。使用这种类型的JDBC驱动程序的Java应用程序可以与服务器端完全分离,具有很大的灵活性。通过网络协议驱动程序操作数据库的方式如图11-4所示。
在这里插入图片描述
4.本地协议驱动程序
本地协议驱动程序是用使用纯Java语言编写的。本地协议驱动程序通常是由数据库厂商直接提供的JAR包。本地协议驱动程序直接将JDBC调用转换为数据库特定的网络通信协议,然后与数据库进行交互。通过本地协议驱动程序操作数据库的方式如图11-5所示。
在这里插入图片描述
在上述4种类型中,JDBC-ODBC桥驱动程序由于执行效率不高,更适合作为开发应用时的一种过渡方案;如果是在内联网(Intranet)中的应用,可以考虑本地API驱动程序;如果是基于互联网(Internet)并且需要同时连接多个不同种类的数据库、并发连接要求高的应用,可以考虑网络协议驱动程序;如果是基于互联网(Internet)但连接单一数据库的应用,可以考虑本地协议驱动程序。本章将基于驱动程序类型对JDBC进行讲解。

11.2 JDBC的常用API

1.Driver接口
Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。需要注意的是,在编写Java应用程序时,必须把使用的数据库驱动程序(这里指MySQL驱动程序的JAR包)或类库加载到项目的classpath中。

2.DriverManager类
使用JDBC连接数据库,需要用到DriverManager类,它用于加载JDBC驱动程序并且创建Java应用程序与数据库的连接。在DriverManager类中,定义了两个重要的静态方法。

方法名称功能描述
registerDriver(Driver driver)该方法用于向DriverManager类注册给定的JDBC驱动程序
getConnection(String url,String user,String password)该方法用于建立和数据库的连接,并返回表示连接的Connection对象

3.Connection接口
DriverManager类的getConnection()方法返回一个Connection对象,它是表示数据库连接的对象,只有获得该对象,才能访问并操作数据库。一个应用程序可与单个数据库建立一个或多个连接,也可以与多个数据库建立连接。

方法声明功能描述
createStatement()用于创建一个Statement对象,该对象可以将SQL语句发送到数据库
prepareStatement(String sql)用于创建一个PreparedStatement对象,该对象可以将参数化的动态SQL语句发送到数据库
prepareCall(String sql)用于创建一个CallableStatement对象以调用数据库的存储过程
isReadOnly()用于查看当前Connection对象的读写模式是否为只读模式
setReadOnly()用于设置当前Connection对象的读写模式,默认为非只读模式
commit()使所有上一次提交/回滚后进行的更改成为持久更改,并释放当前Connection对象持有的所有数据库锁
setAutoCommit(boolean autoCommit)设置是否关闭自动提交模式
roolback()用于取消在当前事务中进行的所有更改,并释放当前Connection对象持有的所有数据库锁
close()用于立即释放当前Connection对象的数据库和JDBC资源,而不是等它们被自动释放
isClose()用于判断当前Connection对象是否已被自动关闭

4.Statement接口Statement接口用于执行静态的SQL语句,并返回一个结果对象。Statement接口对象可以通过Connection实例的createStatement()方法获得,该对象会把静态的SQL语句发送到数据库中编译执行,然后返回数据库的处理结果。Statement接口提供了3个执行SQL语句的常用方法。

方法声明功能描述
execute(String sql)用于执行各种SQL语句。该方法返回一个boolean类型的值,如果返回值为true,表示执行的SQL语句有查询结果,可以通过Statement接口的getResultSet()方法获得查询结果
executeUpdate(String sql)用于执行SQL中的insert、update和delete语句。该方法返回一个int类型的值,表示数据库中受该SQL语句影响的记录条数
executeQuery(String sql)用于执行SQL中的select语句。该方法返回一个表示查询结果的ResultSet对象

5.PreparedStatement接口
Statement接口封装了JDBC执行SQL语句的方法,可以完成Java程序执行SQL语句的操作。然而在实际开发过程中往往需要将程序中的变量作为SQL语句的查询条件,而使用Statement接口操作这些SQL语句过于烦琐,并且存在安全方面的问题。针对这一问题,JDBC API提供了扩展的PreparedStatement接口。PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。PreparedStatement接口扩展了带参数的SQL语句的执行操作,该接口中的SQL语句可以使用占位符“?”代替参数,然后通过setter方法为SQL语句的参数赋值。

方法声明功能描述
executeUpdate()在PreparedStatement对象中执行SQL语句。SQL语句必须是一个DML语句或者是无返回内容的SQL语句(如DDL语句)
executeQuery()在PreparedStatement对象中执行SQL查询。该方法返回的是ResultSet对象
setInt(int Index,int x)将指定位置的参数设置为指定的int类型的值
setFloat(int index,float f)将指定位置的参数设置为float类型的值
setLong(int index,long l)将指定位置的参数设置为long类型的值
setDouble(int index,double d)将指定位置的参数设置为double类型的值
setBoolean(int index,boolean b)将指定位置的参数设置为boolean类型的值
void setString(int Index,String x)将指定位置的参数设置为指定的String类型的值

在表11-4中,DML(数据操纵语言)语句指的是操作数据库、表、列等的语句,使用的关键字为CREATE、ALTER、DROP。DDL(数据定义语言)语句指的是对表中的数据进行增、删、改操作的语句,使用的关键字为INSERT、UPDATE、DELETE。在为SQL语句中的参数赋值时,可以通过输人参数与SQL类型相匹配的setXxx()方法赋值。例如,字段的数据类型为int或Integer,那么可以使用setInt()方法或setObject()方法设置输人参数,具体示例如下:

        String sql="INSERT INTO users(id,name,email) VALUES(?,?,?)";
        Preparedstatement preStmt=conn.prepareStatement(sql);
        preStmt.setInt(1,1);//使用参数与SQL类型相匹配的方法
        preStmt.setString(2,"zhangsan");//使用参数与SQL类型相匹配的方法
        preStmt.setobject(3,"zs@sina.com");//使用setObject()方法设置参数
        preStmt.executeUpdate();

6.ResultSet接口
ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时游标在表格的第一行之前,调用next()方法可以将游标移动到下一行。如果下一行没有数据,则next()方法返回false。在应用程序中经常使用next()方法作为while循环的条件来迭代结果集。

| 方法声明                     | 功能描述                                                     |
| ---------------------------- | ------------------------------------------------------------ |
| getString(int columnIndex)   | 用于获取指定字段的String类型的值,参数columnIndex代表字段的索引 |
| getString(String columnName) | 用于获取指定字段的String类型的值,参数columnName代表字段的名称 |
| getInt(int columnIndex)      | 用于获取指定字段的int类型的值                                |
| getInt(String columnName)    | 用于获取指定字段的int类型的值                                |
| absolute(int row)            | 将游标移动到结果集的第row条记录                              |
| relative(int row)            | 按相对行数(正或负)移动游标                                 |
| previous()                   | 将游标从结果集的当前位置移动到上一行                         |
| next()                       | 将游标从结果集的当前位置移动到下一行                         |
| beforeFirst()                | 将游标移动到结果集的开头(第一行之前)                       |
| isBeforeFirst()              | 判断游标是否位于结果集的开头(第一行之前)                   |
| afterLast()                  | 将游标指针移动到结果集的末尾(最后一行之后)                 |
| isAfterLast()                | 判断游标是否位于结果集的末尾(最后一行之后)                   |
| first()                      | 将游标移动到结果集的第一行                                   |
| isFirst()                    | 判断游标是否位于结果集的第一行                               |
| last()                       | 将游标移动到结果集的最后一行                                 |
| getRow()                     | 返回当前记录的行号                                           |
| getStatement()               | 返回生成结果集的Statement对象                                |
| close()                      | 释放当前结果集的数据库和JDBC资源                             |

11.3 JDBC编程

11.3.1 JDBC 编程步骤

通常情况下,使用JDBCAPI实现JDBC程序时,首先需要加载并注册数据库驱动程序,其次使用DriverManager类调用getConnection()方法获取表示数据连接的Connection对象,最后通过Connection对象调用相应方法获取Statement对象,通过Statement对象执行SQL语句。执行SQL语句之后,如果数据库有返回结果,则将结果封装为ResultSet对象返回。
在这里插入图片描述
1 加载并注册数据库驱动程序
在连接数据库之前,要加载数据库的驱动程序到Java虚拟机。加载数据库驱动程序操作可以通过java.lang.Class类的静态方法forName(StringclassName)或DriverManager类的静态方法registerDriver(Driverdriver)实现,具体示例如下:

DiverManager.registerDiver(Driver Driver)

或者

Class.forName("DriverName");

调用registDriver()方法时,实际上创建了两个Driver对象,对于只需加载驱动程序类来讲有些浪费资源;使用forName()方法,驱动程序类的名称是以字符串的形式填写的,使用时可以把该驱动程序类的名称放到配置文件中,如果需要切换驱动程序类会非常方便。所以在实际开发中,常调用forName()方法注册数据库驱动程序。forName()方法中的参数DriverName表示数据库的驱动程序类。以MySQL数据库为例,MySQL驱动程序类在MySQL6.0.2版本之前是com.mysql.jdbc.Driver,加载示例代码如下:

Class.forName("com.mysql.jdbc.Driver");

而在MySQL6.0.2版本之后,MySQL驱动程序类是com.mysql.cj.jdbc.Driver,加载示例代码如下:

Class.forName("com.mysql.cj.jdbc.Driver");

在实际加载时,用户需要根据数据库版本选择对应的驱动程序类

2 通过DriverManager类获取数据库连接
DriverManager类的getConnection()方法用于获取JDBC驱动程序到数据库的连接,通过DriverManager类获取数据库连接的具体方式如下:

Connection conn = DriverManager.getConnection(String url,String user,String pwd);

从上述代码可以看出,getConnection()方法有3个参数,分别表示连接数据库的URL、登录数据库的用户名和登录数据库的密码。以MySQL数据库为例,数据库地址的书写格式如下:

jdbc:mysql://hostname:port/databasename

在上面的代码中,“jdbc:mysql:”是固定的写法,后面的hostname指的是主机的名称(如果数据库在本机中,hostname可以为localhost或127.0.0.1;如果要连接的数据库在其他计算机中,hostname可以是连接计算机的IP地址),port指的是连接数据库的端口号(MySQL端口号默认为3306),databasename指的是MySQL中相应数据库的名称。

3.通过Connection对象获取Statement对象
获取Connection对象之后,还必须创建Statement对象,将各种SQL语句发送到连接的数据库中执行。如果把Connection对象看作一条连接程序和数据库的索道,那么Statement对象就可以看作索道上的一辆缆车,它为数据库传输SQL语句,并返回执行结果。Connection创建Statement对象的方法有以下3个:
(1)createStatement():创建基本的Statement对象。
(2)prepareStatement():根据传递的SQL语句创建PreparedStatement对象。
(3)prepareCall():根据传人的SQL语句创建CallableStatement对象。
以创建基本的Statement对象为例,创建方式如下:

Statement stmt=conn.createStatement();

4.使用Statement执行SQL语句
创建了Statement对象后,就可以通过该对象执行SQL语句。如果SQL语句运行后产生了结果集,Statement对象会将结果集封装成ResultSet对象并返回。Statement有以下3个执行SQL语句的方法:

  • execute():可以执行任何SQL语句。
  • executeQuery():通常执行查询语句,执行后返回代表结果集的ResultSet对象。
  • executeUpdate():主要用于执行DML语句和DDL语句。执行DML语句(如INSERT、UPDATE或DELETE)返回受SQL语句影响的行数;执行DDL语句返回0。以executeQuery()方法为例,调用形式如下:
//创建SQL语句
String sql="SELECT name from users WHERE id=1";
//执行SQL语句,获取结果集
ResultSet rs=stmt.executeQuery(sql);

需要注意的是,在调用executeQuery()方法和executeUpdate()方法时,如果作为参数的SQL语句有多行(多条SQL语句),将出现编译错误,因此在构造SQL语句时,如果SQL语句有多行,需要将多行SQL语句加上双引号并使用十号连接起来。例如下面的SQL语句:

String sql="INSERT INTO users(NAME,PASSWORD,email,birthday)"
        +VALUES('zhangs','123456','zs@sina.com','1980-12-04');"
        "ResultSetrs=stmt.executeQuery(sgl);

5.操作结果集
如果执行的SQL语句是查询语句,执行结果将封装成一个ResultSet对象,该对象保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象取出查询结果。

6.关闭连接并释放资源
每次操作数据库结束后都要关闭数据库连接并释放资源,以防止系统资源浪费。资源的关闭顺序和声明顺序相反,关闭顺序依次为关闭ResultSet对象、关闭Statement对象、关闭Connection对象。为了保证在异常情况下也能关闭资源,通常在try".catch语句的finally代码块中统一关闭资源。至此,JDBC程序的大致实现步骤已经讲解完成。

11.3.2 实现第一个JDBC程序

(1)搭建数据库环境。在MySQL中创建名称为jdbc的数据库,然后在jdbc数据库中创建users表,创建数据库和表的SQL语句如下:

CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(40),
        password VARCHAR(40),
        email VARCHAR(60),
        birthday DATE
        );

jdbc数据库和users表创建成功后,再向users表中插人3条数据,SQL语句如下:

insert into users(NAME,PASSWORD,email,birthday) values('zhangs','123456','zs@sina.com','1980-12-04'), ('1isi','123456','1isi@sina.com','1981-12-04'),('wangwu','123456','wangwu@sina.com','1979-12-04');

为了查看数据是否添加成功,使用SELECT语句查询users表中的数据,执行结果如图11-7所示。
在这里插入图片描述

(2)创建项目环境,导人数据库驱动程序。在IDEA中新建名称为chapterl1的Java项目,右击项目名称,在弹出的快捷菜单中选择New→Directory命令,在弹出的对话框中将该目录命名为lib,项目根目录中就会出现一个名称为lib的目录。将下载好的MySQL数据库驱动程序文件mysql-connector-java-8.0.15.jar复制到项目的lib目录中,并把JAR包添加到项目里。在IDEA菜单栏中选择File→ProjectStructure→Modules→Dependencies命令,单击最右侧加号后选择第一项:“JARsordirectories"”,在弹出的对话框中选择下载好的JAR包并确认。最后可以看到mysql-connector-java-8.0.15.jar已添加到IDEA的依赖项中。成功添加MySQL的JAR包的界面如图所示。
在这里插入图片描述
将mysql-connector-java-8.0.15.jar添加到依赖项之后,单击Apply按钮,再单击OK按钮,可以看到在ExternalLibraries下已经存在刚刚添加的JAR包。至此,JAR包添加成功。加人数据库驱动程序后的项目结构如图所示。
在这里插入图片描述
(3)编写JDBC程序。在项目chapterl1的src目录下,新建名称为com.itheima.jdbc.example的包,在该包中创建Example01类,该类用于读取数据库中的users表,并将结果输出到控制台。Example01类的实现如文件所示。

import java.sql.*;

public class Example01 {
    public static void main(String[] args) throws Exception {
        Statement stmt = null;
        ResultSet rs = null;
        Connection conn = null;
        try {
            // 1. 注册数据库的驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2.通过DriverManager获取数据库连接
            String url =
                    "jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8&useSSL=false";
            String username = "root";    //数据库用户名
            String password = "root";    //数据库密码
            conn = DriverManager.getConnection(url, username, password);
            // 3.通过Connection对象获取Statement对象
            stmt = conn.createStatement();
            // 4.使用Statement执行SQL语句。
            String sql = "select * from users";
            rs = stmt.executeQuery(sql);
            // 5. 操作ResultSet结果集
            System.out.println("id	|	name	|	password|	email		|	birthday");
            while (rs.next()) {
                int id = rs.getInt("id"); // 通过列名获取指定字段的值
                String name = rs.getString("name");
                String psw = rs.getString("password");
                String email = rs.getString("email");
                Date birthday = rs.getDate("birthday");
                System.out.println(id + "	|	" + name + "	|	" + psw +  "	|	" + email + "	|	" + birthday);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 6.回收数据库资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    }
}

在这里插入图片描述
在文件中,第9行代码通过Class的forName()方法注册了MySQL数据库驱动程序。
第11~16行代码通过DriverManager的getConnection()方法获取数据库的连接。
第18行代码通过Connection对象获取Statement对象。
第20、21行代码调用Statement对象的executeQuery()方法执行SQL查询语句。第23~33行代码使用ResultSet对象操作结果集,并用while循环获取数据库的所有数据。
第38~61行代码依次关闭ResultSet对象、Statement对象和Connection对象并释放资源。
运行结果所示。users表中的数据已输出控制台。至此,第一个JDBC程序成功实现。在实现这个JDBC程序时,有以下3点需要注意。
(1)注册驱动程序。虽然使用DriverManager.registerDriver(newcom.mysql.cj.jdbc.Driver())方法也可以完成注册,但这种方式会使数据库驱动程序被注册两次。因为在Driver类的源码中,已经在静态代码块中完成了数据库驱动程序的注册。为了避免数据库驱动程序被重复注册,在程序中使用Class.forName()方法加载驱动程序类即可。
(2)释放资源。由于数据库资源非常宝贵,数据库允许的并发访问连接数量有限,因此,当数据库资源使用完毕后,一定要释放资源。为了保证资源被释放,在Java程序中应该将释放资源的操作放在finally代码块中。
(3)获取数据库连接。在MySQL8.0及以上版本中获取数据库连接时需要设置时区为北京时间(serverTimezone=GMT%2B8),因为安装数据库时默认为美国时间。如果不设置时区为北京时间,系统会报告MySQL设置时区与当前系统时区不符的错误

更换URL地址

url=jdbc:mysql://127.0.0.1:3306/jdbc?characterEncoding=utf8&useSSL=true

在这里插入图片描述
本章主要讲解了JDBC的基本知识,包括什么是JDBC、JDBC的主要类和接口、JDBC的人门程序。通过本章的学习,读者可以了解什么是JDBC,熟悉JDBC的主要类和接口,掌握如何使用JDBC操作数据库中的数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/533775.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么用核心板与底板模式开发智能产品?小米SU7坐舱域控制器PCB设计的新选择

随着科技的飞速发展,智能产品市场的竞争日益激烈。如何在最短的时间内,以最低的成本,打造出性能卓越的产品,成为了各大企业面临的重要课题。近日,小米SU7智能汽车的发布为我们提供了一个全新的视角——通过核心板与底板…

算法:多重背包问题dp

文章目录 一、多重背包问题特点1.1、多重背包问题的特征1.2、解决多重背包问题的基本方法典型例题:AcWing——多重背包问题I 1.3、二进制优化1.3.1、二进制优化的思想1.3.2、多重背包问题的二进制优化 一、多重背包问题特点 多重背包问题是背包问题的又一变种&…

钢条切割问题:动态规划算法的典型应用

一、引言 在工业生产和物流管理中,钢条切割问题是一个常见的优化问题。企业在购买长钢条并将其切割为短钢条出售时,往往面临着如何切割以最大化利润的问题。这个问题不仅关系到企业的成本控制和利润最大化,也涉及到资源的有效利用和生产效率…

QA:缺少VC运行时库导致VisualBox和XShell运行出错

前言 启动软件时,特别是绿色版软件,有时会遇到“缺少xxx.dll文件”,导致软件启动失败。 注:xxx.dll是动态链接库(DLL)文件,包含了程序运行所需的函数和资源。 内容 象上面这种类型的错误&…

漫画|数据工程师面试常见问题之数据倾斜

话说,闹钟一响,现实照进梦想,又是李大虎面试找工作的一天。 李大虎心里一直有个想法,如果一天睡20个小时,然后这20个小时全做美梦,醒来的4个小时用来吃喝拉撒,这样岂不就和那些富二代一样了&am…

AI应用实战2:使用scikit-learn进行回归任务实战

代码仓库在gitlab,本博客对应于02文件夹。 1.问题分析 在此篇博客中我们来对回归任务进行实战演练,背景是直播带货平台的业绩预测。第一步,就是分析问题。 问题痛点: 在直播带货平台上,由于市场环境多变、用户行为复…

【网站项目】校园二手交易平台小程序

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

Python爬虫网络实践:去哪儿旅游数据爬取指南

Python爬虫网络实践:去哪儿旅游数据爬取指南 在这个博客中,我们将探索如何使用 Python 来进行网络数据抓取,并以抓取旅游数据为例进行演示。我们将通过一个简单的示例来说明如何利用 Python 中的常用库进行网页抓取,从而获取旅游…

ABAP 增强篇

文章目录 ABAP 增强篇第一代增强-基于源码增强用户出口子程序所能使用的数据变量VA01增强示例 第二代:基于函数出口增强(FUNCTION)SMOD与COMD查找出口函数出口对象激活(SMOD)增强详细说明文档示例:通过出口…

vulhub靶场shiro系列漏洞复现CVE-2010-3863、CVE-2016-4437(shiro550)、CVE-2020-1957、shiro721

目录 shiro简介 shiro漏洞成因 shiro550 shiro721 利用过程 CVE-2010-3863(未授权访问) 简介 CVE-2016-4437(shiro550) 简介 CVE-2020-1957(未授权访问) 漏洞影响 简介 url处理过程 shiro721 影响版本 简介 利用 …

2024全国现代流通经济创新大会暨城郊大仓基地高质量建设论坛日程发布

2024年4月19日 中国平谷 建设城郊大仓基地 创新现代流通经济 一、大会开幕式&主论坛 时间:9:00-12:00 地点:博物馆一楼 报告厅 主持人:中国商业联合会商贸物流与供应链分会会长干为 08:30-09:00 大会入场&宣传片视频 09:00-0…

iOS 启动速度优化

启动耗时:点击App后到首帧显示耗费的时间。 阶段分析:premain、postmain,也就是main函数执行前和main函数执行后。 耗时检测:Instrument->App Launch Premain 减少动态库数量:启动时程序会加载动态库,…

Acrobat Pro DC 2021---PDF编辑与管理,打造高效PDF工作流程 含Mac+win

Acrobat Pro DC 2021包括全面的PDF编辑、OCR识别、多种输出格式转换以及强大的文件安全性保护。用户可轻松编辑、合并、转换PDF文件,同时支持将扫描文档转换为可编辑的PDF。可将PDF转换为Word、Excel、PowerPoint等格式,提高工作效率。 Mac电脑&#xf…

vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户

1.后端返回的json数据结构为: {"message":"下载失败,下载文件不存在,请联系管理员处理!","code":500} 2.vue 请求后台接口返回的 Blob数据 3.问题出现的原因是,正常其他数据列表接口&…

2024/4/2—力扣—连续数列

代码实现: 思路:最大子数组和 解法一:动态规划 #define max(a, b) ((a) > (b) ? (a) : (b))int maxSubArray(int* nums, int numsSize) {if (numsSize 0) { // 特殊情况return 0;}int dp[numsSize];dp[0] nums[0];int result dp[0];fo…

阿里云云效CI/CD配置

1.NODEJS项目流水线配置(vue举例) nodejs构建配置 官方教程 注意:下图的dist是vue项目打包目录名称,根据实际名称配置 # input your command here cnpm cache clean --force cnpm install cnpm run build 主机部署配置 rm -rf /home/vipcardmall/frontend/ mkdir -p /home/…

海山数据库(He3DB)原理剖析:浅析OLAP数据库计算引擎中的统计信息

背景: 统计信息在计算引擎的优化器模块中经常被提及,尤其是在基于成本成本优化(CBO)框架中统计信息发挥着至关重要的作用。CBO旨在通过评估执行查询的可能方法,并选择最有效的执行计划来提高查询性能。而统计信息则提…

传统企业如何实现数字化转型?

传统企业实现数字化转型是一个系统性工程,涉及到企业战略、技术应用、组织结构、业务流程、人才培养等多个方面。以下是一些关键步骤和策略: 1、明确转型目标和战略:首先,企业需要明确数字化转型的目标,这通常是为了提…

48-基于腾讯云EKS的容器化部署实战

准备工作 在部署IAM应用之前,我们需要做以下准备工作: 开通腾讯云容器服务镜像仓库。安装并配置Docker。准备一个Kubernetes集群。 开通腾讯云容器服务镜像仓库 在Kubernetes集群中部署IAM应用,需要从镜像仓库下载指定的IAM镜像&#xff…

MES车间管理有哪些方面

一、MES车间管理概述 MES车间管理是以MES系统为基础,对车间生产过程进行全方位、实时性的管理和控制。它涵盖了生产计划、生产调度、物料管理、设备维护、质量控制等多个方面,确保生产过程的顺利进行,提高生产效率和质量。 二、生产计划与调…