基础
八大基本数据类型
8种基本数据类型包括:byte,short,int,long,float,double,boolean,char
- byte:字节型,用于存储整数的, 占用1个字节,范围-128到127
- short:短整型,用于存储整数的,占用2个字节,范围-32768到32767
- int:最常用的整型,用于存储整数的,占用4个字节,范围-231 到 231-1
- long:长整型,用于存储较大的整数, 占用8个字节,范围-263到 263-1
- float:单精度符点数,用于存储小数的,占用4个字节,不能表示精确的值
- double:双精度符点数,最常用的存储小数的类型,占用8个字节,不能表示精确的值
- boolean:布尔型,用于存储true或false,占用1个字节
- char:字符型,采用Unicode字符编码格式,用于存储单个字符,占用2个字节
JRE JVM JDK关系
- JDK:java开发工具包,是java的核⼼,包括:JRE+编译、运行等命令工具
- JRE:java运行环境,是运行java程序所必须的环境集合,包括:JVM+java系统类库
- JVM:java虚拟机,是java实现跨平台的最核⼼部分,能够运行java语⾔所开发的程序
- 简单来说,JDK提供了开发Java程序所需的工具和库,JRE提供了执行Java程序所需的运行时环境,而JVM则是在运行Java程序时实际执行字节码的虚拟机。在开发过程中,你需要安装JDK来编写、编译和调试Java程序,而在运行Java程序时,只需安装JRE即可。
switch 支持类型,String支持么?
byte,short,int,char,String,枚举,其余类型都不允许
面向对象
面向对象特征
- 封装
- 封装通过将相关的数据和方法组合在一个类中,隐藏了内部实现细节并提供公共的接口。这样,对象的状态和行为只能通过公共方法来访问和操作,从而提高了代码的安全性和可维护性。
- 继承
- 继承允许一个类继承另一个类的属性和方法。子类(派生类)可以继承父类(基类)的属性和方法,并且可以在子类中添加新的属性和方法或者覆盖父类的方法。
- 多态
- 通过多态,可以实现代码的灵活性和可扩展性,使得程序具备更高的可维护性和可扩展性。
重写 重载区别
- 重写 :发⽣在⽗子类中,方法名相同,参数列表相同
- 重载:发⽣在同⼀类中,方法名相同,参数列表不同
final修饰特征
final 是Java中用于修饰变量、方法和类的关键字,它具有以下特征:
- final 变量:
- 当 final 修饰一个变量时,该变量被称为常量或者不可改变的变量。一旦被赋值后,其数值将不能再被修改。
- final 变量必须在声明时进行初始化,可以在声明时直接赋值或在构造函数中进行赋值。
- final 变量通常使用大写字母命名,并使用下划线分隔多个单词。
- final 方法:
- 当 final 修饰一个方法时,该方法被称为最终方法,即不能在子类中被重写。
- 子类可以继承父类的 final 方法,但不能对其进行重写或覆盖。
- final 类:
- 当 final 修饰一个类时,该类被称为最终类,即不能被其他类继承。
- final 类中的方法默认为最终方法,不能被子类重写。
使用 final 的主要目的是为了实现不可变性、安全性和效率等方面的需求。通过将变量、方法和类声明为 final,可以确保它们的行为和状态无法被修改,防止意外的改动和继承,从而提升程序的可靠性和性能。
抽象类和接口的区别
- 抽象类 :
- 由abstract修饰
- 可以包含变量、常量、构造方法、普通方法、静态方法、抽象方法
- 派⽣类通过extends继承
- 只能继承⼀个(单⼀继承)
- 抽象类中的成员,任何访问权限都可以(默认为默认权限(同包中))
- 接口:
- 由interface定义
- 可以包含常量、抽象方法、静态方法(1.8后)、默认方法(1.8后)
- 实现类通过implements实现
- 可以实现多个(体现多实现)
- 接口中的成员,访问权限只能是public(默认public权限)
static用法修饰
- 静态变量(Static Variables):
- 使用 static 关键字修饰的属性属于类,而不是类的实例。所有该类的实例共享同一个静态属性,对其中一个实例的修改会影响到其他实例。静态属性可以通过类名直接访问,而不需要创建类的实例
- 静态方法(Static Methods):
- 静态方法是被 static 修饰的方法,它属于类而不是对象,可以直接通过类名调用,无需实例化对象。
- 静态方法不能访问非静态的成员变量和方法,只能操作静态变量或调用其他静态方法。
- 静态代码块(Static Initialization Blocks):
- 静态块是一个在类加载时执行的特殊块,它用 static 关键字修饰。静态块中的代码只会执行一次,用于初始化静态属性或执行其他需要在类加载时完成的操作
内部类 匿名内部类
- 内部类是定义在另一个类内部的类,它可以访问外部类的成员变量和方法
- 区别:
- 局部内部类:定义在方法或代码块内部的内部类,仅在所定义的作用域内可见。局部内部类可以访问外部类、方法或代码块的成员。
- 匿名内部类:没有显式的类名,直接通过实例化接口、抽象类或具体类的方式来创建。通常用于实现简单的逻辑操作和事件处理等。
- 优点:
- 可以方便的访问外部类的私有成员
- 内部类可以实现多继承,一个类可以继承一个类同时实现多个接口
API
Stringbuilder和Stringbuffer 和String的区别
- 可变性
- Stringbuilder和Stringbuffer是可变的
- Stirng一旦创建则无法修改
- 线程安全性:
- StringBuilder 是非线程安全的,适合在单线程环境中使用。
- StringBuffer 是线程安全的,适合在多线程环境中使用。它使用同步(synchronized)来确保并发访问的线程安全性。
- String 是不可变的,因此在多线程环境中也是线程安全的
- 效率性
- StringBuilder 高于StringBuffer,如果对线程没有要求时优先使用StringBuffer
equesl与==区别
- equals() 方法用于比较对象的内容是否相等,通常用于判断两个对象是否逻辑上相等。
- == 运算符用于比较两个对象的引用是否相等,即两个对象是否指向同一个内存地址。
- equals() 方法适用于所有的对象类型,包括自定义类,可以根据具体需求重写该方法实现自定义的比较逻辑。
- == 运算符适用于比较基本数据类型的值以及对象引用的地址
异常
- 异常分类:
- Java 中的异常分为两大类:Checked Exception(已检查异常)和 Unchecked Exception(未检查异常)。
- 已检查异常是指继承自 Exception 类或其子类的异常,在编译时就需要进行处理或声明抛出。
- 未检查异常是指继承自 RuntimeException 类或其子类的异常,编译器不会强制要求进行处理或声明抛出。
- 异常处理方式:
- try-catch 块:使用 try 块来包含可能抛出异常的代码,然后通过 catch 块来捕获并处理特定类型的异常。
- throws 关键字:对于已检查异常,可以在方法签名中使用 throws 关键字声明该方法可能抛出的异常,由调用者来处理。
- finally 块:不管代码是否抛出异常,finally 块中的代码都会被执行,通常用于资源释放等清理操作。
- 自定义异常:
- Java 允许开发人员通过创建自定义异常类来满足特定的业务需求。
- 自定义异常类应该继承自 Exception 或其子类,一般推荐继承自 RuntimeException 类,以便让异常可以在运行时自动抛出。
- 自定义异常类通常会提供构造方法和错误信息,可以添加额外的字段或方法以满足特定业务需求。
在回答面试题时,可以结合具体的代码示例来说明异常分类、异常处理方式以及自定义异常的概念和应用。展示对异常处理机制的理解和熟练应用能够为面试官展示你在Java开发中处理异常的能力。
线程
- 线程创建:
- 在Java中,可以通过两种方式创建线程:继承 Thread 类和实现 Runnable 接口。
- 继承 Thread 类需要重写 run() 方法,该方法包含了线程需要执行的代码逻辑。
- 实现 Runnable 接口需要实现 run() 方法,并将其作为参数传递给 Thread 对象。
- 线程生命周期:
- 线程的生命周期包括五个状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和终止(Terminated)。
- 新建状态是指线程对象被创建但尚未启动的状态。
- 就绪状态是指线程具备运行条件,等待CPU调度执行的状态。
- 运行状态是指线程正在执行其任务的状态。
- 阻塞状态是指线程暂时停止执行,直到某个条件满足才能继续执行的状态。
- 终止状态是指线程执行完任务或异常终止的状态。
- 并发处理:
- 并发是指多个线程可以同时执行的情况,可以提高程序的处理效率。
- 在并发处理中,可能会出现竞态条件和临界区问题。竞态条件是多个线程访问共享资源时导致结果依赖于线程执行的具体时序。
- 临界区问题是指多个线程同时访问共享资源时可能出现数据不一致的情况。
- 可以通过使用同步机制(如锁、信号量等)来解决并发处理中的竞态条件和临界区问题。
- Java中提供了 synchronized 关键字和 Lock 接口等用于实现同步的机制。
io种类,对象流
- IO种类:
- Java中常见的IO种类有:字节流和字符流。
- 字节流(Byte Stream)用于处理二进制数据,以字节为单位进行读写。常见的字节流类有 InputStream 和 OutputStream。
- 字符流(Character Stream)用于处理文本数据,以字符为单位进行读写。常见的字符流类有 Reader 和 Writer。
- 对象流:
- 对象流是一种特殊的IO流,用于在Java程序中对对象进行读写操作。
- 对象流可以将Java对象直接写入到文件或网络流中,也可以从文件或网络流中读取对象。
- Java提供了 ObjectInputStream 和 ObjectOutputStream 类来实现对象流的读写操作。
- 对象流的优点是可以方便地将复杂的对象进行序列化和反序列化,便于对象的存储和传输。
list set map区别
- List:
- List是一种有序的集合,可以包含重复元素。
- List的实现类有ArrayList、LinkedList和Vector等。
- List允许通过索引访问元素,可以根据位置进行插入、删除和修改操作。
- List适用于需要保留元素插入顺序以及允许重复元素的场景,例如需要维护一个有序的数据集合。
- Set:
- Set是一种不允许重复元素的集合,没有固定的顺序。
- Set的实现类有HashSet、TreeSet和LinkedHashSet等。
- Set通过哈希表或二叉树等数据结构实现元素的存储和查找,具有较快的查找性能。
- Set适用于需要检查元素是否存在以及去重的需求,例如存储唯一的用户ID或关键词等。
- Map:
- Map是一种键值对(Key-Value)的集合,每个键对应一个值,键不允许重复。
- Map的实现类有HashMap、TreeMap和LinkedHashMap等。
- Map通过哈希表或二叉树等数据结构实现键值对的存储和查找。
- Map适用于根据键快速查找对应的值的场景,例如存储用户信息、缓存数据等。
总结:
- List适用于需要保留元素顺序且允许重复的场景。
- Set适用于需要去重或检查元素是否存在的场景。
- Map适用于根据键快速查找对应值的场景。
arraylist linkedlist 区别
- 内部实现:
- ArrayList是基于数组实现的动态数组,它的元素存储在连续的内存空间中。
- LinkedList是基于链表实现的双向链表,它的元素存储在通过指针连接的节点中。
- 插入和删除操作:
- ArrayList对于中间位置的插入和删除操作性能较差,因为需要移动其他元素来保持连续性。
- LinkedList在任意位置的插入和删除操作性能较好,只需要调整相邻节点的指针。
- 随机访问:
- ArrayList通过索引可以进行快速随机访问,时间复杂度为O(1)。
- LinkedList需要从头或尾开始遍历链表,直到达到目标位置,时间复杂度为O(n)。
- 空间占用:
- ArrayList在创建时会分配一块连续的内存空间,可能会浪费一些空间。
- LinkedList在每个元素节点中都存储了前后节点的引用,会占用更多的内存空间。
- 用途:
- ArrayList适用于频繁读取和随机访问的场景,例如需要根据索引获取元素的情况。
- LinkedList适用于频繁插入和删除元素的场景,例如实现栈、队列或需要频繁改变顺序的情况。
总结:
- ArrayList适用于读取和随机访问较多的场景,内存占用相对较少。
- LinkedList适用于插入和删除较多的场景,能够在任意位置进行高效操作。
map有序?? 如何有序
- 如何实现有序:
- 从Java 8开始,引入了新的Map实现类LinkedHashMap,它可以维护元素的插入顺序或访问顺序,因此可以实现有序的特性。LinkedHashMap是HashMap的子类,在HashMap的基础上添加了一个双向链表来维护元素的顺序,他提供了2种有序的方式:
- 插入顺序(Insertion Order) 插入顺序(Insertion Order)
- 从Java 8开始,引入了新的Map实现类LinkedHashMap,它可以维护元素的插入顺序或访问顺序,因此可以实现有序的特性。LinkedHashMap是HashMap的子类,在HashMap的基础上添加了一个双向链表来维护元素的顺序,他提供了2种有序的方式:
反射
- 什么是反射
- 反射是指在程序的运行过程中动态的获取成员变量、⽅法、构造函数等信息,并可以在运⾏时调⽤对象的⽅法,创建对象的实例,操作对象的属性等。
- Java中,反射机制主要通过以下⼏个类实现:
- Class类:表⽰类的类型,通过该类可以获取类的构造函数、成员变量、⽅法等信息。
- Constructor类:表⽰类的构造函数类型,通过该类可以创建类的实例。
- Field类:表⽰类的成员变量类型,通过该类可以获取、设置类的成员变量的值。
- Method类:表⽰类的⽅法类型,通过该类可以调⽤类的⽅法。
- 尽管反射机制可以⽅便地获取类的信息并进⾏操作,但是它也具有⼀定的缺点,如性能较差、代码可读性差、安全性差等。因此,在实际开发中,应该根据实际情况谨慎使⽤反射机制。
- 如何获取反射
- ⾸先找到类型的Class对象
Class.forName(类型)
类型.class
对象.getClass() - 然后在类型上查找⽅法
getMethods();//获取包括⾃⾝和继承(实现)过来的所有的public⽅法
getDeclaredMethods();//获取⾃⾝所有的⽅法
getMethod(⽅法签名);//表⽰获取指定的⼀个公共的⽅法,包括继承的
getDeclaredMethod(⽅法签名);//表⽰获取本类中的⼀个指定的⽅法,不包括继承的
⽅法 ⽅法签名包括:⽅法的名字,参数的Class类型列表
- ⾸先找到类型的Class对象
HTTP请求结构
⼀个HTTP请求报⽂由四个部分组成:请求⾏、请求头部、空⾏、请求数据
包装类作用 及转换
-
支持泛型和集合:泛型和集合框架只接受对象作为参数,而不接受基本数据类型。通过使用包装类,可以将基本数据类型作为对象来传递给泛型和集合。
-
Integer:int Long:long Double:double Float:float
-
Byte:byte Short:short Boolean:boolean Character:char
-
自动装箱和拆箱:自动装箱是指将基本数据类型自动转换为对应的包装类对象,拆箱则是相反的过程。这些转换都是在编译器层面完成的,无需显式调用。
int num = 10;
Integer wrappedNum = num; // 自动装箱
int unwrappedNum = wrappedNum; // 自动拆箱 -
构造函数和静态方法:使用包装类的构造函数或者静态方法来实现装箱和拆箱。
int num = 10;
Integer wrappedNum = new Integer(num); // 装箱
int unwrappedNum = wrappedNum.intValue(); // 拆箱
get post区别
GET⽅式是通过请求⾏传递⽤户所输⼊的内容,其内容会全部显⽰的浏览器的地址栏中;
- GET提交具有⻓度限制
- GET是从服务器上获取数据
- GET请求没有HTTP消息体
- POST提交将⽤户所输⼊数据放到HTTP消息体中发送到服务器端
- POST没有提交⻓度限制
- POST是向服务器传送数据
数组复制 排序
-
复制
//使用循环遍历数组,并逐个将元素复制到目标数组中
int[] sourceArray = {1, 2, 3, 4, 5};
int[] targetArray = new int[sourceArray.length];for (int i = 0; i < sourceArray.length; i++) {
targetArray[i] = sourceArray[i];
}//使用Arrays.copyOf()方法进行数组复制。
int[] sourceArray = {1, 2, 3, 4, 5};
int[] targetArray = Arrays.copyOf(sourceArray, sourceArray.length); -
数组排序:
// 使用Arrays.sort()方法对数组进行排序,默认是按升序排序。
int[] array = {5, 2, 8, 1, 4};
Arrays.sort(array); // 默认升序排序
System.out.println(Arrays.toString(array)); // [1, 2, 4, 5, 8]//如果要进行降序排序,可以使用自定义比较器(Comparator)。
Integer[] array = {5, 2, 8, 1, 4};
Arrays.sort(array, Collections.reverseOrder()); // 降序排序
System.out.println(Arrays.toString(array)); // [8, 5, 4, 2, 1]
web-数据库相关
css选择器,使用方法及优先级
- 选择器
- 元素选择器:通过标签名选择元素,例如 div 选择所有的
元素。
- 类选择器:通过类名选择元素,以.开头,
。
- ID选择器:通过ID选择元素,以#开头,
。
- 属性选择器:通过元素的属性选择元素,例如 [type=“text”] 选择所有 type 属性为 text 的元素。
- 关系选择器:通过元素之间的关系选择元素,例如 div p 选择所有在
元素内部的
元素。
- 伪类选择器:通过元素的状态或位置选择元素,例如 :hover 选择鼠标悬停在元素上的状态
- 组合选择器:将多个选择器组合在一起选择元素,例如 div, p 选择所有的
和
元素。
- 优先级
-
内联样式:使用style属性直接在HTML元素上定义样式。内联样式具有最高的优先级,将覆盖其他选择器定义的样式。
htmlCopy Code
This text will be red. -
ID选择器:给元素添加一个唯一的ID,并使用ID选择器设置样式。ID选择器的优先级较高。
htmlCopy Code
This text has a unique style. -
类选择器和属性选择器:使用类选择器或属性选择器为元素设置样式。它们的优先级较低于ID选择器。
This text has a class style. -
外部样式表:使用外部CSS文件链接到HTML文件,并在CSS文件中定义样式。外部样式表的优先级较低于内嵌样式表和内联样式。
-
!important
多个样式规则都使用了!important时,很难确定哪个规则具有更高的优先级,并且可能出现样式冲突的情况。
一旦某个样式规则使用了!important,其他相同优先级的规则将无法覆盖该样式,除非使用更高优先级的选择器或再次使用!important来覆盖
不可继承性:!important会取消样式的继承性,导致样式无法按照正常的层级关系传递给子元素。这可能会导致样式无法正确应用于子元素。
js使用方法
-
内联方式:将JavaScript代码直接嵌入到HTML文件中的
VUE的生命周期,常用指令及命令
- beforeCreate:在实例初始化之后、数据观测之前被调用。此时,实例的属性和方法还未初始化。
- created:在实例创建完成后被调用。可以在这个钩子函数中进行数据的初始化、Ajax请求等操作,但此时模板还未编译成HTML。
- beforeMount:在挂载之前被调用。在该钩子函数中,模板已经编译成HTML,但尚未挂载到页面上。
- mounted:在实例挂载到页面后被调用。此时,实例已经被创建,并且挂载至页面中,可以访问DOM元素。
- beforeUpdate:在响应式数据更新时调用,但在更新之前DOM尚未重新渲染。
- updated:在数据更新导致DOM重新渲染后被调用。
- beforeDestroy:在实例销毁之前调用。可以在这个钩子函数中进行清理工作,比如清除定时器、解绑全局事件等。
- destroyed:在实例销毁后调用,此时Vue实例的所有东西都已解绑,所有的事件监听器被移除,所有的子实例也被销毁。
常用的Vue指令有:
- v-if:根据表达式的值来条件性地渲染元素。
- v-for:循环渲染数组或对象的数据生成多个元素。
- v-bind:动态绑定HTML属性或组件props。
- v-on:绑定事件监听器,用于处理DOM事件。
- v-model:实现表单元素与Vue实例中数据的双向绑定。
- v-show:根据表达式的值来显示或隐藏元素,通过CSS的display属性控制。
- v-text:更新元素的textContent。
- v-html:更新元素的innerHTML。
数据库数据类型
- 常见的基本数据类型包括整数类型(int,tinyint,bigint等)、浮点数类型(float,double等)、字符类型(char,varchar等)、日期时间类型(date,datetime等),如果内容篇幅过长可使用text
数据库约束种类
- 主键约束(Primary Key Constraint):用于唯一标识表中的记录。主键约束要求被约束的字段(或字段组合)的值是唯一的且非空的,通常用于快速检索和识别表中的记录。
- 唯一约束(Unique Constraint):用于保证被约束字段(或字段组合)的值在表中是唯一的,但允许为空值。唯一约束可以用于避免数据重复和提高数据查询效率。
- 非空约束(Not Null Constraint):用于限制某个字段不允许为空值。非空约束可以保证表中的某列始终具有有效值,确保数据的完整性。
- 检查约束(Check Constraint):用于限制字段的取值范围或满足特定条件。检查约束通过指定一个逻辑表达式来验证数据的合法性,如果表达式为假,则不允许插入或更新该行数据。
- 默认约束(Default Constraint):用于给字段设置一个默认值,如果在插入数据时未提供该字段的值,则将使用默认值。默认约束可以确保表中的特定字段始终具有一个默认值。
分页 排序 分组 去重 聚合函数 关联查询
- 分页查询 limit 格式: limit 跳过的条数,请求的条数(每页的条数) , *跳过的条数=(请求的页数-1)*每页的条数
- 排序 order by 格式: order by 字段名 asc升序(默认)/desc降序
- 去重 distinct 例如 : select distinct dept_id from emp
- 聚合查询 平均值avg(字段名) 最大值/最小值max/min(字段名) 求和sum(字段名) 计数count(*)
- 分组 group by
- having having关键字专门用来写聚合函数条件的, 并且需要和分组group by结合使用, 写在分组的后面
- 关联查询:
- 等值连接: select 字段信息 from A,B where A.x=B.x(关联关系) and 其它条件
- 内连接格式: select 字段信息 from A join B on A.x=B.x(关联关系) where 其它条件;
- 外连接: 格式: select 字段信息 from A left/right join B on A.x=B.x where 其它条件;
SQL优化 视图 索引
-
优化: 确保查询语句只选择必要的列,避免不必要的数据传输和处理。可以通过使用EXPLAIN语句来分析查询执行计划,找出需要创建或调整的索引。可以通过使用EXPLAIN语句来分析查询执行计划,找出需要创建或调整的索引。
-
视图: 简化复杂的查询:将复杂的查询转换为简单的视图,以提高可读性和可维护性。隐藏敏感数据:通过视图,可以限制用户仅查看他们需要的数据,保护敏感信息的安全性。
-
索引: 1. 选择唯一性索引 2.为经常需要排序、分组和联合操作的字段建立索引 3.尽量使用数据量少的索引 4. 尽量使用前缀来索引
crud 基本语法(增删改查)
- 增 insert into 表名 values(值1,值2,值3…) insert into 表名(字段1,字段2)values(值1,值2)
- 删 delete from 表名 where 条件;
- 改 update 表名 set 字段名=值 ,字段名=值 where 条件;
- 查 select 字段名称 from 表名 where条件;
事务特征
- ACID特性:事务具有ACID(原子性、一致性、隔离性和持久性)特性。可以解释每个特性的含义:
- 原子性:要么全部执行成功,要么全部失败
- 一致性:事务在执行前后,数据库的状态必须保持一致。
- 隔离性:隔离性确保了事务间的并发执行不会导致数据不一致或其他问题。
- 持久性:一旦事务提交,对数据库的修改应该是永久性的,即使在系统故障的情况下也应该保持。
SQL分类
- 数据操作语言(Data Manipulation Language,简称DML)增删查改
- 数据操作语言(Data Manipulation Language,简称DML)创建表、修改表和删除表
- 数据控制语言(Data Control Language,简称DCL)GRANT:用于授予用户对数据库对象的特定; REVOKE:用于收回用户对数据库对象的权限。
- 事务控制语言(Transaction Control Language,简称TCL)
- BEGIN/START TRANSACTION:用于开始一个事务。
- COMMIT:用于提交事务,将更改保存到数据库中。
- ROLLBACK:用于回滚事务,撤消之前的所有更改。
JDBC 连接步骤
- 加载数据库驱动程序:首先,需要加载适当的数据库驱动程序,以便能够与特定数据库建立连接。这可以通过使用Class.forName()方法来实现。例如,如果要使用MySQL数据库,可以加载MySQL驱动程序如下所示:
javaCopy CodeClass.forName(“com.mysql.jdbc.Driver”); - 建立数据库连接:在加载了驱动程序之后,可以通过创建一个Connection对象来建立与数据库的物理连接。需要提供数据库的URL、用户名和密码等连接参数。例如,连接到名为"mydatabase"的MySQL数据库,可以使用以下代码:
javaCopy CodeString url = “jdbc:mysql://localhost:3306/mydatabase”;
String username = “your-username”;
String password = “your-password”;
Connection connection = DriverManager.getConnection(url, username, password); - 创建执行SQL语句的Statement或PreparedStatement对象:通过使用连接对象的createStatement()方法或prepareStatement()方法,可以创建一个用于执行SQL语句的Statement或PreparedStatement对象。例如,使用Statement对象执行查询语句:
javaCopy CodeStatement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(“SELECT * FROM mytable”); - 执行SQL语句:使用创建的Statement或PreparedStatement对象的方法,可以执行各种SQL语句,如查询、更新、插入和删除等。例如,执行一个更新语句:
javaCopy Codeint rowsAffected = statement.executeUpdate(“UPDATE mytable SET column1=‘value’ WHERE column2=‘condition’”); - 处理结果:如果执行的是查询语句,可以使用ResultSet对象来获取结果集中的数据。可以使用各种ResultSet的方法来访问和处理结果集中的数据。例如,遍历结果集并打印每一行的数据:
javaCopy Codewhile (resultSet.next()) {
String column1Value = resultSet.getString(“column1”);
int column2Value = resultSet.getInt(“column2”);
System.out.println("Column1: " + column1Value + ", Column2: " + column2Value);
} - 关闭连接和释放资源:在完成数据库操作后,需要关闭连接和释放相关的资源,以便释放数据库服务器的资源。可以使用close()方法来关闭连接、Statement对象和ResultSet对象。例如:
javaCopy CoderesultSet.close();
statement.close();
connection.close();
SQL注入
- 执行查询语句之前要做好SQL注入的检查,使用JDBC中的PreparedStatement执行预编译SQL语句来避免SQL注入攻击。
连接池
- 导入依赖 -> 配置连接池参数->创建连接池对象->获取链接->使用连接->释放连接->销毁连接池
- 它的作用是为应用程序提供高效的数据库连接,避免因频繁建立和关闭数据库连接而导致的性能问题。连接池通常采用预创建连接的方式,即在应用程序启动时就创建一定数量的数据库连接,并将其保存在连接池中。当应用程序需要连接数据库时,直接从连接池中获取连接对象即可,使用完毕后将连接返回给连接池而不是关闭连接。
- 连接池的优点是提高了应用程序的性能、可扩展性和灵活性,但需要占用一定的系统资源。
框架啦!!
maven的作用,使用
- 依赖管理:Maven可以自动下载和管理第三方依赖库,并解决依赖之间的冲突。
- 构建管理:Maven提供了一种标准化的项目构建方式,可以自动编译、测试、打包和部署项目。
- 发布管理:Maven可以帮助开发人员自动化地发布项目到仓库或服务器上。
spring介绍 核心IOC, DI ,AOP 表达式
- 介绍:Spring是一个开源的轻量级应用程序开发框架,主要用于构建Java应用程序。它提供了一种综合性的编程和配置模型,以简化企业级应用的开发过程。Spring框架的核心特点包括控制反转(IoC)、依赖注(DI)面向切面编程(AOP)和表达式语言(SpEL)等。
- 控制反转(IOC)控制反转是Spring框架的核心理念之一。它通过将对象的创建和依赖关系的管理转移到容器中,实现了对象之间的解耦。开发人员只需要通过配置文件或注解告诉Spring容器如何创建和组装对象,从而实现了对对象的控制反转。
- 依赖注入(DI)依赖注入是控制反转的具体实现方式之一,它是指将对象的依赖关系通过容器自动注入到对象中。可以通过属性/Setter/构造方法注入,通过使用依赖注入,开发人员可以将对象之间的耦合度降低,提高代码的可读性和可维护性。
- 面向切面编程(AOP)面向切面编程是Spring框架的另一个核心特点,它通过在不改变原有代码逻辑的情况下,添加一些横切关注点(比如日志记录、事务管理等),从而实现对系统功能的增强。Spring的AOP模块基于代理模式和动态代理技术实现,可以在运行时动态地将横切逻辑织入到目标对象中。
- 表达式语言(SpEL)Spring表达式语言(SpEL)是Spring框架引入的一种强大的表达式语言,用于在运行时对对象进行求值和处理SpEL支持访问对象的属性、调用对象的方法、进行逻辑运算和数学计算,并且可以与Spring的注解和配置文件结合使用,提供了更灵活和动态的配置方式。
MVC 流程
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
单例模式
- 概念: 单例模式是一种创建型设计模式,旨在确保一个类只有一个实例,并提供全局访问点以供其他对象使用
- 单例模式的优点包括:
- 全局唯一实例,方便对实例进行控制和管理。
- 节省系统资源,避免重复创建实例。
- 单例模式的缺点包括:
- 违背了单一职责原则,将创建和使用职责集中在一起。
- 可能会引起不必要的资源占用。
- 可能会导致代码的可测试性下降。
Spring-Boot优势
- 简化的配置:Spring Boot通过自动化配置和约定大于配置的原则,大大简化了应用程序的配置过程。它提供了许多默认配置,可以根据应用程序的需求进行覆盖或修改。同时,Spring Boot还提供了属性文件和注解等方式来灵活配置应用程序的行为。
- 快速开发:Spring Boot通过提供各种开箱即用的功能模块和集成组件,加快了应用程序的开发速度。它内置了许多常用的功能,如Web开发、安全认证、数据库访问、缓存、消息队列等,开发人员可以直接使用这些功能,而无需编写大量的样板代码。
- 独立运行:Spring Boot应用程序可以作为独立的可执行文件运行,无需依赖外部的应用服务器。它内嵌了Servlet容器(如Tomcat、Jetty),可以直接以类似于传统Java应用程序的方式启动和运行。这种独立运行的特性使得部署和分发应用程序变得非常简单。
MyBatis作用
- 数据库访问封装:MyBatis 封装了数据库连接、事务管理、预处理语句等底层细节,开发人员只需要专注于 SQL 语句和参数的编写即可。
- 灵活的 SQL 控制:过使用 MyBatis 提供的强大的动态标签(如if、choose、foreach等),可以根据实际需求动态生成 SQL 语句,从而避免了手动拼接 SQL 字符串的麻烦。
- 对象关系映射(ORM)支持开发人员可以通过配置映射文件,将 Java 对象与数据库表的字段进行映射,从而实现对象的持久化操作。
- 缓存支持:一级缓存是会话级别的缓存,它位于会话内部,可以直接共享同一个会话的多个数据库操作。二级缓存是跨会话级别的缓存,可以共享多个会话之间的数据库操作结果。通过合理配置缓存,可以减少重复的数据库访问,提升系统的性能。
- 可扩展性:MyBatis 是一个非常灵活和可扩展的框架。它提供了许多插件接口和扩展点,可以根据需要自定义功能。
动态SQL
<!-- 批量删除-数组格式:
collection用来设置遍历对象的类型,
item设置遍历出每一个变量的名称
separator设置分隔符
注意:注释一定要放在delete标签的外面,不能放在里面,放在里面会被当做sql语句执行!
-->
<delete id="deleteByIds1">
DELETE FROM 表名 WHERE id IN(
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</delete>
<!-- 动态修改
问题:如果修改局部可能会导致多出逗号
使用<set>标签,会自动识别是否多逗号,如果最后一个是逗号会自动去掉逗号
-->
<update id="dynamicUpdate">
UPDATE comment
<set>
<if test="实体类属性值!=null">字段=#{created},</if>
<if test="实体类属性值!=null">字段=#{实体类属性值},</if>
</set>
WHERE id=#{id};
</update>
<!-- 1.重复SQL抽取-sql标签 -->
<sql id="selectSql">
SELECT * FROM t_category
</sql>
<select id="selectAll" resultType="实体类路径">
<!--2.通过include标签复用-include标签-->
<include refid="selectSql"></include>
</select>
MyBatis中#{}和${}的区别
- Mybatis中的#{}格式的占位符是预编译的,即SQL语句会先经过词法分析、语义分析,再编译,当编译完成后,再将值代入到编译结果中一并执行!由于是预编译的,此前已经完成语义分析,语义是已经确定的,占位符的位置一直是某个值,不可能是字段名,所以,所有值都不需要使用单引号框住!并且,由于是预编译的,所以不存在SQL注入的问题!使用这种占位符时,占位符位置只能表示某个值!
- Mybatis中的${}格式的占位符不是预编译的,即先将值代入到SQL语句中,然后,并代入后的结果再执行词法分析、语义分析、编译,最终执行!由于不是预编译的,而是先将值代入到SQL语句中,对于非数值、非布尔值的其它值而言,如果不加单引号,就会被误以为是字段名,所以,所有非数值、非布尔值的其它值都必须使用一对单引号框住!并且,由于不是预编译的,向SQL语句中传入的值有可能改变SQL的语义,是存在SQL注入风险的!使用这种占位符时,占位符位置可以表示SQL语句的任何片段!
接受参数的请求方式种类
- GET 请求:GET 请求通过 URL 的查询字符串传递参数。GET 请求的参数会暴露在 URL 中,适用于参数较少、参数无敏感信息的情况。
- POST 请求:POST 请求将参数包含在请求体中,不会暴露在 URL 中。参数以键值对的形式发送给服务器。通常用于传输大量数据或包含敏感信息的情况,参数数量和长度没有明确限制。
- PUT 请求:PUT 请求用于向服务器发送数据,更新或创建资源。类似于 POST 请求
- DELETE 请求:DELETE 请求用于删除服务器上的资源。
restful风格
Redis解释支持类型 ,应用场景
小细节:命令不区分大小写,而key是区分大小写的;help @类型名词
官网命令大全:http://www.redis.cn/commands.html
String
- 常用:set key value;get key
- 同时设置/获取多个键值对:MSET key value [key value];MGET key [key…]
- 递增数字:INCR key
- 增加指定整数:INCRBY key increment
- 递减数字:DECR key
- 减少指定整数:DECRBY key decrement
- 获取字符串长度:STRLEN key
- 分布式锁:set key value Ex seconds [NX|XX]
- 应用场景:商品编号、订单号采用INCR命令生成、喜欢的文章点赞
hash
- Map<String,Map<Object,Object>>
- 一次设置一个字段值:HSET key field value
- 一次获取一个字段值:HGET key field
- 一次设置多个字段值:HMSET key field value [field value…]
- 一次获取多个字段值:HMGET key field [field…]
- 获取所有字段值:hgetall key
- 获取某个key内的全部数量:hlen
- 删除一个key:hdel
- 应用场景:购物车,小中厂使用
list
- 向列表左边添加元素:LPUSH key value [value…]
- 向列表右边添加元素:RPUSH key value [value…]
- 查看列表:LRANGE key start stop
- 获取列表中元素的个数:LLEN key
- 应用场景:微信文章订阅公众号
set
- 添加元素:SADD key member [member…]
- 删除元素:SREM key member [member…]
- 获取集合中的所有元素:SMEMBERS key
- 判断元素是否在集合中:SISMEMBER key member
- 获取集合中的元素个数:SCARD key
- 从集合中随机弹出一个元素,元素不删除:SRANDMEMBER key [数字]
- 从集合中随机弹出一个元素,出一个删一个:SPOP key [数字]
- 集合的差集运算:属于A但不属于B的元素构成的集合 SDIFF key [key…]
- 集合的交集运算:属于A同时也属于B的元素构成的集合 SINTER key [key…]
- 集合的并集运算:属于A或者属于B的元素构成的集合 SUNION key [key…]
- 应用场景:微信抽奖小程序、微信好友共同关注、QQ推荐可能认识的人、朋友圈点赞
zset
- 向有序集合中加入一个元素和该元素的分数
- 添加元素:ZADD key score member [score member…]
- 按元素分数从小到大顺序,返回索引start到stop之间的所有元素:ZRANGE key start stop [WITHSCORES]
- 获取元素的分数:ZSCORE key member
- 删除元素:ZREM key member [member…]
- 获取指定分数范围的元素:ZRANGEBYSCORE key min max WITHSCORES
- 增加某个元素的分数:ZINCRBY key increment member
- 获取集合中的元素数量:ZCARD key
- 获取指定分数范围内的元素个数:COUNT key min max
- 获取元素排名:从大到小:ZERVRANK key member;从小到大:ZRANK key member
- 按照排名范围删除元素:ZREMRANGEBYRANK key start stop
- 应用场景:根据商品销售对商品进行排序显示、抖音热搜
对Redis分布式锁的理解, 删key的时候有什么问题
- synchronized单机版OK,上分布式,分布式部署后,单机锁还是出现超卖现象,需要分布式锁
- nginx分布式微服务 单机锁不行
- 取消单机锁上redis分布式锁setnx
- 只加了锁,没有释放锁, 出异常的话,可能无法释放锁, 必须要在代码层面finally释放锁
- 宕机了,部署了微服务代码层面根本没有走到finally这块,没办法保证解锁,这个key没有被删除,需要有lockKey的过期时间设定
- 为redis的分布式锁key,增加过期时间,此外,还必须要setnx+过期时间必须同一行的原子性操作
- 必须规定只能自己删除自己的锁,你不能把别人的锁删除了,防止张冠李戴,1删2,2删3
- lua或者事务
- redis集群环境下,我们自己写的也不OK,直接上RedLock之Redisson落地实现
Redis缓存过期淘汰策略
redis默认内存多少?在哪里查看? 如何设置修改?
- 打开redis配置文件,设置maxmemory参数,maxmemory是bytes字节类型,注意转换。
- 在64位操作系统下不限制默认内存大小,32位操作系统下最多使用3GB
- 一般通过Redis设置内存为最大物理内存的四分之三,即0.75
- 查看redis内存使用情况:info memory
- 通过命令修改内存大小:config set maxmemory 数值
真要打满了会怎么样?
如果Redis内存使用超出了设置的最大值会怎样? 引出Redis缓存过期淘汰策略
过期的删除策略:
定期删除、惰性删除、折中
- noeviction:不会驱逐任何key
- allkeys-lru:对所有key使用LRU算法进行删除
- volatile-lru:对所有设置了过期时间的key使用LRU算法进行删除
- allkeys-random:对所有key随机删除
- volatile-random:对所有设置了过期时间的key随机删除
- volatile-ttl:删除马上要过期的key
- allkeys-lfu:对所有key使用LFu算法进行删除
- volatile-lfu:对所有设置了过期时间的key使用LFU算法进行删除
security 解释,认证流程,授权