1.java基础
String类为什么是final类型的?
https://blog.csdn.net/weixin_44973961/article/details/107409361
1.static 关键字:
1、修饰函数的局部变量:
特点:只执行一次,运行一开始就开辟了内存,内存放在全局
2、修饰全局函数和全局变量:
特点:只能在本源文件使用
3、修饰类里面的成员变量:
特点:不依赖于类对象的存在而存在(可直接调用,要进行外置声明)
Object方法 重点(hashmap)
1. getClass方法是获取类对象的
2. hashcode方法 返回的是hash码
3. equals()方法 在字符串判断两个值相等的
4. toString方法 java中的类会重写这个方法,比如:list会重写这个方法
5. finalize方法 当垃圾回收器将要回收对象所占内存之前被调用
6. wait方法 线程等待
7. clone方法 克隆
8. notify方法 唤醒一个线程
9. notifyAll方法 唤醒所有线程
集合 重点
List和set以及Map 聊一下?
List接口和Set接口属于Collection接口,Map接口和Collection接口并列存在(同级)
1.List(元素可重复性,有序性)
arraylist底层是数组实现
linkedlist底层是双向链表
2.Set(具有唯一性,无序性)
hashset是无序且唯一的是基于hashmap实现,底层采用的hashmap来保存元素
linkedhashset:是继承hashset
treeset:无序的,且唯一底层是采用红黑树
注:LinkedHashSet是一种有序的Set集合,即其元素的存入和输出的顺序是相同的。
3.Map(采用键值对<key,value>存储元素,key键唯一)
hashmap:底层结构是数组+链表+红黑树,无序,线程不安全,效率高,允许有null(key和value都允许),父类是AbstractMap 元素不能重复 ---重点
treemap:底层结构是红黑树,有序,将数据按照key排序,默认是升序排序。
hashtable:底层结构是哈希表,无序,线程安全,效率低,不允许有null值,父类是Dictionary
collection所有集合的顶层父类:集合都有的crud都是来自这里
collection下面有
list set map
首先说一下list
list下面有
arraylist底层是数组实现
linkedlist底层是双向链表
set下面有hashset
hashset是有序且唯一的是基于hashmap实现,底层采用的hashmap来保存元素
linkedhashset:是继承hashset
treeset:有序的,且唯一底层是采用红黑树
Map
hashmap:在jdk1.8之前底层是使用数组+链表,数组是hashmap的主体而链表是为了解决哈希冲突,在jdk1.8之后链表长度大于默认阈值8之后将改为红黑树,减少搜索的时间消耗
linkedhashmap是继承自hashmap所以底层也是数组或者链表或者红黑树,在此基础上添加了一条双向链表
2.java集合排序怎么实现? 重点(排序 删除元素)
第一种是实体类实现Comparable ,重写compareTo的方法 —重点
删除一个元素,用for循环?
使用迭代器中的remove方法
Java集合怎么去重的?说一下思想
1.使用set去重
2.用!list.contains(list.get(i)),如果集合中部存在就添加到新集合中
Java集合中的hashcode和equals有什么区别和作用都行? —重点
1、若两个对象equals返回true,则hashCode有必要也返回相同的int数;
2、若两个对象hashCode返回相同int数,则equals不一定返回true。
3、Hashcode比较的是hash值,equals比较的是内存地址
5.3排序算法
冒泡排序:
选择排序
二分查找:
5.4 StringBuffere和StringBuilder
1.在StringBuffer后面追加字符串方法: 对象名.append(字符串)
StringBuffer sb = new StringBuffer(“this”).append(" is bread");
3.查看 StringBuffer的容量和长度
容量: 对象名.capacity()
长度 : 对象名.length()
1.在StringBuilder后面追加字符串方法: 对象名.append(字符串)
2.在StringBuilder中插入字符串的方法: 对象名.insert(索引位置,字符串)
3.查看 StringBuilder的容量和长度
容量 : 对象名.capacity()
长度 : 对象名.length()
5.5 锁
悲观锁和乐观锁:是一种思想,可以用在很多方面
比如:数据库方面
悲观锁就是for update(锁定查询的行)
乐观锁就是version字段
JDK方面:
悲观锁就是sync
乐观锁就是原子类(内部使用CAS实现)
本质来说,就是悲观锁认为总会有人抢的
乐观锁就是认为,本质上没人抢
乐观锁的业务场景及实现方式:
每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。
乐观锁:比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量。
5.6 线程 重点
- 创建线程主要有三种方式:
1. 继承Thread类创建线程类
2. 通过Runnable接口创建线程类
3. 通过Callable和Futere创建线程
2.创建线程池的几种方式:
newFixedThreadPool(int nThreads)
创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程
newCachedThreadPool()
创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制.
newSingleThreadExecutor()
这是一个单线程的 Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行.
newScheduledThreadPool(int corePoolSize)
创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于 Timer。
3.线程的声明周期
(1)新建(new Thread)
(2)就绪(runnable)
(3)运行(running)
(4)死亡(dead)
(5)堵塞(blocked)
(6)正在睡眠:用 sleep(long t) 方法可使线程进入睡眠方式
(7)正在等待:调用 wait()方法
5.7 多线程
什么是进程?
电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。比如下图中的QQ、酷狗播放器、电脑.
什么是线程?
进程中的最小执行单位就是线程,并且一个进程中至少有一个线程
提到多线程这里要说两个概念,就是串行和并行
串行: 就比如说下载多个文件,A文件下载完成之后再去下载b文件
并行:下载多个文件,开启多条线程,多个文件同时进行下载
如何确保线程的安全?
1.synchronized关键字,就是用来控制线程同步的,保证我们的线程在多线程环境下,不被多个线程同时执行,确保我们数据的完整性,使用方法一般是加在方法上。
2.在需要的时候去手动的获取锁和释放锁,甚至我们还可以中断获取以及超时获取的同步特性,但是从使用上说Lock明显没有synchronized使用起来方便快捷。
final,finally,finalize三个关键字的区别?
final
当这个关键字修饰一个类时,意味着他不能派生出新的子类,也就是说不能被继承,因此一个类不能被同时声明abstract和final。当final修饰变量或者方法时,可以保证他们在使用中不会被改变。被声明为final的变量必须在初始化时给定初值,以后在使用时只能被引用而不能被修改。同样,当final修饰一个方法时,这个方法不能被重载。
finally
异常处理时提供finally来执行任何清楚操作。如果抛出一个异常,那么相匹配的catch子句就会被执行,然后控制就会转入finally块。
finalize
方法名。finalize方法在垃圾回收器执行内存对象清理时会调用finalize()方法进行前期的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在Object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。
5.8 设计模式
1.单例设计模式:
正常情况下,一个类可以有无数个对象。
单例设计模式:一个类只能有一个对象。
实现步骤:
1.要把构造方法私有化(不允许外界创建对象)
2.为了使用该类的对象,我们在类中创建一个私有的静态的对象
3.在类中在提供一个public的静态的方法,获取这个对象,供其他类使用根据私有对象的赋值时机不同分为两种:
1.饿汉式(在对象创建之后直接赋值)
2.懒汉式(在方法被调用的时候赋值)
2.多例设计模式
多例设计模式:一个类可以创建有限个数的对象
实现步骤:
1.要把构造方法私有化(不允许外界创建对象)
2.在类中定义一个静态代码块(在类被加载进内存的时候,这个代码块就存在了),在类中定义一个集合(容器)用来存放类对象
3.在类中提供一个public的静态的方法,获取到这个集合里面的对象,供其他类使用
3.装饰者模式:
装饰者: 拥有一些个方法
被装饰者: 在被装饰者里面将装饰者构造进去,被装饰者可以有自己独特的方法,也可以引用装饰者的方法.
4.动态代理模式:
https://blog.csdn.net/huangwei18351/article/details/82460589
5.9 数据结构
栈:
特点: 先进后出(压栈和弹栈)
栈的入口 出口的都是栈的顶端位置
队列:
先进先出
队列的入口和出口各占一侧
数组:
特点: 查询快,增删慢
链表:
二叉树:
平衡二叉树:
红黑树:
2.框架
Spring
2.1 什么是Spring框架 ?
Spring是分层的 Java SE/EE应用 full-stack(全栈) 轻量级开源框架
2.2 使用Spring的步骤 ?
方案一:
1. 写一个java文件
2. 写一个配置文件 ,这个配置文件的名字应该是applicationContext.xml,把这个类放入Spring容器中
<bean id="自己写" class="java文件的权限定类名"></bean>
3. 启动Spring容器
4. 从Spring容器中把对象提取出来
5. 用此对象调用相关的方法
注: 使用Spring最少需要导入两个jar包,一个是Spring的核心包,在Spring的dist目录下.另一个是第三方包Commons-logging,在Spring的lib下
方案二:
首先配置一个xml文件,在里面配置bean还有彼此之间的依赖关系, 然后我会把这个xml读取出来 ,然后放到一个IOC一个容器中 然后启动这个ioc容器 然后去创造这个工厂对象,这个工厂对象有两种,第一个是BeanFctory他用的是一个懒汉式加载模式,就是当你需要的时候呢,你会通过getBean再把它生产出来,实例化这个bean,还有一个是application context的,这个是饿汉式的一个加载模式,容器初始化完毕之后,它就会实例化所有的bean,他俩是有这么一个关系的,就是BeanFctory是一个父接口,ApplicationContext是他的一个子接口,在这个工厂对象中呢会把bean对象实例化,实例完毕之后呢通过这个@Autowarit这个注解注入,可以注入我们想要的一个方法中,然后可以把这个bean给他取出来,去调用其中bean的方法就可以了
2.3 Spring的优势?
通过Spring提供的 IOC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度耦合。 用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
1. AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松实现。
2. 声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。
3. 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
4. 方便集成各种优秀框架
Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。
5. 降低JavaEE API的使用难度
Spring对JavaEEAPI(如JDBC、JavaMail、RPC等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。
6. Java源码经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。
常用注解:
@component
作用: 调用无参构造创建一个bean对象,并把对象存入spring的IOC容器,交由spring容器进行管理。相当于在xml中配置一个bean。
@controller
作用: 作用上与@Component。一般用于表现层的注解。
@service
作用: 作用上与@Component。一般用于业务层的注解。
@Repository
作用: 作用上与@Component。一般用于持久层的注解。
@Bean
作用: 用于把当前方法的返回值作为bean对象存入spring的ioc容器中
Spring里面的动态代理?
1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2.如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3.如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
(1)添加CGLIB库,SPRING_HOME/cglib/*.jar
(2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
Spring里面的beanfactory和applicationContext有什么区别?
0).ApplicationContext 是 BeanFactory接口的子接口
1)BeanFactory 采用的是延迟加载,第一次getBean的时候才会初始化Bean
2)ApplicationContext是对BeanFactory的扩展,提供了更多的功能
国际化处理
事件传递
Bean自动装配
各种不同应用层的Context实现
结论:开发中尽量使用ApplicationContext 就可以了
beanFactory和factorybean有什么区别吗?
BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
2.4 aop思想 声明事务 重点
抽取公共的代码,解耦合,方法调用公共的代码就行了.我们的开发可以更多的抽取这样的切面,让每个系统的开发只专注于核心的业务,而不考虑这样,那样的共性问题。
https://blog.csdn.net/wangyongxia921/article/details/46272813
2.5 IOC也称为DI 容器管理各层的组件 重点
https://blog.csdn.net/bookfish/article/details/79641254
Ioc就是将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制的.之前我们写的java代码,是直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建,传统应用程序是我们自己在对象中主动控制去直接获取依赖对象,ioc是由容器来帮忙创建及注入依赖对象.
2.6 Spring bean的生命周期可以说一下吗? 重点
1. 实例化Bean
2. 设置对象属性(依赖注入)
3. 注入Aware接口
4. bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现
5. InitializingBean与init-method
6. DisposableBean和destroy-method
SpringMVC
2.1 什么是SpringMVC ?
SpringMVC 是一种基于 Java 的实现 MVC 设计模式的轻量级 Web 框架,它可以通过一套注解,让一个简单的Java类成为控制器,而无须实现任何接口.
2.2 SpringMVC的执行流程是什么? 重点
https://www.jianshu.com/p/8a20c547e245
2.3 常用注解
@RequestMapping
@PathVariable
@RequestParam
@RequestBoy
@ResponseBody
SpringBoot
2.1 SpringBoot自动配置原理? 重点
一般我们的SpringBoot项目启动类都会添加@SpringBootApplication注解,而这个注解的其中一个二级注解是@EnableAutoConfiguration注解。而@EnableAutoConfiguration注解通过@Import注解,以ImportSelector接口的方法来导入classpath下的META-INF/spring.factories文件,这些文件中会指定需要加载的一些类名称。这些类一般都加了@Configuration注解,并且完成了对某框架(例如Redis、SpringMVC)的默认配置,当这些类符合条件时,就会被实例化,其中的配置生效,那么自动配置自然生效了。
2.2 SpringBoot的执行原理? 重点
SpringBoot项目启动第一步就是创建SpringApplication的实例,并且调用SpringApplication.run()这个方法。
创建SpringApplication实例主要完成三件事情:
- 记录当前启动类字节码
- 判断当前项目类型,普通Servlet、响应式WebFlux、NONE
- 加载/META-INF/spring.factories文件,初始化ApplicationContextInitializer和ApplicationListener实例
而后的run()方法则会创建spring容器,流程如下:
- 准备监听器,监听Spring启动的各个过程
- 创建并配置环境参数Environment
- 创建ApplicationContext
- prepareContext():初始化ApplicationContext,准备运行环境
- refreshContext(context):准备Bean工厂,调用一个BeanDefinition和BeanFactory的后处理器,初始化各种Bean,初始化tomcat
- afterRefresh():拓展功能,目前为空
- 发布容器初始化完毕的事件
2.3 常用注解:
@SpringBootApplication
@Repository
@Service
@RestController
@ResponseBody
@Component
@ComponentScan
@Configuration
@EnableAutoConfiguration
@AutoWired
@RequestMapping
SpringCloud
2.1 什么是SpringCloud?
Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,提供与外部系统的集成。
Spring cloud Task,一个生命周期短暂的微服务框架,用于快速构建执行有限数据处理的应用程序。
2.2 常用5大组件 重点
Ribbon/Feign 客服端负载均衡
远程调用接口: 项目中使用了Fegin
Zuul 服务网关
Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,是PRE、ROUTING、POST、ERROR。
Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。
- PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
Zuul高可用:
为了保证Zuul的高可用性,前端可以同时启动多个Zuul实例进行负载,在Zuul的前端使用Nginx或者F5进行负载转发以达到高可用性。
Spring cloud Config 分布式配置
Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。方便部署与运维。
优点:
1.集中管理配置文件
2.不同环境不同配置,动态化的配置更新
3.运行期间,不需要去服务器修改配置文件,服务会想配置中心拉取自己的信息
4.配置信息改变时,不需要重启即可更新配置信息到服务
5.配置信息以 rest 接口暴露
SpringCloud Bus :
Spring Cloud Bus提供了跨多个实例刷新配置的功能。因此,在上面的示例中,如果我们刷新Employee Producer1,则会自动刷新所有其他必需的模块。如果我们有多个微服务启动并运行,这特别有用。这是通过将所有微服务连接到单个消息代理来实现的。无论何时刷新实例,此事件都会订阅到侦听此代理的所有微服务,并且它们也会刷新。可以通过使用端点/总线/刷新来实现对任何单个实例的刷新。
避免了当修改了配置之后,必须重启服务,否则配置无法生效。
Hystix断路器:
Hystix如何解决雪崩问题?
Hystrix为每个依赖服务调用分配一个小的独立线程池,用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满调用将被立即拒绝,否则使用线程来处理请求。
可以在主线程中设置超时时间,超过这个时间如果子线程还没有执行完成任务或者子线程执行出现异常,则会进行服务降级。
用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果(例如返回友好的提示信息)。
服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。
Hystix如何进行服务熔断?如何实现容错?
Hystix的熔断状态:
- Closed:关闭状态(断路器关闭),所有请求都正常访问。
- Open:打开状态(断路器打开),所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
- Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则继续保持打开,再次进行5秒休眠计时。
Eureka 服务发现
Eureka就是客户端发现模式,客户端负责决定相应服务实例的网络位置,并且对请求实现负载均衡。客户端从一个服务注册服务中查询所有可用服务实例的库,并缓存到本地。服务调用时,客户端使用负载均衡算法从多个后端服务实例中选择出一个,然后发出请求.
3.数据库
3.MySql
SQL语句
1.排序:
select … from 表名 order by 排序列 [asc|desc],排序列 [asc|desc]
asc:升序(默认值)
desc:降序
2.分组
select 分组列 from 表名 group by 分组列 having 分组后条件过滤
where和having的区别?
where在分组前进行条件过滤,不能使用聚合函数
having在分组后进行条件过滤,可以使用聚合函数
3.分页:
语法: select … from 表名 limit 开始索引,每页显示个数
索引从0开始,也是默认值
公式: 索引 = (当前页-1) * 每页显示个数
sql注入问题 ?
#和KaTeX parse error: Expected 'EOF', got '#' at position 9: 的区别? (1)#̲将传入的数据都当成一个字符串,…将传入的数据直接显示生成在sql中。如:order by
u
s
e
r
i
d
user_id
userid,如果传入的值是id,则解析成的sql为order by id。
(3)#方式在很大程度上能够防止sql注入。
(4)
方
式
无
法
防
止
s
q
l
注
入
。
(
5
)
方式无法防止sql注入。 (5)
方式无法防止sql注入。(5)方式一般用于传入数据库对象,例如传入表名。(这里得注意SQL注入问题)
(6)一般能用#的就别用KaTeX parse error: Expected 'EOF', got '#' at position 8: 。 总结区别:#̲{} 传入值时,sql解析时,…{}穿入值,sql解析时,参数是不带引号的。
mysql优化 ? — 重点
1. 为搜索字段创建索引
https://blog.csdn.net/qq_25385555/article/details/100772764?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-2.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-2.control
前缀索引
优点:占用空间比较小
缺点:会增加额外的扫描次数
3. 避免使用 select *,列出需要查询的字段。
4. 拆分表
4.Linux
mkdir newfolder 创建目录
ls -al 查看文件,包含隐藏文件
su -username 切换用户
tar -xvzf test.tar.gz 解压文件
find / -name test.txt 根据名字查找/目录下的文件
kill -9 19979 终止线程
Vi 启动Vi编辑器
**
Mybatis
3.1 什么是MyBatis ?
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集。MyBatis 使 用 简 单 的 XML 或 注 解 来 配 置 和 映 射 基 本 体 , 将 接 口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录。
3.2 Mybatis的工作流程 :
① 创建 SqlSessionFactory
② 通过 SqlSessionFactory 创建 SqlSession
③ 通过 sqlsession 执行数据库操作
④ 调用 session.commit()提交事务
⑤ 调用 session.close()关闭会话
3.3 Mybatis的工作原理 :
Mybatis底层封装了JDBC,使用了动态代理模式。
1.SqlSessionFactoryBuilder (构造器):使用Builder模式根据mybatis-config.xml配置或者代码来生成SqISessionFactory。
2.SqlSessionFactory(工厂接口):使用工厂模式生成SqlSession。
3.SqlSession (会话): 一个既可以发送 SQL 执行返回结果,也可以获取Mapper的接口。
4.SQLMapper (映射器): 它由一个Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则,它负责发送SQL去执行,并返回结果。
5.Executor(执行器):进行对数据指令的下达
3.4 常用注解
https://blog.csdn.net/xunao1992/article/details/83342600
@Param 接收参数
@Insert
@Update
@Delete
@Select
@Result 实现结果集封装
@Results 可以与@Result 一起使用,封装多个结果集
@ResultMap 实现引用@Results 定义的封装
@One 实现一对一结果集封装
@Many 实现一对多结果集封装
Redis(非关系型数据库)
1.说说Redis的数据结构和类型?
String(字符串)
数据结构:底层是字符串数组结构
Hash(哈希)
数据结构:key value的形式映射表
List(列表)
数据结构:字符串列表,可以两头添加元素
Set(集合)
数据结构:无序的集合,通过哈希表实现的
Zset(sorted set:有序集合)
数据结构:string类型元素的集合,且不允许重复的成员
5种数据类型:
- String:等同于java中的:Map<String,String>
- list:等同于java中的:Map<String,List>
- set:等同于java中的:Map<String,Set>
- sort_set:可排序的set
- hash:等同于java中的:Map<String,Map<String,String>>
2.Redis的作用场景?
1. 存储带有失效时间的业务(鉴权)
2. 黑名单id
3. 存储搜索关键字做缓存
4. 微博热搜
5. 秒杀
6. 短信失效时间
3.存在数据库和Redis中的区别?
存储到数据库中,IO读写慢.redis直接在内存中读取数据,读取速度:8.6万次/S如果关系型不大的数据存储到内存中,效率就非常非常快.
4.AoF和RDB的持久化方案说一下?
https://www.cnblogs.com/chenliangcl/p/7240350.html
默认持久化是RDB,我们可以手动开启AOF
RDB可以在程序运行的时候开启一个快照的功能,可以把这个东西生成一个RDB的一个文件,这个文件可以存储快照这个东西. 什么时候可以进行一个快照呢,这里有一个时间的规则.比如说在15分钟之内有修改这么一个操作.就会进行一个持久化操作,生成这么一个文件.
RDB的缺点:没有说在没进行快照之前的话,这就有可能宕机了,有可能会丢失部分的数据,效率上虽然高,但是数据上可能不安全,但是做数据缓存,有可能被MySql使用.
AOF它是通过一个日志,它会监控每次set的一个操作,监控到了就会写到这上面,也就是当回去这个数据的时候就会把上面的数据执行一遍. 然后把这个文件再重新写入. 使用每秒进行写入,那他生成这个AOF呢,这里不是生成一个文件一直往里写.
写入方式: 每秒 每次 隔一段时间
6.Redis的集群搭建?
在搭建一台master的时候,就会出现单点故障. 一台master主机可以搭配多个save从机.
5.缓存击穿、缓存穿透与缓存雪崩? 重点
7.1什么是Redis缓存击穿?怎么解决?
查找数据的顺序是:先查找缓存,再查找数据库.当查找一个数据时,缓存没有都会请求数据库,当查找的数据为热点key,高并发时缓存就起不到作用,会压垮数据库,如果黑客利用这个不存在的key进行攻击可能压垮数据库.
解决方案:
1.布隆过滤器:将数据库中的数据哈希映射到bitmap(0、1表示存在、不存在),查询时先访问bitmap,查询不存在的数据就会被bitmap拦截,就不用进入数据库查询.
2.返回空值给缓存:当查询不存在数据访问数据库返回值为空,仍然将空值进行缓存(Redis中value为空值会被回收,可以设置empty字符串等),当然插入值时要替代掉空值.
7.2什么是Redis缓存穿透?怎么解决?
缓存中没有数据但数据库里有(例0如缓存过期),会进入后端访问数据库并回设到缓存,高并发的请求key,会压垮数据库
解决方案:
1.设置热点key永不过期
2.加互斥锁(mutex key)
7.3什么是Redis缓存雪崩?怎么解决?
当缓存服务器重启或者缓存短时间内大量失效,高并发时,引起数据库压力过大甚至宕机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而引起对服务器的访问压力.
解决方案:
1.尽量设置缓存失效时间均匀分布,别在短时间内大量缓存过期
2.考虑用加锁队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求数据库(在高并发下线程阻塞,用户体验差)
8.RocketMQ数据写入和读取问题
6.RocketMQ数据写入:
1.消息生产者将消息发送给Broker(消息队列服务器的实体)
2.Broker将消息写入 CommmitLog(提交日志),将CommmitLog里面的消息加载到OS线程中,然后异步刷盘到CommitLog(磁盘)
RocketMQ数据读取:
1.消息生产者将消息发送给Broker(消息队列服务器的实体)
2.将Broker的消息数据持久化到CommmitLog,然后刷到CommitLog(磁盘)
3.消息消费者组去读取ConsumeQueue里面的offset,然后根据offset去找到CommmitLog里面的消息(Message)
熟悉Dubbo分布式框架 Zookeeper注册中心
9.事务回滚(@Transactional) 重点
什么是事务ACID?
事务是所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。