Java JDBC详解

news2024/11/26 8:30:51

1、JDBC概念、本质、好处

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

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

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

2、JDBC快速入门

先来看看通过Java操作数据库的流程:
第一步:编写Java代码
第二步:Java代码将SQL发送到MySQL服务端
第三步:MySQL服务端接收到SQL语句并执行该SQL语句
第四步:将SQL语句执行的结果返回给Java代码

编写代码步骤

/**
 * JDBC快速入门
 */
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/db1";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "update account set money = 2000 where id = 1";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //5. 执行sql
        int count = stmt.executeUpdate(sql);//受影响的行数
        //6. 处理结果
        System.out.println(count);
        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

3、JDBC API详解

DriverManager

DriverManager(驱动管理类)作用:
1、注册驱动
在这里插入图片描述
细节:MySQL 5之后的驱动包,可以省略注册驱动的步骤;自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
2、获取数据库连接
在这里插入图片描述
细节:URL(如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对;配置 useSSL=false 参数,禁用安全连接方式,解决警告提示)、user (用户名)、poassword (密码)

Connection

Connection(数据库连接对象)作用:获取执行 SQL 的对象、管理事务

获取执行对象:

  • 普通执行SQL对象

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

    PreparedStatement  prepareStatement(sql)
    

    通过这种方式获取的 PreparedStatement SQL语句执行对象是我们一会重点要进行讲解的,它可以防止SQL注入。

  • 执行存储过程的对象

    CallableStatement prepareCall(sql)
    

    通过这种方式获取的 CallableStatement 执行对象是用来执行存储过程的,而存储过程在MySQL中不常用,所以这个我们将不进行讲解。

事务管理:

先回顾一下MySQL事务管理的操作:

  • 开启事务 : BEGIN; 或者 START TRANSACTION;
  • 提交事务 : COMMIT;
  • 回滚事务 : ROLLBACK;

MySQL默认是自动提交事务

接下来学习JDBC事务管理的方法。

Connection几口中定义了3个对应的方法:

//开启事务
void setAutoCommit(false);//关闭事务自动提交

//提交事务
void commit();

//回滚事务
void rollback();

代码演示:

/**
 * JDBC API 详解:Connection
 */
public class JDBCDemo3_Connection {

    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql1 = "update account set money = 3000 where id = 1";
        String sql2 = "update account set money = 3000 where id = 2";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();

        try {
            // ============开启事务==========
            conn.setAutoCommit(false);
            //5. 执行sql
            int count1 = stmt.executeUpdate(sql1);//受影响的行数
            //6. 处理结果
            System.out.println(count1);
            int i = 3/0;
            //5. 执行sql
            int count2 = stmt.executeUpdate(sql2);//受影响的行数
            //6. 处理结果
            System.out.println(count2);

            // ============提交事务==========
            //程序运行到此处,说明没有出现任何问题,则需求提交事务
            conn.commit();
        } catch (Exception e) {
            // ============回滚事务==========
            //程序在出现异常时会执行到这个地方,此时就需要回滚事务
            conn.rollback();
            e.printStackTrace();
        }

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

Statement

Statement对象的作用就是用来执行SQL语句。而针对不同类型的SQL语句使用的方法也不一样。

执行DDL、DML语句
在这里插入图片描述

执行DQL语句
在这里插入图片描述

ResultSet

作用:封装了SQL查询语句的结果

那么我们就需要从 ResultSet 对象中获取我们想要的数据。ResultSet 对象提供了操作查询结果数据的方法,如下:

boolean next()

  • 将光标从当前位置向前移动一行
  • 判断当前行是否为有效行

方法返回值说明:

  • true : 有效行,当前行有数据
  • false : 无效行,当前行没有数据

xxx getXxx(参数):获取数据

  • xxx : 数据类型;如: int getInt(参数) ;String getString(参数)
  • 参数
    • int类型的参数:列的编号,从1开始
    • String类型的参数: 列的名称

代码演示:

/**
  * 执行DQL
  * @throws Exception
  */
@Test
public void testResultSet() throws  Exception {
    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");
    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    Connection conn = DriverManager.getConnection(url, username, password);
    //3. 定义sql
    String sql = "select * from account";
    //4. 获取statement对象
    Statement stmt = conn.createStatement();
    //5. 执行sql
    ResultSet 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("--------------");

        }*/
    // 6.1 光标向下移动一行,并且判断当前行是否有数据
    while (rs.next()){
        //6.2 获取数据  getXxx()
        int id = rs.getInt("id");
        String name = rs.getString("name");
        double money = rs.getDouble("money");

        System.out.println(id);
        System.out.println(name);
        System.out.println(money);

        System.out.println("--------------");
    }

    //7. 释放资源
    rs.close();
    stmt.close();
    conn.close();
}

PreparedStatement

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

  • 获取 PreparedStatement 对象
// SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
// 通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
  • 设置参数值
    上面的sql语句中参数使用 ? 进行占位,在之前之前肯定要设置这些 ? 的值。

PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值
Xxx:数据类型 ; 如 setInt (参数1,参数2)
参数:
参数1: ?的位置编号,从1 开始
参数2: ?的值

  • 执行SQL语句

executeUpdate(); 执行DDL语句和DML语句
executeQuery(); 执行DQL语句
注意:
调用这两个方法时不需要传递SQL语句,因为获取SQL语句执行对象时已经对SQL语句进行预编译了。

代码演示:

 @Test
public void testPreparedStatement() throws  Exception {
    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    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 = ?";
    // 获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);
    // 设置?的值
    pstmt.setString(1,name);
    pstmt.setString(2,pwd);
    // 执行sql
    ResultSet rs = pstmt.executeQuery();
    // 判断登录是否成功
    if(rs.next()){
        System.out.println("登录成功~");
    }else{
        System.out.println("登录失败~");
    }
    //7. 释放资源
    rs.close();
    pstmt.close();
    conn.close();
}

执行上面语句就可以发现不会出现SQL注入漏洞问题了。那么PreparedStatement又是如何解决的呢?它是将特殊字符进行了转义,转义的SQL如下:

select * from tb_user where username = 'sjdljfld' and password = '\'or \'1\' = \'1'

4、数据库连接池

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏

    好处:
  • 资源重用
  • 提升系统响应速度
  • 避免数据库连接遗漏

数据库连接池实现

  • 标准接口:DataSource
Connection getConnection()

那么以后就不需要通过 DriverManager 对象获取 Connection 对象,而是通过连接池(DataSource)获取 Connection 对象。

  • 常见的数据库连接池
    DBCP
    C3P0
    Druid(我们现在使用更多的是Druid,它的性能比其他两个会好一些)

Driud使用

  • 导入jar包 druid-1.1.12.jar
  • 定义配置文件
  • 加载配置文件
  • 获取数据库连接池对象
  • 获取连接

编写配置文件如下:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=1234
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000

使用druid的代码如下:

/**
 * Druid数据库连接池演示
 */
public class DruidDemo {

    public static void main(String[] args) throws Exception {
        //1.导入jar包
        //2.定义配置文件
        //3. 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
        //4. 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        //5. 获取数据库连接 Connection
        Connection connection = dataSource.getConnection();
        System.out.println(connection); //获取到了连接后就可以继续做其他操作了

        //System.out.println(System.getProperty("user.dir"));
    }
}

c3p0使用

第一步:添加jar包

  • c3p0-0.9.1.2.jar
  • mysql-connector-java-5.0.8-bin.jar

第二步:在src下创建C3P0的配置文件c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
  <default-config>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb</property>
    <property name="user">root</property>
    <property name="password">root</property>
    <property name="initialPoolSize">15</property>
    <property name="maxIdleTime">40</property>
    <property name="maxPoolSize">150</property>
    <property name="minPoolSize">20</property>
  </default-config>
</c3p0-config>

第三步:编写操作C3P0的工具类C3P0Util

package com.liming.util;


import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class C3p0Util {
    //创建数据库连接池
    private static DataSource dataSource = new ComboPooledDataSource();

    //创建连接
    public static Connection getConnection() {
        try{
            return dataSource.getConnection();
        }catch (SQLException e){
            throw new RuntimeException("获取数据库失败");
        }
    }

    //关闭数据库连接释放资源
    public static void release(Connection connection, Statement statement, ResultSet resultSet) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

第四步:使用C3P0
(1)、在数据库中建立学生表并插入数据(略)
(2)、编写JavaBean即Student(略)
(3)、在JDBC中使用C3P0

package cn.com.demo8;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestC3P0 {
	public static void main(String[] args) {
		TestC3P0 demo = new TestC3P0();
		demo.testC3P0();
	}

	public void testC3P0() {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		try {
			connection = C3P0Util.getConnection();
			preparedStatement = connection.prepareStatement("SELECT * FROM student");
			resultSet = preparedStatement.executeQuery();
			while (resultSet.next()) {
				Student student = new Student();
				int id = resultSet.getInt("studentid");
				String name = resultSet.getString("studentname");
				student.setStudentID(id);
				student.setStudentName(name);
				System.out.println(student);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			C3P0Util.release(connection, preparedStatement, resultSet);
		}
	}
}

5、DbUtils框架

为更加简单且高效地使用JDBC,Apache组织提供了数据库操作工具类commons-dbutils,该工具可以自动完成:创建连接、封装结果、释放资源。DbUtils对JDBC进行了封装,可极大地简化JDBC的编码工作量。

DbUtils操作简单,功能强大;其中,它的大部分功能都由以下三大核心实现:

  • DbUtils工具类
    该类主要用于关闭连接、装载JDBC驱动程序等等

  • ResultSetHandler接口
    该接口及其实现类主要用于处理结果集

  • QueryRunner类
    该类主要用于增,删,改,查

DbUtils工具类

public static void closeQuietly(Connection conn,Statement stmt, ResultSet rs):

该类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception

ResultSetHandler接口

BeanHandler
将结果集中的第一行数据封装到一个对应的JavaBean实例中。

BeanListHandler
将结果集中的每一行数据都封装到一个对应的JavaBean实例中,再存放到List里

QueryRunner类

我们先来瞅瞅QueryRunner常用的构造函数:

QueryRunner(DataSource ds):采用该方法创建QueryRunner时数据库的事务由DBUtils自动控制。正因为该构造方法传入了参数DataSource,所以在调用该对象的query、update、等方法时无需传入参数Connection。

利用QueryRunner的有参构造函数即QueryRunner(DataSource ds )创建QueryRunner执行数据库操作后不需要手动关闭数据库连接Connection;DbUtils框架会自动释放数据库连接Connection.

QueryRunner的常用方法:

public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException 
public int update(Connection conn, String sql, Object[] params) throws SQLException 

public int update(Connection conn, String sql) throws SQLException 

public int update(String sql) throws SQLException 

DbUtils简易封装

在实际开发中,我们通常将DbUtils的获取连接、释放资源等操作封装在工具类中以简化操作。

package com.liming.util;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.DbUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * DbUtils工具类
 */
public class DBUtils {
    //创建数据库连接池
    private static DataSource dataSource = new ComboPooledDataSource();

    //获取数据库连接池
    public static DataSource getDataSource(){
        return dataSource;
    }

    //创建连接
    public static Connection getConnection(){
        try{
            return dataSource.getConnection();
        }catch (SQLException e){
            throw new RuntimeException("获取数据库连接失败");
        }
    }

    //释放连接
    public static void releaseConnection(Connection connection, Statement statement, ResultSet resultSet){
        DbUtils.closeQuietly(connection,statement,resultSet);
    }
}

DbUtils使用示例

(1)、在数据库中建立会员卡表并插入数据

代码如下:

-- 若存在数据库mydb则删除
DROP DATABASE IF EXISTS mydb;
-- 创建数据库mydb
CREATE DATABASE mydb;
-- 选择数据库mydb
USE mydb;

-- 创建表
CREATE TABLE membershipcard (
    id int primary key auto_increment, 
    username varchar(40),
    password varchar(40), 
    email varchar(40), 
    birthday date 
);

-- 插入数据
INSERT INTO membershipcard (username,password,email,birthday) VALUES ("lili","abc123","lili@sina.com","1999-08-14");
INSERT INTO membershipcard (username,password,email,birthday) VALUES ("koko","efg456","koko@sohu.com","1998-07-15");
INSERT INTO membershipcard (username,password,email,birthday) VALUES ("mbmb","mnb333","mbmb@sina.com","1997-06-16");
INSERT INTO membershipcard (username,password,email,birthday) VALUES ("zxzx","poi666","zxzx@sohu.com","1996-05-17");

(2)、编写JavaBean即MembershipCard(略)

(3)、利用DbUtils实现增删改查

package com.liming.dao;

import com.liming.pojo.MembershipCard;
import com.liming.util.DBUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.Date;
import java.util.List;

/**
 * 利用DbUtils实现增删改查
 */
public class DButilsDao {
    public static void main(String[] args) throws Exception {
        testInsert();
        testDelete();
        testUpdate();
        testSelect();
        testselectAll();
    }

    /**
     * 增加数据
     */
    public static void testInsert() throws Exception{
        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());
        String sql = "insert into membershipcard(username,password,email,birthday) " +
                "values (?,?,?,?)";
        Date birthday = Date.valueOf("1997-07-01");
        Object[] params = {"huhu","asd777","huhu@qq.com",birthday};
        int num = qr.update(sql, params);
        if (num > 0){
            System.out.println("添加成功");
        }else {
            System.out.println("添加失败");
        }
    }

    /**
     * 删除数据
     */
    public static void testDelete() throws Exception{
        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());
        String sql = "delete from membershipcard where username=?";
        Object[] params = {"huhu"};
        int num = qr.update(sql, params);
        if (num > 0){
            System.out.println("删除成功");
        }else {
            System.out.println("删除失败");
        }
    }

    /**
     * 修改数据
     */
    public static void testUpdate() throws Exception{
        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());
        String sql = "update membershipcard set password=? where username=?";
        Object[] params = {"www888","huhu"};
        int num = qr.update(sql, params);
        if (num > 0){
            System.out.println("修改成功");
        }else {
            System.out.println("修改失败");
        }
    }

    /**
     * 查询单条数据
     */
    public static void testSelect() throws Exception{
        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());
        String sql = "select * from membershipcard where username=?";
        Object[] params = {"lili1"};
        BeanHandler<MembershipCard> beanHandler = new BeanHandler<>(MembershipCard.class);
        MembershipCard query = qr.query(sql, beanHandler, params);
        if (query != null){
            System.out.println(query);
        }else {
            System.out.println("数据不存在");
        }
    }

    /**
     * 查询所有数据
     */
    public static void testselectAll() throws Exception{
        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());
        String sql = "select * from membershipcard";
        BeanListHandler<MembershipCard> listHandler = new BeanListHandler<>(MembershipCard.class);
        List<MembershipCard> query = qr.query(sql, listHandler);
        for (MembershipCard m : query) {
            System.out.println(m);
        }
    }
}

示例总结

在该示例中利用DbUtils实现了增删改查操作。其中,我们可利用BeanHandler将查询到的一条数据转换成与其对应的JavaBean;类似地,我们可利用BeanListHandler将查询到的多条数据转换为JavaBean再存放至List集合。

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

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

相关文章

展现AI与自动化测试技术之间的神奇化学反应

目录 零&#xff1a;前言 一、介绍 1.1、什么是自动化测试技术 1.2、痛点 1.3、几款优秀的自动化测试工具介绍 1.3.1、Selenium 1.3.2、龙测AI-TestOps云平台 1.3.3、TestCafe 二、实操 2.1、主要功能模块介绍 2.2、实战演练 2.2.1、创建web项目 2.2.2、录制流程图…

Taro3.x 容易踩坑的点(阻止滚动穿透,弹框蒙层父级定位)

解决弹框滚动的时候&#xff0c;下层也会滚动问题》阻止滚动穿透(react,vue)案例描述&#xff1a;页面展示时需要滚动条才可以显示完整&#xff0c;但是当我们显示弹框的时候&#xff0c;即使不需要滚动条&#xff0c;但是页面仍然可以滚动&#xff0c;并且下层内容会随着滚动变…

MES助力灯具照明行业从制造到”智造”

现如今&#xff0c;LED照明行业产品更新换代太快&#xff0c;一个产品一两年不更新一下外观、材料&#xff0c;就会被对手超越。这直接导致LED产品标准化程度不够高&#xff0c;LED下游制造类厂家智能化生产程度普遍偏低。 加之大多属于劳动密集型产业&#xff0c;传统的依靠买…

Hive分区表与分桶表的使用具体说明

目录 一、分区表 (一)分区表基本语法 1.创建分区表 2.往分区表中写入数据的两种方法 (1)load装载本地数据 (2)insert...select...(常用) 3.读取分区表数据 4. Hive分区表的存储路径规划&#xff1a;分区字段分区值 5.分区表基本操作 (1)查看所有分区信息 (2)新增分区…

C#使用MQTT通信 .Net实现MQTT通信 java使用MQTT通信 java实现MQTT通信

MQTT是一种轻量级、基于发布/订阅模式的通信协议&#xff0c;通常用于物联网设备间的通信。MQTT协议采用简单的二进制消息格式&#xff0c;能够在不占用过多网络带宽的情况下进行高效的通信。以下是使用MQTT进行通信的一些基本概念&#xff1a;BrokerMQTT通信中的中间件&#x…

机器学习算法: AdaBoost 详解

1. 集成学习概述 1.1. 定义 集成学习&#xff08;Ensemble learning&#xff09;就是将若干个弱分类器通过一定的策略组合之后产生一个强分类器。 弱分类器&#xff08;Weak Classifier&#xff09;指的就是那些分类准确率只比随机猜测略好一点的分类器&#xff0c;而强分类器&…

住宅防雷接地的选择要求和施工方法

在您家的布线系统中&#xff0c;防雷接地系统是一项至关重要的安全功能。如果系统发生某种故障&#xff0c;接地系统提供电阻最小的路径&#xff0c;确保电流安全地流回大地本身。因此&#xff0c;它减少了短路导致火灾或危及生命的电击的可能性。家庭接地系统的最后一个也是最…

成都的Java培训机构有哪些?

强烈自荐 二十三年教学实力积累 "课工场是专注互联网教育的生态平台&#xff0c;汇聚中国和北美数百位来自互联网企业的行业大咖&#xff0c;向寻求技术提升和想进入IT行业的人群提供直播、录播、线下面授等多模式教学服务&#xff0c;并通过全国线下服务中心提供更加成熟…

【JVM】内存结构

【JVM】内存结构 文章目录【JVM】内存结构1. 程序计数器1.1 定义1.2 作用2. 虚拟机栈2.1 定义2.2 栈内存溢出2.3 线程运行诊断3. 本地方法栈4. 堆4.1 定义4.2 堆内存溢出4.3 堆内存诊断5. 方法区5.1 定义5.2 组成5.3 方法区内存溢出5.4 运行时常量池5.5 StringTable特性1. 程序…

Hadoop集群模式安装(Cluster mode)

1、Hadoop源码编译 安装包、源码包下载地址 Index of /dist/hadoop/common/hadoop-3.3.0为什么要重新编译Hadoop源码? 匹配不同操作系统本地库环境&#xff0c;Hadoop某些操作比如压缩、IO需要调用系统本地库&#xff08;*.so|*.dll&#xff09; 修改源码、重构源码 如何…

电子墨水屏的应用场景

电子纸挺好个东西&#xff0c;大家都把注意力集中在商超场景&#xff0c;其实还有更多有趣的场景方案可用&#xff0c;价值也不小&#xff0c;比如&#xff1a; 仓库场景&#xff1a;通过亮灯拣选&#xff0c;提高仓库作业效率。 仓库循环使用标签&#xff1a;做NFC类发卡式应…

CnOpenData专精特新“小巨人”企业工商注册基本信息数据

一、数据简介 “专精特新”一词最早来源于2011年7月&#xff0c;由时任工信部总工程师朱宏任在《中国产业发展和产业政策报告&#xff08;2011&#xff09;》新闻发布会上首次提出。“专精特新”是指具备专业化、精细化、特色化、创新型四大优势的企业。根据工信部的定义&#…

content-type几种常见类型区别

Content-Type叫做MIME&#xff08;mediaType&#xff09;类型,使用Content-Type来表示请求和响应中的媒体类型信息。如果是请求头&#xff0c;它用来告诉服务端如何处理请求的数据&#xff0c;如果是响应头&#xff0c;它用来告诉客户端&#xff08;一般是浏览器&#xff09;如…

numpy的常见数据类型

常见数据类型介绍Python 原生的数据类型相对较少&#xff0c; bool、int、float、str等。这在不需要关心数据在计算机中表示的所有方式的应用中是方便的。然而&#xff0c;对于科学计算&#xff0c;通常需要更多的控制。为了加以区分 numpy 在这些类型名称末尾都加了“_”。类型…

【ESP32+freeRTOS学习笔记-(九)事件组】

目录1、概述2、事件组的特性2.1 事件组、事件标志和事件位2.2 事件组位长的设置2.3 多任务访问3、使用事件组管理事件3.1 xEventGroupCreate()3.2 xEventGroupSetBits()3.3 xEventGroupGetBits()3.4 xEventGroupWaitBits()3.5 示例4、使用事件组同步任务4.1 xEventGroupSync()4…

MobaXterm安装与使用

MobaXterm安装与使用 我们首先进入MobaXterm官网&#xff0c;其提供了收费版和免费版&#xff0c;我们使用免费版即可 随后便是安装过程了&#xff0c;很简单。解压后运行该文件一路next即可。 安装完成后我们便可以使用了点击session 选择SSH连接方式&#xff0c;输入服务器…

vue项目——获取指定日期是周几和第几周的信息——表格展示

最近在写后台管理系统&#xff0c;遇到以下的要求&#xff0c;就是要展示 年月日和周几和第几周的情况。 下面记录一下用到的函数&#xff1a; 1.跟据日期获取第几周 //根据日期获取第几周 getWeek(dateTime) {let temptTime new Date(dateTime);//周几let weekday temptT…

浏览器用一行JS代码导出cookies.txt,Python的requests库导入cookies格式化为字典格式

在Python进行爬虫时&#xff0c;如果仅使用requests库打开某个网页&#xff0c;requests的session.cookies保存的cookies信息少得可怜&#xff0c;有时cookies甚至是空白&#xff01;但浏览器里打开同一个网页&#xff0c;cookies信息非常详尽&#xff0c;比如浏览器的cookies保…

2023-02-22 学习记录--TS-邂逅TS(二)

TS-邂逅TS&#xff08;二&#xff09; 不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。&#x1f4aa;&#x1f3fb; 一、接口&#xff08;interface&#xff09; 在 ts 中&#xff0c;子类只能继承一个父类&#xff0c;不可多继承&#xff0c;但是…

2020蓝桥杯真题单词分析 C语言/C++

题目描述 小蓝正在学习一门神奇的语言&#xff0c;这门语言中的单词都是由小写英文字母组 成&#xff0c;有些单词很长&#xff0c;远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词&#xff0c;他准备不再完全记忆这些单词&#xff0c;而是根据单词中哪个字母出…