目录
一、数据库语句是如何优化的?
二、你使用SpringBoot的时候各种配置文件是怎么引入的
、 说说你做过的项目和你主要负责的模块。
七、 讲讲Redis,你在项目中有用过Redis吗?
九. 数据库建表的时候int(1)和int(2)的区别
二、.1. #和$的区别
2 Springmvc的执行流程
3. 讲讲ioc
4. Jvm参数
反射的三种创建方式
6. Arraylist和linklist的区别
7.Arraylist一次扩容多少
8. Vector是如何实现的安全的
9. 讲讲你知道哪些排序方法,并说下他们的时间复杂度
三、
1.mysql优化
2. stringbuild跟stringbuffer的区别
3.hashmap跟hashtable区别
常见集合的区别
vue子父项目怎么实现请求同步
es的使用,为什么要用
redis的几种问题跟解决方案
面向对象的六大原则
RabbitMQ的用途
创建线程的三种方式
Jdk8比以前有什么新特性
elasticsearch用的什么查询
Hashmap+list什么时候触发红黑树
面向对象的理解
Linux常用命令
css有哪些选择器
Radis怎么实现数据同步
4 wildcard(通配符查询)
5 bool查询(布尔查询)
Spring boot有什么注解
Vue怎么实现中英文切换,用什么实现
mysql跟oracle的区别
在jdbc中是使用什么实现占位符
mybaits常用注解
Redis的执行原理
spring的事务
索引的作用
控制反转和注入方式
什么是线程
的资源。sleep和wait的区别
深拷贝和浅拷贝的区别
1.建立索引 (一个表的索引不是越多越好,也没有一个具体的数字,根据以往的经验,一个表的索引最多不能超过6个,因为索引越多,对update和insert操作也会有性能的影响,涉及到索引的新建和重建操作。)
2.like语句优化
3.增加查询范围的限制
4.复合索引(形如(x,y,uid)索引的索引)
5.where子句使用 != 或 <> 操作符优化where子句使用IN 或 NOT IN的优化
6.limit分页优化
自动配置类是什么时候导入内存的 启动类上的注解:@SpringBootApplication
包含三个注解:
1.@ComponentScan 包的扫描
2.@SpringBootConfiguration 定义配置类
3.@EnableAutoConfiguration 启动自动配置(将自动配置类加载到内存)
怎么加载类到内存中? Class.forName("完整类名")
@EnableAutoConfiguration --> AutoConfigurationImportSelector --> loadFactoryNames --->
loadSpringFactories --> classLoader.getResources("META-INF/spring.factories")
在spring-boot-autoconfigure包下保存大量的自动配置类
类名都保存 META-INFO/spring.factotiries文件下
自动配置类生效需要一定条件,如@ConditionalOnClass,引入某些类时(导入了对应的框架依赖)
聪优课堂是迎合当今互联网教育市场,让相关专业学生系统的学习知识体系,系统采用分布式架构
设计,主要模块有搜索,广告、登录、课程、订单、支付、评论等模块。
项目职责:
1.搜索功能:调用课程服务查询到数据库的信息导入到Elasticsearch中,通过用户选择的过滤条件
和当前参数,通过布尔查询对多个条件进行过滤,处理结果查询。
2.解决数据同步问题:当对数据库进行增删改操作,使用RabbitMQ消息队列同步到Elasticsearch
3.登录模块:用户认证通过后,采用JWT和RSA加密算法,生成token,做到每次请求都携带JWT token,实现单点登录。
用过。Redis是一个高性能的内存数据库,以key-value方式存储数据,可以作为缓存使用。
MySQL的连接数存在瓶颈,连接过大可能导致MySQL宕机、所以使用Redis -性能高(读的速度是110000次/s,写的速度是81000次/s,单机redis支撑万级并发)
支持多种存储类型 丰富的特性(发布订阅、事务、过期策略等) 支持持久化 单线程 (避免上下文切换,线程同步问题)
常见问题有、缓存击穿(短时间内缓存会被穿过)、缓存穿透(查找不存在的数据)、缓存雪崩(缓存服务器重启或热点数据同时过期)
号中的字符表示显示宽度,整数列的显示宽度与MySQL需要用多少个字符来显示该列数值,
与该整数需要的存储空间的大小都没有关系,INT类型的字段能存储的数据上限还是2147483647(有符号型)和4294967295(无符号型)。
#{}对传入的参数视为字符串,也就是它会预编译防止sql注入
${}字符串拼接有sql注入风险
用户发送请求
前端控制器获得用户请求的URL,发送URL给处理器映射
处理器映射将Handler(包装方法信息)返回给前端控制器
前端控制器发送Handler给处理器适配器,适配器执行Handler方法
执行Handler方法后,返回ModelAndView(逻辑视图)给前端控制器
前端控制器将ModelAndView发送给视图解析器,解析出物理视图返回给前端控制器
前端控制器渲染视图,发送视图给用户
控制反转是一种程序设计思想。般情况下对象的创建和管理由开发者控制,反转是把对象的创建和管理交给容器完成,然后再交给开发者
IOC的主要作用是:解耦:解耦,是降低程序耦合度改一处代码不会影响很多其他的代码
标准参数:不会随着jdk版本的变化而变化。比如:java -version、java -help
非标准参数:随着JDK版本的变化而变化。
1. 类名.class
2. 对象.getClass()
3. Class.forName("包名+类名")
1. 数据结构:ArrayList是数组,LinkedList是双向链表
2. ArrayList查找性能高(因为通过下标快速定位),插入和删除性能低(移动大量数据)
3. LinkedList查找性能低(因为要向前或向后依次查找),插入和删除姓高(只需要修改前后指针,不用移动)
ArrayList扩容1.5倍
Vector的get() 、remove()、size()方法都是同步的
Vector 的所有方法加上了 synchronized 关键字
归并排序 归并排序的时间复杂读为nlogn,每一行时间复杂度O(n) 然后二叉树高度log(n)
重复
stringbuffer是线程安全的效率低于stringbuild
stringbuild是非线程安全的效率更高
Hashtable是线程安全的,HashMap是非线程安全的
HashMap的性能高于Hashtable
Hashtable不能接收null作为键和值,HashMap可以
1、list和set是实现了collection接口的。
2、list可以允许重复的对象。可以插入多个null元素。是一个有序容器,保持了每个元素的插入顺
序,输出的顺序就是插入的顺序。Set不允许重复对象,无序容器,你无法保证每个元素的存储顺
序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。只允许一个 null 元素。
3、Map不是collection的子接口或者实现类。Map是一个接口。Map 的 每个 Entry 都持有两个对
象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。TreeMap 也通
过 Comparator 或者 Comparable 维护了一个排序顺序。Map 里你可以拥有随意个 null 值但最多
只能有一个 null 键。
父组件通过 props 传入状态给子组件,子组件通过 props 来初始化另外一个内部的状态,子组件每
次更改状态之后都通知父组件,然后由
Elasticsearch具备以下特点:
分布式,无需人工搭建集群
Restful风格,一切API都遵循Rest原则,容易上手
近实时搜索,数据更新在Elasticsearch中几乎是完全同步的。
正排索引
通过key找到value,如通过id找到文章
查询内容时,需要逐条遍历,速度比较慢
倒排索引
通过value找到key
对内容进行分词,生成倒排索引
父组件来更改自己的状态,就是 props on emit 的应
1)缓存击穿
高并发的情况下,短时间内缓存会被穿过,请求直接打到数据库上,可能导致数据库压力过大。
解决方案:对代码上锁(双重检查锁)
2)缓存穿透
高并发的情况下,如果查询不存在的数据,因为缓存和数据库都不存在,请求都会打到数据库上,可能导致系统崩溃。
解决方案:
1) 保存不存在的数据到缓存中,设置一定过期时间
2) 布隆过滤器(直接过滤掉不存在数据的请求) 不能准确判断是否存在数据,能准确判断数据不存在
3)缓存雪崩
高并发的情况下,缓存服务器重启或热点数据同时过期,全部访问数据库,导致数据库宕机
解决方案:
1)配置缓存集群
2)尽量给热点数据设置不一样的过期时间,相对均匀
消息队列的用法
最基本的队列模型: 一个生产者发送消息到一个队列,一个消费者从队列中取消息。
工作队列,生产者将消息分发给多个消费者,如果生产者生产了100条消息,消费者1消费50条,
消费者2消费50条。
实现能者多劳:
channel.basicQos(1);限制队列一次发一个消息给消费者,等消费者有了反馈,再发下一条
channel.basicAck 消费完消息后手动反馈,处理快的消费者就能处理更多消息
basicConsume 中的参数改为false
发布/订阅模式和Work模式的区别是:Work模式只存在一个队列,多个消费者共同消费一个队列中
的消息;而发布订阅模式存在多个队列,不同的消费者可以从各自的队列中处理完全相同的消息。
1) 创建交换机(Exchange)类型是fanout(扇出)
2) 交换机需要绑定不同的队列
3) 不同的消费者从不同的队列中获得消息
4) 生产者发送消息到交换机
5) 再由交换机将消息分发到多个队列
路由模式的消息队列可以给队列绑定不同的key,生产者发送消息时,给消息设置不同的key,这样
交换机在分发消息时,可以让消息路由到key匹配的队列中。
主题模式和路由模式差不多,在key中可以加入通配符:
* 匹配任意一个单词 com.* ----> com.hopu com.blb com.baidu
# 匹配.号隔开的多个单词 com.* ---> com.hopu.net com.hopu com.163.xxx.xxx.xxx
用
单一职责原则SRP(Single Responsibility Principle)
是指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,否则一天到晚虽然忙忙碌碌的,但效率却高不起来。
开放封闭原则OCP(Open-Close Principle)
一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。
里式替换原则LSP(the Liskov Substitution Principle LSP)
子类应当可以替换父类并出现在父类能够出现的任何地方。(比如父类public,子类一定是public)比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。
依赖倒置原则DIP(the Dependency Inversion Principle DIP)
A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
B.抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
具体依赖抽象,上层依赖下层。高层模块就是调用端,底层模块就是具体实现类。(应该让底层模块定义抽象接口并且实现,让高层模块调用抽象接口,而不是直接调用实现类。)
通俗来讲:依赖倒置原则的本质就是通过抽象(接口或抽象类)使个各类或模块的实现彼此独立,互不影响,实现模块间的松耦合。
问题描述:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
解决方案:将类A修改为依赖接口interface,类B和类C各自实现接口interface,类A通过接口interface间接与类B或者类C发生联系,则会大大降低修改类A的几率。(比如A依赖于车的轮胎,速度,牌子等接口,然后让B,C直接实现这些接口的方法,A间接通过接口与BC发生联系。)
好处:依赖倒置的好处在小型项目中很难体现出来。但在大中型项目中可以减少需求变化引起的工作量。使并行开发更友好。
接口分离原则ISP(the Interface Segregation Principle ISP)
模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来,即面向接口编程。(提供接口,给其他模块调用)
核心思想:类间的依赖关系应该建立在最小的接口上通俗来讲:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。
也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
问题描述:类A通过接口interface依赖类B,类C通过接口interface依赖类D,如果接口interface对于类A和类C来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
需注意:接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情为依赖接口的类定制服务。只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
迪米特法则(Law of Demeter,简称LoD)
核心思想:类间解耦。
通俗来讲:一个类对自己依赖的类知道的越少越好。自从我们接触编程开始,就知道了软件编程的总的原则:低耦合,高内聚。无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。
耦合是:
简单地说,软件工程中对象之间的耦合度就是对象之间的依赖性。指导使用和维护对象的主要问题是对象之间的多重依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。
有软硬件之间的耦合,还有软件各模块之间的耦合。
耦合性是程序结构中各个模块之间相互关联的度量。它取决于各个模块之间的接口的复杂程度、调用模块的方式以及哪些信息通过接口。
耦合可以分为以下几种,它们之间的耦合度由高到低排列如下:
· 内容耦合。当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过正常入口而转入另一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用之。
· 公共耦合。两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。在具有大量公共耦合的结构中,确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。
· 外部耦合。一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
· 控制耦合。一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进行适当的动作,这种耦合被称为控制耦合。
· 标记耦合。若一个模块A通过接口向两个模块B和C传递一个公共参数,那么称模块B和C之间存在一个标记耦合。
· 数据耦合。模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另一些模块的输入数据。
· 非直接耦合。两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。
1)解耦
服务之间进行解耦,A服务调用B服务时,需要编写相关的代码,调用情况发生改变时,需要修改
调用的代码
2)异步
传统的同步调用方式,需要等待调用完成,才能进行其它业务
异步调用方法,将消息发送到队列中,就可以返回,执行其它业务,速度大大提升
3)削峰
出现流量激增的情况时,消息队列可以设置消息的最大数量,处理一部分消息,其它消息交给队列
排队处理
继承Thread类
1.继承Thread类 2.重写run方法 3.调用start启动线程
实现Runnable接口
1.实现Runnable接口 2.实现run方法
3.创建实现Runnable接口的对象,传入Thread对象中 4.启动线程
实现Callable接口
java8的新特性还是比较多的如:函数式接口,Lambda表达式,方法引用,Stream接口, Optional类等。
ElasticSearch常用的几种查询方式,terms 查询是term的扩展,可以支持多个vlaue匹配,只需要一个匹配就可以了。
1 term查询(精准查询)
term是ES中的精准查询,不会参与ES分词查询。
2 math查询(分词匹配查询)
match查询是按ES分词的倒排表进行查询,而keyword不会被分词,match的需要跟keyword的完全匹配可以。可以用于一般性的匹配查询。
3 fuzzy查询(模糊查询)
fuzzy查询可以用于纠正去拼写的问题,fuzziness是可以允许纠正错误拼写的个数
情况一:链表长度到满足8,先尝试转红黑树
情况二:校验数组长度满足64
MIN_TREEIFY_CAPACITY:64
调用treeifyBin()的方法,先判断数组长度是否小于64,小于则进行扩容;否则,转红黑树。
装(把代码装起来,把一个类相关的属性和方法装起来,将一些代码装到方法中,方便调用)
封(信息的隐藏,将某些属性和方法隐藏起来,提供公开的属性和方法供调用者使用)
封装性:封装是一种信息隐蔽技术,它体现于类的说明,是对象的重要特性。封装使数据和加工该
数据的方法(函数)封装为一个整体,以实现独立性很强的模块,使得用户只能见到对象的外特性
(对象能接受哪些消息,具有那些处理能力),而对象的内特性(保存内部状态的私有数据和实现
加工能力的算法)对用户是隐蔽的。封装的目的在于把对象的设计者和对象者的使用分开,使用者
不必知晓行为实现的细节,只须用设计者提供的消息来访问该对象。
子类能够继承父类的属性和方法,实现了代码的重用
多个类具有相同的属性和方法,提取出来放到共同的父类
提升了代码重用性、可维护性和可扩展性
继承性:继承性是子类自动共享父类之间数据和方法的机制。它由类的派生功能体现。一个类直接
继承其它类的全部描述,同时可修改和扩充。继承具有传递性。继承分为单继承(一个子类只有一
父类)和多重继承(一个类有多个父类)。类的对象是各自封闭的,如果没继承性机制,则类对象
中数据、方法就会出现大量重复。继承不仅支持系统的可重用性,而且还促进系统的可扩充性。
可以将子类的对象赋值给父类的引用,可以将子类对象当做父类来使用,从而屏蔽不同对象之间的
差异,可以写出更加通用和灵活的代码,以适应不同的业务需求。
多态性:对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行
动,这种现象称为多态性。利用多态性用户可发送一个通用的信息,而将所有的实现细节都留给接
受消息的对象自行决定,如是,同一消息即可调用不同的方法。例如:Print消息被发送给一图或表
时调用的打印方法与将同样的Print消息发送给一正文文件而调用的打印方法会完全不同。多态性的
实现受到继承性的支持,利用类继承的层次关系,把具有通用功能的协议存放在类层次中尽可能高
的地方,而将实现这一功能的不同方法置于较低层次,这样,在这些低层次上生成的对象就能给通
用消息以不同的响应。在OOPL中可通过在派生类中重定义基类函数(定义为重载函数或虚函数)
来实现多态性。
切换目录
cd 目录名
查看目录
ls 目录名(不写就是查看当前目录)
-l 详细列表
-a 所有文件
查看目录详情
ll 目录名
创建目录
mkdir 目录名
删除目录
rm 目录名
-r 遍历所有子目录
-f 强制删除
创建\打开文件
vi 文件名
三种模式:
命令模式 能删除、复制、粘贴,无法编辑
输入模式 编辑内容
命令行模式 退出、保存文件
操作方式:默认进入命令模式,按i进入输入模式,按esc回到命令模式,按:进入命令行模式
命令模式
x 删除一个字符
dd 删除一行
yy 复制一行
p 粘贴
u 撤销Vue怎么实现中英文切换,用什么实现
命令行模式
wq 保存退出
q 退出 (如果有修改,此方式退出会出错)
q! 强制退出
cat 显示整个文件内容(不支持分页)
more 分页显示(只能向前分页查询)
less 分页显示,功能比more强大。(支持前后分页查询)
支持文本查找,/查找内容 向下查询 ; ?查找内容 向上查找内容
退出less模式,点击q
对比vi命令:cat、more、less仅仅是用来进行文本阅读命令,vi用来进行文本编辑的命令。
查询当前文件中是否包含有java单词,如果包含有Java单词的所有行全部显示出来。
cat 文件名 | grep 查询文字
find 查找目录 -name 文件名称
find 查找目录 | grep 名称
which 命令名称
移动文件
mv 原文件 目标文件
复制文件
cp 原文件 目标文件
解压指令:tar -zxvf
压缩指令:tar -zcvf
-z:表示压缩和解压缩的格式为gz压缩文件(gzip)
-c::表示压缩
-x:表示解压缩
-v:表示显示压缩或者解压缩的详细过程。
-f:表示指定压缩或者解压缩的文件,只能放在命令的最后
tar -zcvf demo.tar.gz demo2.txt
tar -cvf 压缩后的文件名称 待压缩的文件
tar -xvf 待解压的解压包名
通过端口查看进程:netstat –apn | grep 8080
通过端口查看进程:lsof -i:3306
通过进程名称查询进程:ps -ef | grep redis
杀死进程:kill -9 PID(进程ID,-9表示强制杀死)
1、标签选择器 以标签名开头,选择所有div元素
2、类选择器 给标签取class名,以点(.)加class名开头,选择所有该class名的元素
3、id选择器 给标签取id名,以#加id名开头,具有唯一性,选择”id = ‘wrap’”的元素
4、子选择器 以>隔开父子级元素,(模块名>模块名,修饰>前模块内的子模块)
5、包含选择器 以空格隔开包含关系的元素,(模块名模块名,修饰空格前模块内所有该模块)
6、兄弟选择器 以~隔开兄弟关系的元素(模块名~模块名 修饰~前模块往下的所有兄弟模块)
7、相邻选择器 以+隔开相邻关系的元素(模块名+模块名 修饰加号前模块往下的相邻的模块 只一个)
8、全局选择器 以*开头(星号标在大括号前,修饰了包含body所有的标签)
9、群选择器 以,分隔(逗号分隔开需要修饰的模块名)
10、属性选择器 [] ([type=text]修饰属性为type=text的模块)
11、伪类选择器
(1) li:first-child{} (修饰第一个li) 修饰第一个li元素
(2) li:last-child{} (修饰最后一个li) 修饰最后一个li元素
(3) li:nth-child{} (修饰第()个li) 修饰第二个li元素
(4) li:not(){} (不修饰第()个li,括号里面可以填以上的选择器)
Redis的主从同步机制可以确保redis的master和slave之间的数据同步。按照同步内容的多少可以分
为全同步和部分同步;按照同步的时机可以分为slave刚启动时的初始化同步和正常运行过程中的
数据修改同步;本文将对这两种机制的流程进行分析。
全备份过程中,在slave启动时,会向其master发送一条SYNC消息,master收到slave的这条消息
之后,将可能启动后台进程进行备份,备份完成之后就将备份的数据发送给slave,初始时的全同
步机制是这样的:
(1)slave启动后向master发送同步指令SYNC,master接收到SYNC指令之后将调用该命令的处
理函数syncCommand()进行同步处理;
(2)在函数syncCommand中,将调用函数rdbSaveBackground启动一个备份进程用于数据同
步,如果已经有一个备份进程在运行了,就不会再重新启动了。
(3)备份进程将执行函数rdbSave() 完成将redis的全部数据保存为rdb文件。
(4)在redis的时间事件函数serverCron(redis的时间处理函数是指它会定时被redis进行操作的函
数)中,将对备份后的数据进行处理,在serverCron函数中将会检查备份进程是否已经执行完毕,
如果备份进程已经完成备份,则调用函数backgroundSaveDoneHandler完成后续处理。
(5)在函数backgroundSaveDoneHandler中,首先更新master的各种状态,例如,备份成功还是
失败,备份的时间等等。然后调用函数updateSlavesWaitingBgsave,将备份的rdb数据发送给等
待的slave。
(6)在函数updateSlavesWaitingBgsave中,将遍历所有的等待此次备份的slave,将备份的rdb文
件发送给每一个slave。另外,这里并不是立即就把数据发送过去,而是将为每个等待的slave注册
写事件,并注册写事件的响应函数sendBulkToSlave,即当slave对应的socket能够发送数据时就调
用函数sendBulkToSlave(),实际发送rdb文件的操作都在函数sendBulkToSlave中完成。
(7)sendBulkToSlave函数将把备份的rdb文件发送给slave。
通配符查询允许我们指定一个模式来匹配,而不需要指定完整的trem,匹配的方式类似于match的
分词匹配查询。
?将会匹配如何字符;*将会匹配零个或者多个字符。
bool查询本身没有查询功能,而是基于逻辑值使用前面几种查询方式进行组合查询。
1、@SpringBootApplication
替代 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
2、@ImportAutoConfiguration
导入配置类,一般做测试的时候使用,正常优先使用@EnableAutoConfiguration
3、@SpringBootConfiguration
替代@Configuration
4、@ImportResource
将资源导入容器
5、@PropertySource
导入properties文件
6、PropertySources
@PropertySource 的集合
7、@Role
bean角色定义为ROLE_APPLICATION(默认值)、ROLE_SUPPORT(辅助角色)、ROLE_INFRASTRUCTURE(后台角色,用户无感)
8、@Scope
指定bean的作用域,默认singleton,其它包括prototype、request、session、globalSession
9、@Lazy
使bean懒加载,取消bean预初始化。
10、@Primary
自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否者将抛出异常。
11、@Profile
指定Bean在哪个环境下被激活
12、@DependsOn
依赖的bean注册完成,才注册当前类,依赖bean不存在会报错。用于控制bean加载顺序
13、@PostConstruct
bean的属性都注入完毕后,执行注解标注的方式进行初始化工作
14、@Autowired
默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。
15、@Lookup
1.实现Callable接口,实现call方法 2.创建Callable对象,传入FutureTask对象
3.创建FutureTask对象,传入Thread对象 4.启动线程
5.调用get方法得到返回结果
安装 vue-i18n依赖
在src/components下新建文件夹language,并在文件夹language下新建zh.js及en.js
在main.js下引入及注册vue-i18n
在dom里使用 $t(' '),若在js里使用则 this.$t('
一、宏观上:
1、Oracle是大型的数据库而Mysql是中小型数据库;Mysql是开源的,Oracle是收费的,且价格昂贵。
2、Oracle支持大并发,大访问量,是OLTP的最好的工具。
3、安装占用的内存也是有差别,Mysql安装完成之后占用的内存远远小于Oracle所占用的内存,并且Oracle越用所占内存也会变多。
二、微观上:
1、对于事务的支持
Mysql对于事务默认是不支持的,只是有某些存储引擎中如:innodb可以支持;而Oracle对于事物
是完全支持的。
2、并发性
什么是并发性?并发性是OLTP(On-Line Transaction Processing联机事务处理过程)数据库最重要
的特性,并发性涉及到资源的获取、共享与锁定。
Mysql,既支持表锁,也支持行级锁。表锁,对资源锁定的力度很大,如果一个session对一个表加
锁时间过长,会让其他session无法更新此表的数据。
Oracle使用行级锁,对资源锁定的力度要小很多,只是锁定sql需要的资源,并且加锁是在数据库
中的数据行上,不依赖于索引。所以oracle对并发性的支持要好很多。
3、数据的持久性
Oracle保证提交的事务均可以恢复,因为Oracle把提交的sql操作线写入了在线联机日志文件中,
保存到磁盘上,如果出现数据库或者主机异常重启,重启Oracle可以靠联机在线日志恢复客户提交
的数据。
Mysql默认提交sql语句,但是如果更新过程中出现db或者主机重启的问题,也可能会丢失数据。
4、事务隔离级别
MySQL是repeatable read的隔离级别,而Oracle是read commited的隔离级别,同时二者都支持
serializable串行化事务隔离级别,可以实现最高级别的。
读一致性。每个session提交后其他session才能看到提交的更改。Oracle通过在undo表空间中构造
多版本数据块来实现读一致性,每个session 查询时,如果对应的数据块发生变化,Oracle会在
undo表空间中为这个session构造它查询时的旧的数据块。
MySQL没有类似Oracle的构造多版本数据块的机制,只支持read commited的隔离级别。一个
session读取数据时,其他session不能更改数据,但可以在表最后插入数据。session更新数据
时,要加上排它锁,其他session无法访问数据
5、提交方式
Oracle默认不自动提交,需要手动提交。Mysql默认自动提交。
6、逻辑备份
Mysql逻辑备份是要锁定数据,才能保证备份的数据是一致的,影响业务正常的DML(数据操纵语言
Data Manipulation Language)使用;Oracle逻辑备份时不锁定数据,且备份的数据是一致的。
7、sql语句的灵活性
mysql对sql语句有很多非常实用而方便的扩展,比如limit功能(分页),insert可以一次插入多行数
据;Oracle在这方面感觉更加稳重传统一些,Oracle的分页是通过伪列和子查询完成的,插入数据
只能一行行的插入数据。
8、数据复制
MySQL:复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换
丛库到主库。
Oracle:既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题
是,可以自动切换备库到主库,但配置管理较复杂。
9、分区表和分区索引
MySQL的分区表还不太成熟稳定;Oracle的分区表和分区索引功能很成熟,可以提高用户访问db
的体验。
10、售后与费用
Oracle是收费的,出问题找客服;Mysql是免费的的,开源的,出问题自己解决。
11、权限与安全
Oracle的权限与安全概念比较传统,中规中矩;MySQL的用户与主机有关,感觉没有什么意义,
另外更容易被仿冒主机及ip有可乘之机。
12、性能诊断方面
Oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、
sqltrace、tkproof等 ;MySQL的诊断调优方法较少,主要有慢查询日志。
Statement 接口的两个问题:
第一个问题: 使用 Statement 接口 对象发送的 sql 语句需要再数据库进行一次编译之后成为指令才能执行,
每条 sql 语句都需要编译一次, 这样是很慢的.
第二个问题: 使用 Statement 接口 操作的 sql 语句需要使用字符串的拼接方式实现,
这样的方式可能存在 sql 注入的安全风险并且拼接字符串比较麻烦.
对比 Statement 接口, PreparedStatement 接口的优点:
1.使用该接口操作的 sql 语句会先预先编译成指令在发送给数据库, 数据库就执行指令即可, 这样就提高了一定速度,
2.该接口可以避开 sql 需要使用字符串拼接的方式, 从而解决 sql 注入的安全风险,
而是使用占位符 (?) 来代替原来的字符串拼接.
@Insert : 实现新增
@Update: 实现更新
@Delete:实现删除
@Select:实现查询
@Result:
实现结果集封装
@Results:
可以与@Result 一起使用,封装多个结果集
@ResultMap:
实现引用@Results 定义的封装
@One:
实现一对一结果集封装
@Many:
实现一对多结果集封装
@CacheNamespace:
实现注解二级缓存的使用
复杂关系映射的注解说明
@Results 注解
代替的是标签<resultMap>
@Resutl 注解
代替了 <id> 标签和<result> 标签
@One 注解(一对一)
代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
@Many 注解(多对一)
代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
redis服务器对命令的处理都是单线程的,但是I/O层面却面向多个客户端并发地提供服务,并发到
内部单线程的转化通过多路复用框架来实现
首先从多路服用框架(epoll、evport、kqueue)中select出已经ready的文件描述符
(fileDescriptor)
ready的标准是已有数据到达内核(kernel)、已准备好写入数据
对于上一步已经ready的fd,redis会分别对每个fd上已ready的事件进行处理,处理完相同fd上的所
有事件后,再处理下一个ready的fd。有3中事件类型
acceptTcpHandler:连接请求事件
readQueryFromClient:客户端的请求命令事件
sendReplyToClient:将暂存的执行结果写回客户端
对来自客户端的命令执行结束后,接下来处理定时任务(TimeEvent)
aeApiPoll的等待时间取决于定时任务处理(TimeEvent)逻辑
本次主循环完毕,进入下一次主循环的beforeSleep逻辑,后者负责处理数据过期、增量持久化的文件写入等任务
')
加快查询速度,用户查询时,先找索引,通过索引找到实际数据的位置,再直接定位到实际数据上,极大提高查询速度
缺点: 1. 也是数据,需要占存储空间
2. 降低增删改的速度
3. 创建索引也需要一定的时间
控制反转(IOC)和依赖注入(DI),其实是同一个概念的不同角度描述,调用者不负责被调用者的实例创建工作,该工作由Spring框架中的容器来负责,它通过开发者的配置来判断实例类型,创建后再注入调用者。由于Spring容器负责被调用者实例,实例创建后又负责将该实例注入调用者,因此称为依赖注入。而被调用者的实例创建工作不再由调用者来创建而是由Spring来创建,控制权由应用代码转移到了外部容器,控制权发生了反转,因此称为控制反转。
IoC-控制反转:
IoC是 Inverse of Control 的简写,意思是控制反转。是降低对象之间的耦合关系的设计思想。
通过IoC,开发人员不需要关心对象的创建过程,交给Spring容器完成。具体的过程是,程序读取Spring 配置文件,获取需要创建的 bean 对象,通过反射机制创建对象的实例。
缺点:对象是通过反射机制实例化出来的,因此对系统的性能有一定的影响。
控制反转了什么? 获得依赖对象的方式反转了
DI-依赖注入:
Dependency Injection,说的是创建对象实例时,同时为这个对象注入它所依赖的属性或IoC容器注入应用程序所依赖的对象;相当于把每个bean与bean之间的关系交给容器管理。而这个容器就是spring。
例如我们通常在 Service 层注入它所依赖的 Dao 层的实例;在 Controller层注入 Service层的实例。
所以,依赖注入(DI)和控制反转(IoC)是从不同的角度描述的同一件事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦.
Spring 工厂的搭建
Schema:配置文件的schema(规范)。
作用:统一配置方式,开发者和框架采用同一套配置语法。向框架传达开发意图。
格式:xsd文件 (spring-beans-4.1.xsd,spring-context-4.1.xsd,...)
导入方式:spring的每种schema都有namespace作为标识;
进程概念:进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。
线程概念:线程是进程的一个执行路径,一个进程中至少有一个线程,进程中的多个线程共享进程
调用对象不同
wait() 由锁对象调用
sleep() 由线程调用
锁使用不同
执行wait后,自动释放锁
执行sleep后,不会释放锁
唤醒机制不同
执行wait后,可以被通知唤醒
执行sleep后,只能等待时间结束后,自动唤醒
1、浅拷贝:将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用。
2、深拷贝:创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”。