JavaWeb01-JDBC、Druid连接池

目录

一、JDBC

1.概述

2.本质

3.好处

4.使用步骤

5.JDBC_API

(1)DriverManager(驱动管理类)

(2)Connection(数据库连接对象)

(3)Statement

(4)ResultSet(结果集对象)

(5)PreparedStatement

6.使用

(1)快速上手

(2)ResultSet使用

(3)SQL注入模拟及解决

(4)perparedStatement使用

7.关于测试类无法使用Scanner的问题解决

二、数据库连接池

1.概述

2.数据库连接池的实现

(1)标准接口:DataSource

(1)常见的数据库连接池

3.Druid数据库连接池的使用

三、综合练习

1.创建表:

2.添加数据:表中数据增

3.表中数据的删、改、查

(1)查(需要啥写啥)+存

(2)改

(3)删除


一、JDBC

1.概述

  • 全称 Java DataBase Connectivity

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

2.本质

  • 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口

  • 各个数据库厂商去实现这套接口,提供数据库驱动jar包

  • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动iar包中的实现类

3.好处

  • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发

  • 可随时替换底层数据库,访问数据库的Java代码基本不变

4.使用步骤

  • 导入对应的驱动jar包

  • 注册驱动,(mysql驱动包在v5及之后的版本,该步骤可省略)

  • 获取连接

  • 定义SQL语句

  • 获取执行SQL对象

  • 执行SQL

  • 返回结果

  • 释放资源

5.JDBC_API

(1)DriverManager(驱动管理类)

主要作用:

  • 注册驱动

  • 获取数据库连接

(2)Connection(数据库连接对象)

主要作用:

  • 获取执行SQL的对象

  • 管理事务

    • JDBC事务管理:Connection接口中定义了3个对应的方法

    • 开启事务: setAutoCommit(boolean autoCommit): true为自动提交事务; false为手动提交事务,即为开启事务

    • 提交事务commit()

    • 回滚事务: rollback()

主要方法:

  • 执行SQL对象(普通)

方法名
Statement createStatement(sql);
  • 执行SQL对象(预编译SQL):防止SQL注入

方法名
PreparedStatement prepareStatement(sql);
  • 执行存储过程的对象

方法名
CallableStatement prepareCall (sql)
(3)Statement

主要作用

  • 执行SQL语句

方法名说明
int executeUpdate(sql);执行DML、DDL语句 返回值为DML语句影响的行数 DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql);执行DQL语句 返回值为ResultSet结果集对象

(4)ResultSet(结果集对象)

主要作用:

  • 获取查询结果

主要方法

方法名说明
boolean next()将光标从当前位置向前移动一行 判断当前行是否为有效行(有数据)
XXX【数据类型】 getXxx(参数)获取数据 参数: int:列的编号,从1开始 String:列的名称 更多参数看jdk帮助文档

使用:

while(rs.next()){//获取数据rs.getXxx(参数);
}

(5)PreparedStatement

主要作用:

  • 预编译SQL并执行

  • 防止SQL注入

SQL注入:

SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。

好处:

  • 预编译SQL,性能更高

  • 防止SQL注入:将敏感字符进行转义

注意:

  • 默认只是防止SQL注入,并没有预编译SQL提高性能

  • PreparedStatement的预编译功能默认是关闭的,需要在url后架上useServerPrepStmts=true,才会开启

6.使用

(1)快速上手
import java.sql.*;
​
public class Demo01 {public static void main(String[] args) throws Exception {String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";String username = "root";String password = "root";//1.注册驱动,mysql5版本及之后的版本该步骤可以省略registrationDriver();//2.获取数据库连接Connection connection = getConnection(url, username, password);//3.定义SQL语句String sql = "sqls";//4.获取执行SQL的对象Statement statement = connection.prepareStatement(sql);/*开启事务*/connection.setAutoCommit(false);
​try {//5.执行sql,根据方法会返回不同类型的值,详细可查看JDK帮助文档了解boolean execute = statement.execute(sql);//验证SQL语句是否执行成功System.out.println(execute);} catch (SQLException throwables) {throwables.printStackTrace();/*出现异常就回滚事务*/connection.rollback();}
​/*提交事务*/connection.commit();
​//6.释放资源statement.close();connection.close();
​}
​/*** 获取数据库连接* @param url:数据库连接,*           格式:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...*           如果连接的是本机服务器,且端口号为默认,可简写为:jdbc:mysql///数据库名称?参数键值对*           由于没有禁用安全连接方式,会输出警告提示,将参数配置设置为 useSSL = false 即可* @param username:数据库用户名* @param password:数据库密码* @return 连接对象* @throws SQLException: SQLException异常*/private static Connection getConnection(String url, String username, String password) throws SQLException {return DriverManager.getConnection(url, username, password);}
​private static void registrationDriver() throws ClassNotFoundException {Class.forName("com.mysql.jdbc.Driver");}
}

(2)ResultSet使用

查询user表中数据,并根据其数据创建User对象,再将所有的User对象存储到arraysList集合中

实体类User:

public class User {private Long id;private String userName;private String password;private String gmtCreate;private String gmtModified;
​public User() {}
​public User(Long id, String userName, String password, String gmtCreate, String gmtModified) {this.id = id;this.userName = userName;this.password = password;this.gmtCreate = gmtCreate;this.gmtModified = gmtModified;}
​public Long getId() {return id;}
​public void setId(Long id) {this.id = id;}
​public String getUserName() {return userName;}
​public void setUserName(String userName) {this.userName = userName;}
​public String getPassword() {return password;}
​public void setPassword(String password) {this.password = password;}
​public String getGmtCreate() {return gmtCreate;}
​public void setGmtCreate(String gmtCreate) {this.gmtCreate = gmtCreate;}
​public String getGmtModified() {return gmtModified;}
​public void setGmtModified(String gmtModified) {this.gmtModified = gmtModified;}
​@Overridepublic String toString() {return "User{" +"id=" + id +", userName='" + userName + '\'' +", password='" + password + '\'' +", gmtCreate='" + gmtCreate + '\'' +", gmtModified='" + gmtModified + '\'' +'}';}
}

测试

public class TestDemo {String url = "jdbc:mysql:///test?useSSL=false";String userName = "root";String password = "root";@Testpublic void Demo01 () throws Exception {Connection connection = DriverManager.getConnection(url, userName, password);
​String sql = "select * from users";
​Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);
​ArrayList<User> arrayList = new ArrayList<>();while (resultSet.next()){
​User user = new User(resultSet.getLong("id"),resultSet.getString("user_name"),resultSet.getString("password"),resultSet.getString("gmt_create"),resultSet.getString("gmt_modified"));arrayList.add(user);}resultSet.close();statement.close();connection.close();
​arrayList.forEach(user -> System.out.println(user));}
}

(3)SQL注入模拟及解决

模拟登录:sql注入

@Testpublic void sout() throws Exception {Scanner scanner = new Scanner(System.in);System.out.println("请输入用户名");String username = scanner.nextLine();System.out.println("请输入密码");String password = "' or 'a' = 'a";
​Connection connection = DriverManager.getConnection(TestDemo.this.url,TestDemo.this.userName,TestDemo.this.password);Statement statement = connection.createStatement();
​String sql = "select * from users where user_name = '"+username+"' and password = '"+password+"'";
​ResultSet resultSet = statement.executeQuery(sql);
​if (resultSet.next()){System.out.println("登录成功");}else {System.out.println("登录失败");}
​resultSet.close();statement.close();connection.close();}
}

SQL注入本质:由于用户输入导致SQL语句发生变化,如where username = ? and ... +(or 1=1)【后面追加一个恒成立等式,就会导致where条件恒成立】

解决方式1:更多的逻辑判断

@Test
public void demo02() throws Exception {Scanner scanner = new Scanner(System.in);System.out.println("请输入用户名");String username = scanner.nextLine();System.out.println("请输入密码");String password = scanner.nextLine();
​Connection connection = DriverManager.getConnection(TestDemo.this.url,TestDemo.this.userName,TestDemo.this.password);Statement statement = connection.createStatement();
​String sql = "select * from users where user_name = '"+username+"' and password = '"+password+"'";
​ResultSet resultSet = statement.executeQuery(sql);
​while (true){boolean next = resultSet.next();if (next){if (username.equals(resultSet.getString("user_name"))){if (password.equals(resultSet.getString("password"))){System.out.println("登录成功");}else {System.out.println("密码错误");}break;}}else {System.out.println("没有此用户");break;}
​}
​resultSet.close();statement.close();connection.close();
}

解决方式2:预编译SQL

(4)perparedStatement使用
  • 获取PerparedStatement对象

    • 使用Connection的prepareStatement(sql)

    • SQL语句中的参数值,使用?占位符替代

  • 设置参数

    • setXxx【数据类型】(int ?的位置编号,参数值)

    • ?位置从1开始

  • 执行SQL

    • 主要方法

    • 方法名返回值类型说明
      execute()boolean可执行所有sql语句,返回值为是否执行成功
      executeUpdate()int执行数据操纵语言DML或者没有返回值类型的SQL,如DDL
      executeQuery()ResultSet执行DQL,返回ResultSet对象

@Testpublic void sout() throws Exception {Scanner scanner = new Scanner(System.in);System.out.println("请输入用户名");String username = scanner.nextLine();System.out.println("请输入密码");String password = scanner.nextLine();
​Connection connection = DriverManager.getConnection(TestDemo.this.url,TestDemo.this.userName,TestDemo.this.password);
​
​String sql = "select * from users where user_name=? and password=?";
​PreparedStatement preparedStatement = connection.prepareStatement(sql);//设置?的值preparedStatement.setString(1,username);preparedStatement.setString(2,password);
​ResultSet resultSet = preparedStatement.executeQuery();
​if (resultSet.next()){System.out.println("登录成功");}else {System.out.println("登录失败");}
​resultSet.close();preparedStatement.close();connection.close();}
}

7.关于测试类无法使用Scanner的问题解决

  • 点击Help

  • 选择Edit Custom VM Options...

-Deditable.java.test.console=true
  • 之后重启idea即可

二、数据库连接池

1.概述

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)

  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;

  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏

好处:

  • 资源重用

  • 提升系统响应速度

  • 避免数据库连接遗漏

2.数据库连接池的实现

(1)标准接口:DataSource

官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口。

功能:

  • 获取连接:getConnection()

(1)常见的数据库连接池
  • DBCP

  • C3P0

  • Druid(德鲁伊)

    • Druid连接池是阿里巴巴开源的数据库连接池项目

    • 功能强大,性能优秀,是Java语言最好的数据库连接池之一

3.Druid数据库连接池的使用

  • 导入jar包:druid

  • 定义配置文件

  • 加载配置文件

  • 获取数据库连接池对象

  • 获取连接

配置文件:

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

java代码:

@Test
public void connectionPool() throws Exception {//加载配置文件Properties properties = new Properties();properties.load(new FileInputStream("src\\druid.properties"));
​//创建连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);//获取数据库连接final Connection connection = dataSource.getConnection();
​System.out.println(connection);
​
}

三、综合练习

主要目标:

  • 建表:

  • 添加数据:

  • 表中数据的增、删、改、查

  • 表中数据的存储

  • 使用数据库连接池

1.创建表:

这玩意后期不会纯手敲的,除非业务需要

-- auto-generated definition
create table product
(id           bigint auto_increment comment '商品ID'primary key,name         varchar(20)                        not null comment '商品名称',price        decimal(10, 2)                     not null comment '商品价格',category     int      default 1                 not null comment '商品分类',gmt_modified datetime default CURRENT_TIMESTAMP not null comment '最后修改日期',gmt_create   datetime default CURRENT_TIMESTAMP not null comment '创建日期',constraint product_name_uindexunique (name)
)comment '商品表';

2.添加数据:表中数据增

id设置主键和自增约束可不写

public class Practice {public static void main(String[] args) throws Exception {
​//加载配置文件Properties properties = new Properties();properties.load(new FileInputStream("JDBC\\src\\practice\\druidDemo.properties"));
​//获取连接池连接对象final Connection connection = DruidDataSourceFactory.createDataSource(properties).getConnection();
​String sql = "insert into product (name,price,category)" +"values(?,?,?)";Random random = new Random();
​
​final PreparedStatement preparedStatement = connection.prepareStatement(sql);for (int i = 1; i <= 40; i++) {int integerPart = random.nextInt(10001);int decimalPart = random.nextInt(100);preparedStatement.setString(1,"商品"+i);if (decimalPart<10){preparedStatement.setString(2,integerPart+".0"+decimalPart);}else{preparedStatement.setString(2,integerPart+"."+decimalPart);}preparedStatement.setInt(3,1);try {preparedStatement.execute();System.out.println("第"+i+"条数据添加成功");} catch (SQLException e) {System.out.println("第"+i+"条数据添加失败");e.printStackTrace();}
​}
​preparedStatement.close();connection.close();
​}
}

3.表中数据的删、改、查

实体类:后面会有优化,也不会手敲的~

public class Product {private Long id;private String name;private BigDecimal bigDecimal;private Integer category;private Timestamp gmtCreate;private Timestamp gmtModified;
​public Product() {}
​public Product(Long id, String name, BigDecimal bigDecimal, Integer category, Timestamp gmtCreate, Timestamp gmtModified) {this.id = id;this.name = name;this.bigDecimal = bigDecimal;this.category = category;this.gmtCreate = gmtCreate;this.gmtModified = gmtModified;}
​public Long getId() {return id;}
​public void setId(Long id) {this.id = id;}
​public String getName() {return name;}
​public void setName(String name) {this.name = name;}
​public BigDecimal getBigDecimal() {return bigDecimal;}
​public void setBigDecimal(BigDecimal bigDecimal) {this.bigDecimal = bigDecimal;}
​public Integer getCategory() {return category;}
​public void setCategory(Integer category) {this.category = category;}
​public Timestamp getGmtCreate() {return gmtCreate;}
​public void setGmtCreate(Timestamp gmtCreate) {this.gmtCreate = gmtCreate;}
​public Timestamp getGmtModified() {return gmtModified;}
​public void setGmtModified(Timestamp gmtModified) {this.gmtModified = gmtModified;}
​@Overridepublic String toString() {return "Product{" +"id=" + id +", name='" + name + '\'' +", bigDecimal=" + bigDecimal +", category=" + category +", gmtCreate=" + gmtCreate +", gmtModified=" + gmtModified +'}';}
}
(1)查(需要啥写啥)+存
        //查询所有String sql = "select * from product";final PreparedStatement preparedStatement = connection.prepareStatement(sql);ResultSet resultSet = preparedStatement.executeQuery();ArrayList<Product> productArrayList = new ArrayList<>();while (resultSet.next()){Product product = new Product(resultSet.getLong(1),resultSet.getString(2),resultSet.getBigDecimal(3),resultSet.getInt(4),resultSet.getTimestamp(5),resultSet.getTimestamp(6));productArrayList.add(product);}
​productArrayList.forEach(p -> System.out.println(p));
​resultSet.close();preparedStatement.close();connection.close();
        //根据条件查String sql = "select * from product where id = ?";final PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setLong(1,10126);ResultSet resultSet = preparedStatement.executeQuery();ArrayList<Product> productArrayList = new ArrayList<>();while (resultSet.next()){Product product = new Product(resultSet.getLong(1),resultSet.getString(2),resultSet.getBigDecimal(3),resultSet.getInt(4),resultSet.getTimestamp(5),resultSet.getTimestamp(6));productArrayList.add(product);}
​productArrayList.forEach(p -> System.out.println(p));
​resultSet.close();preparedStatement.close();connection.close();
(2)改
public class Practice {public static void main(String[] args) throws Exception {
​//加载配置文件Properties properties = new Properties();properties.load(new FileInputStream("src\\practice\\druidDemo.properties"));
​//获取连接池连接对象final Connection connection = DruidDataSourceFactory.createDataSource(properties).getConnection();//输入sql语句String sql = sqls();
​
​
​
​final PreparedStatement preparedStatement = connection.prepareStatement(sql);//设置参数parameterSetting(preparedStatement);
​//执行sql//execute(),可执行所有SQL语句//executeUpdate(),执行DML(返回受影响的行数)或者无返回值的SQL语句,如DDL//executeQuery(),DQL,返回ResultSet对象preparedStatement.executeUpdate();
​//查询专用//query(preparedStatement);
​preparedStatement.close();connection.close();
​}
​private static void parameterSetting(PreparedStatement preparedStatement) throws SQLException {preparedStatement.setInt(1,3);preparedStatement.setLong(2,10126);}
​private static void query(PreparedStatement preparedStatement) throws SQLException {
​ResultSet resultSet = preparedStatement.executeQuery();
​ArrayList<Product> productArrayList = new ArrayList<>();while (resultSet.next()){Product product = new Product(resultSet.getLong(1),resultSet.getString(2),resultSet.getBigDecimal(3),resultSet.getInt(4),resultSet.getTimestamp(5),resultSet.getTimestamp(6));productArrayList.add(product);}
​productArrayList.forEach(p -> System.out.println(p));
​resultSet.close();}
​private static String sqls() {//查询所有
//        String sql = "select * from product";//根据条件查
//        String sql = "select * from product where id = ?";//根据条件改return "update product set category = ? where id = ?";}
}
(3)删除

改SQL,preparedStatement.set一下就行了

String sql = "delete from product where id = ?";

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

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

相关文章

基于Java SSM框架实现汉服文化平台系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现汉服文化平台系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个汉服文化平台网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论…

Linux中make和makefile

make与makefile 简单介绍常见用法符号替代自动寻找设置变量取消打印提示 简单介绍 make是Linux中一个命令&#xff0c;与之匹配的是makefile&#xff0c;makefile是一个文件。make会根据makefile中的内容完成对应的工作 创建一个名为makefile的文件 vim打开makefile 第一行是依…

调试以及发布npm组件

开发原因&#xff1a; 由于公司自己的封装到npm的组件有点问题&#xff0c;负责人由在忙其他&#xff0c;就由我去负责改改&#xff0c;中途出了不少问题&#xff0c;记录一下。 一、下载源码 第一步肯定是去git上把组件的源码下载下来&#xff0c;这一步没什么好说&#xf…

好的问卷设计标准:确保数据质量与准确性的关键要素

问卷的主要由三个部分组成&#xff1a;问卷说明、问卷主题、问卷结束。而这三个部分又包含了很多因素&#xff0c;比如问卷主题、问卷标题、问卷题目、问卷调查对象等。制作问卷不仅仅是简单的问题罗列&#xff0c;然后进行发放。不同质量的调查问卷会反馈出不一样的效果&#…

Vue.js设计与实现(霍春阳)

Vue.js设计与实现 (霍春阳) 电子版获取链接&#xff1a;Vue.js设计与实现(霍春阳) 编辑推荐 适读人群 &#xff1a;1.对Vue.js 2/3具有上手经验&#xff0c;且希望进一步理解Vue.js框架设计原理的开发人员&#xff1b; 2.没有使用过Vue.js&#xff0c;但对Vue.js框架设计感兴趣…

2024年美赛E题:财产保险的可持续性 Sustainability of Property Insurance 思路模型代码解析

2024年美赛E题&#xff1a;财产保险的可持续性 Sustainability of Property Insurance 思路模型代码解析 【点击最下方群名片&#xff0c;加入群聊&#xff0c;获取更多思路与代码哦~】 问题翻译 极端天气事件对房产所有者和保险公司已经成为一场危机。近年来&#xff0c;世界…

Blender教程(基础)-面的切割-10

快捷键K切割&#xff0c;菜单选项切割. 一、随意切割 物体在编辑模式下&#xff0c;按键盘K建切割物体。 二、中点切割 先按K键&#xff0c;再按shift键&#xff0c;会自动吸附到每条边的中点进行切割。 三、取消吸附 切割时会自动吸附到顶点或边 关闭快速吸附 按K键再按…

26条prompt规则应用于大模型

1、引入动机 llm大模型在回答一些问题上表现出了惊人的能力&#xff0c;例如数学逻辑推理&#xff0c;代码生成&#xff0c;问题答复等。提词工程是和大预言模型交流的一门艺术。 大模型的返回结合和用户的指令和输入直接相关prompts是用户和大模型沟通的一种编码方式 一般地…

在低代码平台上实现精益软件开发:提高效率与灵活性的关键实践

什么是精益软件开发&#xff1f; 精益软件开发是一种敏捷的软件开发框架。它基于最小化浪费和最大化价值的原则。该框架基于最小可行产品策略运行&#xff0c;该策略强调交付具有基本基本功能的产品&#xff0c;然后根据收到的反馈进行迭代以即兴发挥并提供卓越。 精益软件开发…

2阶段提交_3阶段提交(phase-commit)

1. 2PC&#xff08;两阶段提交) 如上所示是2阶段提交的一个过程&#xff0c;可为什么要进行两阶段提交呢&#xff1f;这里主要来说是将操作事务能力和提交、回滚事务能力分开来做成2阶段&#xff0c;如果不分开会造成什么后果呢&#xff1a; 如果单纯 A 向 B 发送一个请求就以…

由于找不到d3dcompiler43.dll无法继续执行程序的解决方法

在日常使用电脑的过程中&#xff0c;我们常常会遭遇一些突发的技术问题&#xff0c;其中之一便是可能会遇到系统提示找不到d3dcompiler43.dll文件的情况。这一特定的动态链接库文件&#xff08;dll&#xff09;对于许多应用程序的正常运行至关重要&#xff0c;尤其是在涉及到图…

PPT母版页码设置

PPT母版页码设置 一、需求介绍二、达到效果三、具体操作1. 插入页码2. 设置起始页码为03. 进入母版编辑页面4. 内容格式调整5. 删去最后一个板式的三个模块信息6. 尾页处理7. 最终效果 一、需求介绍 PPT的母版可以设定PPT的基调&#xff0c;且在非母版页面不会误改PPT中的固定…

【笔记】Android 常用编译模块和输出产物路径

模块&产物路径 具体编译到软件的路径要看编译规则的分区&#xff0c;代码中模块编译输出的产物基本对应。 Android 代码模块 编译产物路径设备adb路径Comment 模块device/mediatek/system/common/ 资源overlay/telephony/frameworks/base/core 文件举例res/res/values-m…

大专考试,搜题最准的软件?搜题神器推荐,助力大学生学业! #其他#知识分享

下面&#xff0c;我将为您介绍几款备受大学生欢迎的搜题软件&#xff0c;希望能够帮助您更好地完成学业和提升学习效果。 1.Quizlet Quizlet是一款学习卡片和题库应用&#xff0c;可用于各种学科的学习和复习。通过Quizlet&#xff0c;学生可以创建自己的学习卡片&#xff0c…

Leetcode的AC指南 —— 栈与队列 :150. 逆波兰表达式求值

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列 &#xff1a;150. 逆波兰表达式求值 **。题目介绍&#xff1a;给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 文章目录 一、题目…

Redis核心技术与实战【学习笔记】 - 17.Redis 缓存异常:缓存雪崩、击穿、穿透

概述 Redis 的缓存异常问题&#xff0c;除了数据不一致问题外&#xff0c;还会面临其他三个问题&#xff0c;分别是缓存雪崩、缓存击穿、缓存穿透。这三个问题&#xff0c;一旦发生&#xff0c;会导致大量的请求积压到数据库。若并发量很大&#xff0c;就会导致数据库宕机或故…

TQ15EG开发板教程:开发板Vivado硬件设置

1&#xff0c;串口的配置 PS端有2个串口,在BANK500, 1.8V IO电平 管脚名称 电平 说明 UART0 RX MIO18 1.8V MPSOC方向看 TX MIO19 1.8V UART1 RX MIO21 1.8V TX MIO20 1.8V 2&#xff0c;QSPI的配置 采用2片MT25QU256 拼接成8bit的QSPI存储系统。采用1.8V…

安卓SurfaceTexture中updateTexImage使用及源码分析

文章目录 引言updateTexImage 简单使用SurfaceTexture 初始化相关源码分析Surface 绘制流程源码分析createBufferQueue 源码分析SurfaceTexture 之 updateTexImage 源码分析结尾 本文首发地址 https://h89.cn/archives/140.html 最新更新地址 https://gitee.com/chenjim/chenji…

中国象棋基础

帅&#xff08;将&#xff09;的运用原则&#xff1a; &#xff08;1&#xff09;帅走直线&#xff0c;前进后退均可 &#xff08;2&#xff09;一次只能走一格 &#xff08;3&#xff09;活动范围在“九宫”之内 &#xff08;4&#xff09;可行处可吃敌子 &#xff08;5&…

React实例之完善布局菜单(一)

今天我们来用所学的知识来做一个布局菜单的组件, 针对这个组件我之前写过一个教程 React之布局菜单-CSDN博客&#xff0c;那个呢比较基础&#xff0c;这节课算是对那个教程的一个扩展和补充。这个实例讲完&#xff0c;这个系列就算告一段落了。先看效果 这个教程要求对React知识…