MySQL学习笔记3——JDBC

目录

  • JDBC简介
  • 数据库驱动
  • JDBC
  • 第一个JDBC程序
  • JDBC中各对象详解
    • statement对象
    • 包装成工具类
    • SQL注入问题
    • PreparedStatement对象
  • 使用IDEA连接数据库
  • JDBC操作事务
  • 数据库连接池
    • DBCP
      • 需要用到的JAR包
      • DBCP配置文件
      • 工具类
      • 测试代码
    • C3P0
      • 需要用到的JAR包
      • C3P0配置文件
      • 工具类
      • 测试代码
    • 结论

JDBC简介

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。

数据库驱动

什么是数据库驱动?类似声卡驱动、显卡驱动
我们的程序会通过数据库驱动,和数据库打交道。
在这里插入图片描述

JDBC

SUN 公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库的)规范,JDBC。

这些规范的实现由具体的厂商去做。

对于开发人员来说,我们只需要掌握JDBC的接口操作即可。
在这里插入图片描述
java.sql

javax.sql

还需要导入数据库驱动包

第一个JDBC程序

1.创建测试数据库

CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;USE jdbcStudy;CREATE TABLE `users`(
id INT PRIMARY KEY,
NAME VARCHAR(40),
PASSWORD VARCHAR(40),
email VARCHAR(60),
birthday DATE
);INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)
VALUES(1,'zhansan','123456','zs@sina.com','1980-12-04'),
(2,'lisi','123456','lisi@sina.com','1981-12-04'),
(3,'wangwu','123456','wangwu@sina.com','1979-12-04')

2.创建一个普通项目

3.导入数据库驱动
pom.xml

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency>

4.编写测试代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class JdbcDemo {public static void main(String[] args) throws Exception {//1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");//固定写法 jdbc驱动版本8.0之前为com.mysql.jdbc.Driver//2. 用户信息和url//useUnicode=true&characterEncoding=utf8&&useSSL=true//useUnicode=true支持中文编码;characterEncoding=utf8中文字符集设置为utf-8;useSSL=true使用安全链接//jdbc驱动版本8.0之后要添加serverTimezone=UTCString url ="jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&&useSSL=true";String name = "root";String password = "123456";//3. 连接成功,返回数据库对象  connection代表数据库Connection connection= DriverManager.getConnection(url,name,password);//4. 执行SQL的对象 statement 执行SQL的对象Statement statement = connection.createStatement();//5. 执行SQL的对象 去执行SQL   可能存在结果,查看返回结果String sql="SELECT * FROM users";ResultSet resultSet = statement.executeQuery(sql);//返回的结果集,结果集中封装了我们全部查询的结果while(resultSet.next()){System.out.println("ID="+resultSet.getObject("id"));System.out.println("姓名="+resultSet.getObject("NAME"));System.out.println("密码="+resultSet.getObject("PASSWORD"));System.out.println("邮箱="+resultSet.getObject("email"));System.out.println("生日="+resultSet.getObject("birthday"));System.out.println("==================================");}//6. 释放连接(从后往前释放)resultSet.close();statement.close();connection.close();}
}

JDBC中各对象详解

步骤总结:
1.加载驱动

2.连接数据库 DriverManager

3.获取执行SQL的对象 Statement

4.获得返回的结果集

5.释放连接

DriverManager

//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");//固定写法
Connection connection= DriverManager.getConnection(url,name,password);//connection代表数据库
//数据库设置自动提交
//事务提交
//事务回滚
connection.rollback();
connection.commit();
connection.setAutoCommit();

URL

String url ="jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&&useSSL=true";//mysql 默认端口3306
//协议://主机地址:端口号/数据库名?参数1&参数2&参数3...//Oracle   1521
//jdbc:oralce:thin:@localhost:1521:sid

statement执行SQL的对象 PrepareStatement 执行SQL的对象

String sql="SELECT * FROM users";//编写Sqlstatement.executeQuery();//查询操作,返回ResultSet
statement.execute();//执行任何SQL
statement.executeUpdate();//更新,插入,删除,返回一个受影响的行数

ResultSet 查询的结果集,封装了所有的查询结果

获得指定的数据类型

ResultSet resultSet = statement.executeQuery(sql);//返回的结果集,结果集中封装了我们全部查询的结果resultSet.getObject();//在不知道列类型下使用//如果知道则使用指定类型
resultSet.getString();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
...       

遍历,指针

        resultSet.next(); //移动到下一个resultSet.afterLast();//移动到最后resultSet.beforeFirst();//移动到最前面resultSet.previous();//移动到前一个resultSet.absolute(row);//移动到指定行

释放内存

//6. 释放连接(从后往前释放) resultSet.close();statement.close();connection.close();//connection连接最占用资源

statement对象

JDBC中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。

Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sq|语句, executeUpdate执行完后, 将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。

Statement.executeQuery方法用于向数据库发生查询语句,executeQuery方法返回代表查询结果的ResultSet对象。

CRUD操作-create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:

 Statement statement = connection.createStatement();String sql = "insert into user(...) values(...)";int num = statement.executeUpdate(sql);if(num>0){System.out.println("插入成功");}

CRUD操作-delete
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:

Statement statement = connection.createStatement();String sql = "delete from user where id =1";int num = statement.executeUpdate(sql);if(num>0){System.out.println("删除成功");}

CURD操作-update
使用executeUpdate(String sql)方法完成数据修改操作,示例操作:

Statement statement = connection.createStatement();String sql = "update user set name ='' where name = ''";int num = statement.executeUpdate(sql);if(num>0){System.out.println("修改成功");}

CURD操作-read
使用executeUpdate(String sql)方法完成数据查询操作,示例操作:

Statement statement = connection.createStatement();String sql = "select * from  user where id =1";ResultSet rs= statement.executeQuery(sql);if(rs.next()){System.out.println("");}

包装成工具类

首先配置文件db.properties写好信息

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&&useSSL=true
username=root
password=123456

工具类

import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;public class JdbcUtils {private static String driver = null;private static String url = null;private static String username = null;private static String password = null;static {try{FileInputStream in = new FileInputStream("src/main/resources/db.properties");//InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");//  通过类加载器读取对应的资源,注意此时db.properties要放在resources文件夹里面Properties properties = new Properties();properties.load(in);driver=properties.getProperty("driver");url=properties.getProperty("url");username=properties.getProperty("username");password=properties.getProperty("password");//1.驱动只用加载一次Class.forName(driver);} catch (Exception e) {e.printStackTrace();}}//2.获取连接public static Connection getConnection() throws Exception{return DriverManager.getConnection(url, username, password);}//3.释放资源public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException {if (rs != null) {rs.close();}if (st != null){st.close();}if(conn != null){conn.close();}}
}

使用工具类(插入数据为例)(exectueUpdate可以进行增删改三个操作)

import com.cheng.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;import static com.cheng.utils.JdbcUtils.getConnection;public class TestInsert {public static void main(String[] args){Connection conn =null;Statement st = null;ResultSet rs =null;try {conn = getConnection();//获取连接st = conn.createStatement();//获取SQL执行对象String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`)" +"VALUES(5,'你好','123456','233223@qq.com','2020-01-01')";int i = st.executeUpdate(sql);if(i>0){System.out.println("插入成功");}JdbcUtils.release(conn,st,rs);} catch (Exception e) {e.printStackTrace();}}}

使用工具类(查询数据为例)

import com.cheng.utils.JdbcUtils;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;import static com.cheng.utils.JdbcUtils.getConnection;public class TestQuery {public static void main(String[] args) throws SQLException {Connection conn =null;Statement st = null;ResultSet rs =null;try {conn = getConnection();//获取连接st = conn.createStatement();//获取SQL执行对象String sql = "select * from users";rs=st.executeQuery(sql);//查询完毕返回结果集while (rs.next()){System.out.println(rs.getString("NAME"));}JdbcUtils.release(conn,st,rs);} catch (Exception e) {e.printStackTrace();}finally {JdbcUtils.release(conn,st,rs);}}
}

SQL注入问题

sql存在漏洞,会被攻击导致数据泄露 SQL会被拼接 or

原理,例如密码查询正常是要匹配密码,但是加个or 1=1后就会认为密码查询通过,因为or是左右两边有一个成立都认为是成立,又因为1=1恒成立,所以服务器被欺骗,认为密码查询通过

示例

import com.cheng.utils.JdbcUtils;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;import static com.cheng.utils.JdbcUtils.getConnection;public class SqlInjection {public static void main(String[] args) {// 正常查询login("你好","123456");System.out.println("=================");// SQL注入login("' OR '1=1","' OR '1=1");}public static void login(String name,String password){Connection conn =null;Statement st = null;ResultSet rs =null;try {conn = getConnection();//获取连接st = conn.createStatement();//获取SQL执行对象// 正常查询:SELECT * FROM users WHERE `NAME`='你好'  AND `PASSWORD`='123456'// SQL注入:SELECT * FROM users WHERE `NAME`='' OR '1=1' AND `PASSWORD`='' OR '1=1'// 即为SELECT * FROM users  这样就能获取整个表所有信息String sql = "SELECT * FROM users WHERE `NAME`='"+ name +"'  AND `PASSWORD`='"+ password +"'" ;rs=st.executeQuery(sql);//查询完毕返回结果集while (rs.next()){System.out.println(rs.getString("NAME"));}JdbcUtils.release(conn,st,rs);} catch (Exception e) {e.printStackTrace();}finally {try {JdbcUtils.release(conn,st,rs);} catch (SQLException throwables) {throwables.printStackTrace();}}}
}

PreparedStatement对象

PreparedStatement 可以防止SQL注入 ,效率更高。

public class Test {public static void main(String[] args) {Connection connection= null;PreparedStatement pstm=null;try {connection = JdbcUtils.getConnection();//PreparedStatement防止SQL注入本质:把传递进来的参数当作字符//假设其中存在转义字符,比如说引号,会被直接转义// 区别:// 1.使用问号占位符代替参数String sql = "insert into users(id, `NAME`, `PASSWORD`, `email`,`birthday`) values(?, ?, ?, ?, ?)";// 2.预编译sql,先写sql然后不执行pstm = connection.prepareStatement(sql);// 手动赋值pstm.setInt(1,4);// 1代表第一个问号pstm.setString(2,"张三");pstm.setString(3,"123123");pstm.setString(4,"123333@qq.com");pstm.setDate(5,new java.sql.Date(new Date().getTime()));// 注意要转换成sql的Date//执行int i = pstm.executeUpdate();if (i>0){System.out.println("插入成功");}} catch (Exception e) {e.printStackTrace();}finally {try {JdbcUtils.release(connection,pstm,null);} catch (SQLException throwables) {throwables.printStackTrace();}}}
}

输出:

你好
=================
zhansan
lisi
wangwu
张三
你好

防止SQL注入本质,传递字符 带有“ ”,转义字符会被转义
改进示例:

import com.cheng.utils.JdbcUtils;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Test {public static void main(String[] args) {// 正常查询login("你好","123456");System.out.println("=================");// SQL注入login("'' OR 1=1","'' OR 1=1");}public static void login(String username,String password) {Connection connection = null;PreparedStatement pstm = null;ResultSet rs = null;try {connection = JdbcUtils.getConnection();// 区别:// 1.使用问号占位符代替参数String sql = "SELECT * FROM users WHERE `NAME`=? AND `PASSWORD`=?";// 2.预编译sql,先写sql然后不执行pstm = connection.prepareStatement(sql);// 手动赋值pstm.setString(1, username);// 1代表第一个问号pstm.setString(2, password);rs = pstm.executeQuery();//注意!!!!这里不像st.executeQuery(sql);那样,括号里不要写sql,否则报错。因为PreparedStatement是预编译的,PreparedStatement对象中已包含SQL查询//查询完毕返回结果集while (rs.next()) {System.out.println(rs.getString("NAME"));}JdbcUtils.release(connection, pstm, rs);} catch (Exception e) {e.printStackTrace();} finally {try {JdbcUtils.release(connection, pstm, rs);} catch (SQLException throwables) {throwables.printStackTrace();}}}
}

注意!!!!rs = pstm.executeQuery();不像rs = st.executeQuery(sql);那样,括号里不要写sql,否则报错。因为PreparedStatement是预编译的,PreparedStatement对象中已包含SQL查询

输出:(SQL注入失效)

你好
=================

使用IDEA连接数据库

连接数据库
在这里插入图片描述

添加表
在这里插入图片描述

修改数据表:
双击数据表,修改,提交
在这里插入图片描述

编写查询
在这里插入图片描述

JDBC操作事务

要么都成功,要么都失败

ACID原则

  • 原子性:要么全部完成,要么都不完成
  • 一致性:结果总数不变
  • 隔离性:多个进程互不干扰
  • 持久性:一旦提交不可逆,持久化到数据库了

隔离性的问题:

  • 脏读: 一个事务读取了另一个没有提交的事务
  • 不可重复读:在同一个事务内,重复读取表中的数据,表发生了改变
  • 虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致

代码实现

  1. 开启事务conn.setAutoCommit(false);
  2. 一组业务执行完毕,提交事务
  3. 可以在catch语句中显示的定义回滚,但是默认失败会回滚

创建示例数据库:
在这里插入图片描述

public class JdbcTransaction{public static void main(String[] args) {Connection conn =null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();//关闭数据库的自动提交功能, 开启事务conn.setAutoCommit(false);//自动开启事务String sql = "update account set money = money-100 where id = 1";ps =conn.prepareStatement(sql);ps.executeUpdate();String sql2 = "update account set money = money-100 where id = 2";ps=conn.prepareStatement(sql2);ps.executeUpdate();//业务完毕,提交事务conn.commit();System.out.println("操作成功");} catch (Exception e) {try {//如果失败,则默认回滚conn.rollback();//如果失败,回滚System.out.println("失败");} catch (SQLException throwables) {throwables.printStackTrace();}e.printStackTrace();}finally {try {JdbcUtils.release(conn,ps,rs);} catch (SQLException throwables) {throwables.printStackTrace();}}}
}

数据库连接池

传统连接方式:数据库连接–执行完毕–释放

服务器频繁重复连接–释放会十分浪费资源

池化技术:准备一些预先的资源,过来就连接预先准备好的

  • 常用连接数:10
  • 最小连接数:10(一般跟常用连接数相等)
  • 最大连接数 : 100(业务最高承载上限)
  • 若大于最大连接数,排队等待,
  • 等待超时:100ms(100ms后等待的链接断开连接)

编写连接池:实现一个接口DateSource

常见的开源数据源实现(拿来即用)
以下这些是市面上常见的DateSource接口的实现类

  • DBCP
  • C3P0
  • Druid: 阿里巴巴

使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了

DBCP

需要用到的JAR包

(使用maven导入)
pom.xml

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId><version>2.7.0</version></dependency>

DBCP配置文件

dbcp-config.properties

#连接设置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&&useSSL=true
username=root
password=123456#<!-- 初始化连接 -->
initialSize=10#最大连接数量
maxActive=50#<!-- 最大空闲连接 -->
maxIdle=20#<!-- 最小空闲连接 -->
minIdle=5#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60-->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】
#注意:"user""password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

工具类

import org.apache.commons.dbcp2.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;public class Dbcp {private static DataSource dataSource = null;static {try{FileInputStream in = new FileInputStream("src/main/resources/dbcpconfig.properties");Properties properties = new Properties();properties.load(in);// 1.创建数据源 工厂模式——>创建dataSource = BasicDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}// 2.获取连接public static Connection getConnection() throws Exception{return dataSource.getConnection();  // 从数据源中获取连接}// 3.释放资源public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException {if (rs != null) {rs.close();}if (st != null){st.close();}if(conn != null){conn.close();}}
}

测试代码

import com.cheng.utils.Dbcp;
import java.sql.*;public class DbcpTest {public static void main(String[] args) throws SQLException {Connection conn =null;PreparedStatement ps = null;ResultSet rs =null;try {conn = Dbcp.getConnection();String sql = "select * from users";ps=conn.prepareStatement(sql);rs=ps.executeQuery();while (rs.next()){System.out.println(rs.getString("NAME"));}} catch (Exception e) {e.printStackTrace();}finally {Dbcp.release(conn,ps,rs);}}
}

C3P0

需要用到的JAR包

(使用maven导入)
pom.xml

    <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.4</version></dependency>

C3P0配置文件

c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><!-- 如果在代码中"ComboPooledDataSource ds=new ComboPooledDataSource();"这样写就表示使用的是c3p0的缺省(默认)--><!-- c3p0的缺省(默认)配置--><default-config><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf8&amp;&amp;useSSL=true</property><property name="user">root</property><property name="password">123456</property><property name="acquireIncrement">5</property><property name="initialPoolSize">10</property><property name="minPoolSize">5</property><property name="maxPoolSize">20</property></default-config><!-- 如果在代码中"ComboPooledDataSource ds=new ComboPooledDataSource("s1");"这样写就表示使用的是s1配置参数)--><named-config name="s1"></named-config></c3p0-config>

另外,可以使用代码配置参数

// 可以使用代码配置参数dataSource = new ComboPooledDataSource();dataSource.setDriverClass("");dataSource.setJdbcUrl("");dataSource.setUser("");dataSource.setPassword("");dataSource.setMaxPoolSize(100);

工具类

import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class C3p0 {private static ComboPooledDataSource dataSource = null;static {try{// 创建数据源dataSource = new ComboPooledDataSource();} catch (Exception e) {e.printStackTrace();}}// 2.获取连接 因为getConnection()是接口的方法 所以下面跟DBCP一样都不用变public static Connection getConnection() throws Exception{return dataSource.getConnection();  // 从数据源中获取连接}// 3.释放资源public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException {if (rs != null) {rs.close();}if (st != null){st.close();}if(conn != null){conn.close();}}
}

测试代码

import com.cheng.utils.C3p0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class C3p0Test {public static void main(String[] args) throws SQLException {Connection conn =null;PreparedStatement ps = null;ResultSet rs =null;try {conn = C3p0.getConnection();String sql = "select * from users";ps=conn.prepareStatement(sql);rs=ps.executeQuery();while (rs.next()){System.out.println(rs.getString("NAME"));}} catch (Exception e) {e.printStackTrace();}finally {C3p0.release(conn,ps,rs);}}
}

结论

无论使用什么数据源,本质是不变的,DateSource接口不会变,方法就不会变,因为这些开源数据源都是DateSource接口的实现。

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

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

相关文章

[Leedcode][JAVA][第15题][三数之和][数组][双指针]

【问题描述】[中等] 给你一个包含 n 个整数的数组 nums&#xff0c;判断 nums 中是否存在三个元素 a&#xff0c;b&#xff0c;c &#xff0c;使得 a b c 0 &#xff1f;请你找出所有满足条件且不重复的三元组。注意&#xff1a;答案中不可以包含重复的三元组。 示例&#…

Yarn的三种资源调度机制

在企业中并不是只有一个人来执行MapReduce程序单独使用Yarn的资源&#xff0c;实际开发中&#xff0c;会有很多人一起使用Yarn这个资源&#xff0c;如果每个人都提交了job&#xff0c;这个时候Yarn就需要进行调度去分配资源给job&#xff0c; 下面三种调度机制&#xff0c;默认…

Java学习笔记9-1——JavaWeb

目录HTTPHTTP请求HTTP响应ServletServlet原理Mapping问题ServletContext获取ServletContext对象ServletContext应用HttpServletResponse下载文件验证码功能实现重定向HttpServletRequestCookie和Session会话CookieSession&#xff08;重点&#xff09;对比ServletContextJSPJSP…

[剑指offer][JAVA]面试题第[22]题[j剑指offer][双指针][快慢指针]

【问题描述】[中等] 输入一个链表&#xff0c;输出该链表中倒数第k个节点。为了符合大多数人的习惯&#xff0c;本题从1开始计数&#xff0c;即链表的尾节点是倒数第1个节点。例如&#xff0c;一个链表有6个节点&#xff0c;从头节点开始&#xff0c;它们的值依次是1、2、3、4…

灰度重采样(Gray Resampling

插值方法 nearest——最邻近点插值。它根据已知两点间的插值 点和这两已知点间位置的远近来进行插值&#xff0c;取较近已知 插值点处的函数值作为未知插值点处的函数值。 linear——线性插值。它将相邻的数据点用直线相连&#xff0c; 按所生成的直线进行插值。 spline——…

空间变换方法

空间变换方法可分为简单变换和控制点变换两种方法&#xff0c; 主要介绍了简单变换 法&#xff0c;这里再补充控制点变换方法。 在许多图像处理的应用中&#xff0c;所需的空间变换都很复杂&#xff0c;不是只通过简单的平移、旋转和 缩放等能解决的&#xff0c;而要通过各种不…

[剑指offer][JAVA]面试题第[24]题[反转链表][递归][双指针][头插法]

【问题描述】[中等] 定义一个函数&#xff0c;输入一个链表的头节点&#xff0c;反转该链表并输出反转后链表的头节点。示例:输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL限制&#xff1a;0 < 节点个数 < 5000【解答思路】 1. …

python学习day32 黏包 struct模块

为什么会出现黏包问题&#xff1f; 首先只有在TCP协议中才会出现黏包现象 是因为TCP协议是面向流的协议 在发送的数据 传输过程中 有缓存机制 来避免数据丢失 因此 在连续发送小数据的时候 以及接收大小不符的时候都容易出现黏包现象 本质还是因为我们在接受数据的时候不知道发…

[Leedcode][JAVA][第1300题][转变数组后最接近目标值的数组和][前缀和][二分法][暴力]

【问题描述】[中等] 给你一个整数数组 arr 和一个目标值 target &#xff0c;请你返回一个整数 value &#xff0c;使得将数组中所有大于 value 的值变成 value 后&#xff0c;数组的和最接近 target &#xff08;最接近表示两者之差的绝对值最小&#xff09;。如果有多种使得…

线性系统的基本理论与运算

线性系统的基本理论与运算 线性系统与非线性系统 线性系统的基本理论 二维线性移不变系统 线性移不变系统 如果一个系统既是线性系统&#xff0c;又是移不变系统&#xff0c;则该系 统是线性移不变系统。

行云管家堡垒机 导入腾讯云主机

行云管家堡垒机 导入腾讯云主机 如何实现了对多家云厂商多种云计算资源的集中管理&#xff0c;从成本、监控、备份、安全等多个维度提供统一运维管控&#xff1f; 工具/原料 行云管家堡垒机方法/步骤 Step1&#xff1a;注册登录 登录行云管家&#xff0c;支持QQ、微信、微博、G…

MyBatis面试题(2020最新版)

目录MyBatis简介MyBatis是什么&#xff1f;ORM是什么为什么说Mybatis是半自动ORM映射工具&#xff1f;它与全自动的区别在哪里&#xff1f;传统JDBC开发存在的问题JDBC编程有哪些不足之处&#xff0c;MyBatis是如何解决这些问题的&#xff1f;Mybatis优缺点MyBatis框架适用场景…

Java学习笔记9-2——JavaWeb

文章目录JavaBeanMVC三层架构Filter过滤器Listener监听器JDBC文件上传Servlet邮件发送ServletJavaBean 实体类 JavaBean有特定的写法&#xff1a; 必须要有一个无参构造&#xff1b;属性必须私有化&#xff1b;必须有对应的get/set方法&#xff1b; 一般用来和数据库的字段…

离散傅立叶变换

离散傅立叶变换 一维离散傅里叶变换 二维离散傅里叶变换(2D-DFT) 、图像傅里叶变换的意义 &#xff08;1&#xff09;简化计算&#xff0c;也即傅里叶变换可将空间域中复杂的卷 积运算转化为频率域中简单的乘积运算。 &#xff08;2&#xff09;对于某些在空间域中难于处理或…

[Leedcode][JAVA][第14题][最长公共前缀][二分][横竖扫描][分治]

【问题描述】[中等] 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀&#xff0c;返回空字符串 ""。示例 1:输入: ["flower","flow","flight"] 输出: "fl" 示例 2:输入: ["dog","raceca…

图像傅里叶变换频谱分析

图像的傅里叶频谱特性分析 图像傅里叶频谱关于(/&#xff0c;/)的对称性 图像傅里叶频谱特性及其频谱图 傅里叶变换在图像处理中的应用

[剑指offer]面试题第[37]题[Leedcode][JAVA][第297题][二叉树列的序列化与反序列化][递归][BFS]

【问题描述】[中等] 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传输到另一个计算机环境&#xff0c;采取相反方式重构得到原数据。请设计一个算法来实现二叉树的序列…

Java学习笔记10-1——MyBatis

文章目录简介第一个Mybatis程序搭建环境导入Mybatis&#xff0c;编写配置文件编写代码测试了解一下官方文档的建议实现增删改查select、insert、update、delete使用map进行CRUD模糊查询配置解析(mybatis-config.xml)核心配置文件mybatis-config.xml环境配置&#xff08;environ…

图像的离散余弦变换

Discrete Cosine Transform&#xff0c;简写为DCT 函数的偶对称性使DCT只有实数域变换结果, 不再涉及复数运算&#xff0c;运算简单&#xff0c;费时少&#xff1b; 又保持了变换域的频率特性&#xff1b; 与人类视觉系统特性相适应&#xff1b; 得到了更加广泛的应用。 二维…