Java中的八个常用数据类型
整形:byte,short,int,long
浮点型:float,double
布尔型:Boolean
字符型:char
引用数据类型:类,接口,数组
final的作用:
修饰数据:告诉编译器这个数据是恒定不变的。
修饰对象:无法修改修饰的对象。
修饰参数:在方法中也无法修改参数的值,可以当作常量引用。
修饰方法:将方法锁定,防止任何继承类修改他的内容,防止子类进行方法覆盖。
修饰类:禁止继承。
Java的异常:exception与error
error:ioerror,threaddeath。
exception:
编译时异常:文件不存在,类为找到。
运行时异常:空指针与数组越界。
处理异常的方式:
try-catch:try里面捕捉可能出现异常的代码,catch则用于捕获特定的异常。
throw:用于手动抛出异常。
@Configuration的作用
定义这个类为bean。
保证单例bean。
成为cglib的代理对象。
spring与springboot的区别:
1springboot内置tomcat
2spring要配置大量数据源与xml文件,springboot用yml或者application properties来简化集中配置
3spring主要将程序打成war包,而spring boot打成jar包。
工厂加策略模式:
1写相关支付的接口(定义两个方法一个时获取枚举对象,另一个时对应类的具体逻辑)。
2编写枚举类,每次添加新的支付方式就枚举出来即可
3写对应支付handler类实现支付接口。
4定义支付工厂,实现 Initializingbean,创建map集合,k存储枚举类,v存储handler类,将所有的支付方式存储在map中,外部想要获取对应的支付方式传入其code,找到对应k,就能找到对应的handler类来实现对应方法。
HashMap的cantainSkey的原理和识别过程:
现根据传入的key进行hash运算,计算出其在数组的那个位置,如果不存在则返回false,如果存在,则遍历该链表或红黑树比较其key值是否相等。
cookie和session的区别
1存储位置:cookie存储在客户端通常为浏览器,当浏览器向服务端发送请求时,会自动携带cookie中的数据。session的数据存储在服务端。每个服务器会给用户分配一个唯一session id,通过cookie或者url重写发送给客户端,客户端后续会携带session id,服务端根据session id来查询对应数据。
2数据容量:单个cookie的容量限制在4kb左右,session理论上无容量限制,主要取决于服务器的大小。
3安全性:cookie存储在浏览器,容易受到脚本攻击,而session存储在服务器,相对于安全些,但也要防止盗取他人session id来登录。
客户端禁用cookie,session也不能使用
客户端禁用cookie的话,服务端无法将session id发送到客户端,客户端后面也无法携带session id返回服务器,从而导致服务器无法识别。
equals与==的区别:
在比较基本数据类型时,==比较的时数据的值,equals不能比较基本类型
在比较引用数据类型时,==只能比较两个类的地址是否相同,而equals能比较俩个类的属性是否相同。
重写equals必须重写hashcode
在集合存储中,两个用equals比较相同的对象,用hashcode比较却不同,导致两个对象存储在不同的hash槽位中,导致出现这两个对象到底是否相同的问题。
两个对象的equals相等,hashcode必须相等。
两个对象不等时,hashcode可能相等。
hashcode相等时,俩个对象不一定相等。
hashcode不等时,俩对象一定不等。
@Autowired是按照类型注入,spring从容器中找到对应的类,让后注入进来。
这样会产生一个问题,当一个类有多个bean值时,无法造成选择注入那个具体的,我们需要配合着@Qualifier使用,@Qualifier告诉spring具体装配那个对象。
@Resource是根据byname注入,里面可以指定name与type,如果指定了name与type就会找到唯一匹配的进行注入,找不到则抛出异常,如果指定了name,则会以name寻找,找不到抛出异常,如果指定type,找不到或者找到多个也会抛出异常,如果没有指定,就以byname方式装配。
单例模式:
单例模式是指在内存中只会创建一次的的设计模式,在程序中多次使用同一对象且作用相同时,为了防止频繁创建对象导致内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方共享一个对象。单例模式的好处可以提升效率,又可以让类自己把控实例实现细节,对外部业务代码不产生影响。(单例模式一定要实现无参构造的私有)
char与vachar的区别:
char:是定长的字符串,不足部分用隐藏空格填充,存储固定长度,如:uuid。
vachar:是不定长字符串,节省空间,存储可变长度。如:姓名,地址等。
装箱与拆箱
基本数据类型与包装类之间的转换:
装箱将基本类型存到包装类中。
拆箱从包装类中取出基本数据。
Integer i=1;
int n =i;
基本数据类型与包装类之间的区别与联系:
基本数据类为数据,创建初始在栈内,且赋值为0。
包装类为对象,初始创建在堆内,且赋值为null。
一定要有包装类的原因,Java集合的泛型只能使用对象类型。
解决spring的循环依赖问题:
前提:spring的依赖注入方式,主要有setter注入和构造器注入,spring可以解决setter类型的依赖注入,构造器是不可以的。spring的多例模式的依赖注入也是解决不了的。
spring生命周期概括为:实例化,属性赋值,初始化,销毁。
定义两个类a与b,a中一个属性引用了b,而b中一个属性引用了a。于是实例化a的时候,去赋值属性b,于是去找b,又实例化b的时候,b属性引用a。于是产生死循环。
一级缓存:用于存放完全初始化好的bean。
二级缓存:用于存放尚未填充属性的bean。
三级缓存:存放bean工厂对象。
如果只有一级缓存的话,a去属性赋值时,去创建b,b在属性赋值时,在缓存中找不到a,又去创建a,就导致了一直创建死循环,导致栈溢出。
二级缓存用于存放半成品对象,a去属性赋值时,发现要去创建b,此时a为半成品,于是就将a放入二级缓存中,再去创建b,同样b在属性赋值时,也将自己放入二级缓存中,b开始填充,在一级缓存中没发现a,就到二级缓存中找到a,就使填充成功,就将自己放入一级缓存中,并删除二级缓存,a再去一级缓存中寻找b,就完成了属性的赋值。于是双方都完成了自己的创建,解决了循环依赖的问题。
三级缓存用于解决aop动态代理问题,spring代理对象的阶段是在属性填充前都创建完成的,于是就跳出了二级缓存,用三级缓存的beanfactory来解决。
我们要实例话对象a,就将a的factory放入三级缓存中,进行属性填充时,发现没有b,就去创建b,将b的factory放入三级缓存中,并将b放入二级缓存中,对b属性填充时,去获取a对象,发现三级缓存中没有a,于是用a的factory创建a并放入二级缓存中,同时删除三级缓存中a的factory,于是b获取不完整的a,就成了完整的b,就将b三级缓存的factory删除掉,a进行属性填充就拿到完整b对象,就删除二级缓存中的a,成为完整对象。
lock和synchronized的区别:
语法层面:1synchronizied是关键字,由jvm实现。
lock是接口。
2 使用synchronized时,退出同步代码块就会自动释放锁。
使用lock时,需要自己手动unlock来释放锁。
功能层面:
1 二者都是悲观锁,都支持互斥,同步,锁重入的功能。
2 lock额外功能:获取等待状态(可以等到等待这个锁的线程),公平锁(lock也支持非公平锁),可打断,可超时(在规定时间内未获取锁,就放弃获取)。
3 lock有许多实现,如:Reentranlock(可重入锁,根据传入参数来表示是公平锁还是非公平锁,true表示公平,false表示非公平),ReentranReadWritelock(适用于读多写少的场景)。
性能层面:
在竞争不激烈的情况下,synchronized做了很多优化,如偏向锁,轻量级锁。
在竞争激烈的情况下,lock性能更好。
lock锁底层实现:
owner[null](初始值为null,代表还没有线程获取锁)
state[0](代表锁的数量)
blocked queue(阻塞队列:当线程获取锁失败就会进入阻塞队列)
waiting queue (线程获取锁后,条件不满足,暂时存放线程的地方)
线程安全的三个方面:
1可见性:一个线程对共享变量修改,其他线程能看到。
2有序性:一个线程内代码按编写顺序进行。
3原子性:一个线程内代码以一个整体运行,期间不能有其他线程代码插队
volatile只能够保证可见性与有序性
不能够实现原子性,就会导致线程不安全,因为代码不是原子性的,导致读取的数据可能有问题。例子(设置初始值为10,加减法,加法先读取数据,让后减法读取,此时减5,然后加法会读取初始读取的值10,再进行加5操作,导致最终数据为15)。
乐观锁与悲观锁:
悲观锁代表就是synchronized和lock
1其核心思想就是(只有线程占有了锁,才能去操作共享变量,每次只有一个线程占锁成功,获取锁失败的线程,都得停下等待)。
2线程从运行到阻塞,再从阻塞到唤醒,涉及线程上下文切换,影响性能。
3线程在获取synchronized和lock锁时,如果锁被占有,会重试几次,减少阻塞机会。
乐观锁代表是Atomiclnteger,使用cas来保证原子性。(共享变量用volatile来修饰)
1其核心思想就是(无需加锁,每次只有一个线程能够修改共享变量,其他失败的线程不需要停止,不断重试直至成功)。
2由于线程一直运行,不需要阻塞,因此不涉及上下文切换
3需要多核cpu支持,且线程数不应超过cpu数。
面向对象的三大特性:
封装,继承,多态。
封装:将对象的属性和方法结合在一起,对外隐藏对象内部细节,仅通过对象提供的接口供外部调用,封装目的增加安全性,解耦,使对象更加独立。
继承:子类能够自动共享父类的属性和方法,extend继承父类。对于局部,本类,父类中的成员变量分别使用规则:局部直接使用,本类this.,父类则super.。子类调用时优先使用本类方法,如果本类中不存在就向上去找,而父类不能向下去找。重用父类方法super.方法名()。
多态:不同类的对象对同一接口实现不同相应,即一个接口,使不同实例有不同的实现,主要有重载与重写。
方法的重载:通常指同一类中,可以有多个重名方法,方法名称一样,参数列表不同,编译器根据传入的参数来确定使用什么方法。
方法的重写(覆盖):通常指子类中可以重新定义父类中的方法,但方法的名称,参数列表,返回值必须一样,只是重写里面方法的逻辑,创建的使子类对象,优先使用子类方法。
抽象: 抽象方法所在的类一定使抽象类,在class前加abstract,方法在返回类型前加abstract。不能直接创建抽象类对象,只能创建一个子类来继承抽象类,子类必须覆盖(重写)父类的抽象方法。
集合:arraylist,linkedlist,hashmap,linkedhashmap,treemap
arraylist(有序):动态数组,能够自动扩容,查询按索引查询,速度很快,但插入与删除数据要移动数组所有很慢,在内存中是连续空间存储,扩容使按1.5倍进行扩容。适合用于多查询,低增删的场景。
linkedlist(有序):双向链表集合,其插入和删除的速度很快,但查询需要一一遍历。
hashmap(去重):底层数据结构1.8之前数组加链表,1.8之后数组,链表+红黑树,解决hash冲突的方法:连地址法,再寻地址法,扩容hash。hashmap初始长度为16,当数组的长处超过此时的长度*负载因子(默认0.75)时,就会2倍扩容,且当数组长度>64且链表长度>8时,链表就会转变为红黑树。
concurrenthashmap(线程安全):jdk1.8之前加分段锁,对数组划分进行上锁,jdk1.8之后,对全部元素上锁,对于数组为null的进行 cas设置该节点,如果不为null则使用synchornized进行头节点加锁,在遍历链表或红黑树判断是否覆盖。
MySQL三大范式:
第一范式:数据列中的数据为不可再分割的原子。
第二范式:数据每一列都与主键相关。
第三范式:任何非主键属性不能依赖其他非主键。
union和union all的区别:union查出的集合为去重的数据,union all 查出的数据则是全部数据。
左外链接查询 查出左表所有数据包括含null的值,比内连接多查出null的数据。
MySQL的默认引擎为Innodb具有acid的特性(即一致性,原子性,隔离性,持久性),支持事务,索引为聚簇索引。
索引
如果查询不用到索引的话,时间复杂度为0(n),走索引的话一般为Olog(n),数据库索引数据结构一般为b+树
索引一般分为:主键索引(聚簇索引),二级索引(非聚簇索引)
聚簇索引里面一般非叶子节点只存主键值与指针,叶子节点存储主键值与其全部数据。
非聚簇索引里面一般非叶子节点存其字段,叶子节点存储主键值,要是查询的数据不全的话,会根据查出的主键值回表查询。
联合索引:将几个非主键组合的索引排序,其叶子节点仍然存储主键值,且遵循最左前缀法则。
1 联合索引最左前缀法则失效的情况:左边的索引没有使用,那其后边的索引也不能使用。
左边的索引使用了范围查询(如果是>=或者<=则不影响),其后边的索引也不能使用。
最左边的索引没有使用,其不能使用索引。
2 模糊查询时,最左边使用%进行查询。
3 查询时where后使用<和>符号会导致索引失效,最好加上=。
4查询时对索引列使用函数也会导致索引失效。
sql优化:
1.避免使用select *;不会走覆盖索引,产生回表操作,可能查询出text字段业务并不使用。
2.小表驱动大表:from小表left后边大表。
3.使用limit。
4使用union all,尽量不使用union。
${}与#{}的区别:
sql注入问题:用拼接的方式写出的sql存在注入问题,而用字符串传入的方式就可以避免。
"select * from table where id= " +id;
拼接出来的sql,在后边加入 10 or 1=1,拼接出来的sql因为有or的存在导致不管id是否正确的情况下,只会判断后边的 1=1这个条件正确,就会导致sql注入的问题。(对于mybatis就是${}的使用方式)select * from table where id =${id},直接进行字符串拼接,出现sql注入问题
"select * from table where id =?" 而这次再传入的话,会是传入的字符串与id比较作为整体比较,就不会出现上边的问题。(对于mybatis就是#{}的使用方式)。select * from table where id =#{}
就会在传入的id前后加上' ' ,就是以此为整体比较了。
相较于注入问题,${}的使用场景则是对字符串的拼接,不能用于判断条件。
原子性:即事务,操作要么全部完成,要么全部回滚,不会存在中间状态。(通过undo log 回滚日志来实现)
一致性:即事务操作前后,数据库中的数据的保持一致性。
隔离性:数据库在高并发情况下,对数据修改,能够数据隔离,一个用户修改数据,别的用户不受影响。(mvcc来实现)
持久性:事务结束的时候,对数据的修改是持久的,即使系统故障也不会丢失。(通过redo log 重做日志来实现)
冒泡排序:双层for循环,里层for循环循环数组,外层for循环,循环次数。每次比较数组中的数据,大的数据就交换位置,每次都将大的数据排在后边。
插入排序:从第一个开始,依次往后比较,保证每次前边的数据是有序的,遍历到最后一个元素则全部有序。
希尔排序:将间隔为数组数的一半间隙为初始值,分组,每次保证其组内有序,最后到间隙为1时,就和插入排序一样,但比插入排序的效率更高,能让大的数很快往后,大的数很快往前。
快速排序:寻找数组的一个基准点,每次将此基准点大的往后排,小的往前拍,当小组差为1时,就为有序。
秒杀系统设计
用户请求先打入网关层,网关进行第一波限流处理,验证其token,通过的话,可以下单,用redis的原子操作实现库存扣减,再打入消息队列中实现异步操作生成订单,再打入数据库事务处理,失败的话回滚事务。
网关层:通过token验证身份,防止未登录用户访问秒杀接口。负载均衡地发送请求至后端服务器,进行限流。
缓存层:用redis缓存秒杀商品信息和库存,抗住第一波流量。
用redis扣减库存,试用其高性能以及原子性扣减库存。
使用redis欲扣减库存,使其库存减一,并设置3分钟过期时间,如果用户在3分钟内未支付,库存自动回补。(不打如MySQL,提高性能)
消息队列:使用消息队列削峰填谷,异步生成订单,减小后端服务器压力。
数据库:主从复制,实现数据库读写分离。
使用乐观锁来保证数据库的库存一致性。
zset设置延迟队列:设置其score为当前时间➕延迟时间,让后去比较当前时间与score时间,当前时间大于score就发送消息。
延迟队列:实现消息在指定时间送达处理队列。
死信队列:通过设置ttl通过将超时订单转为死信,由监听死信的消费者处理。
spring:
ioc:即控制反转,之前我们创建对象,需要new,有了ioc框架后直接注入到容器中,通过bean工厂get bean (类名.class)即可创建对象。
di:即依赖注入,之前我们一个对象需要依赖另一个对象时,会在其内部new,而现在则只需要字段注入,setter注入,构造器注入。
aop:即面向切面编程,aop能将那些与业务无关,却被业务共同调用的逻辑封装起来,减少重复代码,降低耦合度,提高代码扩展性和维护性。(自己项目中,有个增加和修改,设置设置当前时间的逻辑,很多模块与业务都有,为了降低耦合性,自定义注解和切面类去实现)在切面类中加@Aspect注解,并在方法上写明那个方法使用,在切面类的方法@befor(@annotation说明在那个包下加了这个注解就进行拦截并实现业务重复逻辑)
springmvc的工作流程:
1用户请求会先到前端处理器中serverlet
2请求handlermapping中寻找请求路径,返回映射器执行链
3调用handler适配器调用handler处理器处理后端方法
4返回modleandview(请求域和视图)
5请求视图解析器,解析视图
6响应给用户
redis为什么那么快:
1 redis是单线程,避免多线程之间的竞争,减少了多线程切换的时间,避免死锁问题。
2 redis是基于内存操作,redis的瓶颈期是网络与内存大小。
3 redis采用io多路复用机制,即单线程的redis能够处理多个io。
redis具备高性能和高并发性:
1高性能:假如用户第一次读取MySQL中的数据,因为从磁盘中读取,所以比较慢。将用户访问的数据缓存到redis中,下一次访问直接访问缓存,redis是基于内存操作的,速度很快。
2高并发性:reids的qps为每秒10w次,是数据库的十倍,所有将热点数据缓存到redis中能够有效避免服务器宕机。
redis的持久性:
redis的读写操作都是在内存内操作,所以性能很高,但是redis重启后,数据就会丢失,为了保证内存中数据不丢失,redis实现了数据持久化的机制,这个机制会把数据存在磁盘里,redis重启就会从磁盘里读取数据。
AOF日志:每执行一次写命令,就将该命令追加到文件中。
redis在执行完一次写命令后,就会将该命令该命令写入一个文件中,redis重启的话,就会读取该文件记录的命令,然后逐一执行来恢复数据。
RDB快照:将某一时刻的内存数据,以二进制的方式写入磁盘。
因为AOF记录的时操作日志,所以当数据量比较多时,会影响性能,RDB快照就是记录下某一时刻的快照,记录实时数据,直接将RDB文件读入内存即可。
过期淘汰策略
1 定时删除:在设置key的过期时间时,同时创建一个定时事件,当时间到达时,由事件处理器自动执行删除过期key的操作。
优点:过期key会被尽早删除,内存也会尽快释放,内存友好型。
缺点:删除过期key会占用cpu时间,在内存不紧张,cpu紧张的情况下,对服务器的响应时间以及吞吐量造成影响,对cpu不友好型。
2惰性删除:不主动删除过期key,每次访问key时,看key是否过期,如果过期就删除key。
优点:每次访问时才删除key,占用很少系统资源,对cpu友好型。
缺点:如果一个过期的key,因为不被访问,而一直占用内存,造成空间的浪费,对内存不友好型。
3定期删除:每隔一段时间,抽出一批key来检测是否过期,过期就将其删除。
redis采用惰性加定期删除策略(默认每10秒抽查20个数据,看在数据库中不)
redis的内存淘汰策略:
LRU:最近最少使用,会淘汰最近最远被使用的数据,在redis的数据对象结构体后加一个额外字段,用于记录此数据最后一次的访问时间,
redis使用就是随机取出n(可自定义)个值,淘汰最久那个。
LFU:最近最不常用,redis会淘汰被访问次数少的数据
redis和数据库一致性:
1由于先更新数据库再更新redis会出现不一致性问题,请求a更新数据库还没来得即更新redis,请求b就带着最新数据来更新数据库和redis,而请求a此时才更新redis,就覆盖了最新的数据,导致数据库与缓存数据不一致的情况,也导致读到藏数据。
2先更新redis再更新数据库一样会出现类似问题,导致缓存与数据库的不一致性。
3以及先删除缓存,再更新数据库,请求打入缓存,发现没有数据,就会读到数据库旧数据,再将缓存更新为就数据,而此时数据再更新为新数据,也会导致数据库与缓存不一致。
4先更新数据库再删除缓存,请求a读取缓存未命中,就会读取数据库旧数据,此时请求b再更新数据库,请求b删除缓存,请求a再将旧数据写入缓存,还是导致数据不一致。(概率很小)
延迟双删保证最终一致性:先删除缓存,再更新数据库,延迟一段时间,再删除缓存。
如果删除失败,删除失败的消息打入消息队列,服务端监听队列,再次重新执行。
mysql的三种日志:
undo log:回滚日志,记录事务提交前的反向操作,事务要是回滚的话,直接执行日志里面的内容,回滚到事务提交前的状态。实现事务的原子性。
redo log:重做日志,每次更新内容时,innodb会先更新内存buffer pool(同时标记为脏页),让后将本次修改的内容以redolog日志的方式记录下来,以防断电断网内存内数据丢失。(实现事务的持久性)记录的是数据页和更新后的地址。
bin log :记录了所有数据表结构变更,和表修改的日志,不会记录查询操作。
三种模式:
statement:每一条修改的sql语句都会记录在日志中。
row:记录行数据最终被修改成什么。
mixed:两种结合。
sql调优:先开启慢日志查询,让后找到慢sql,进行索引分析,不走索引的话,看情况加索引。
slow_query_log=1(开启慢日志查询),slow_query_time=2(记录查询超过2秒的语句)
explain加在慢sql语句前面,细看里面的type(数据扫描类型:all全表扫描,index全索引扫描,rage范围索引扫描,ref非唯一索引扫描,eq_ref唯一索引扫描,const主键或唯一索引扫描),possiblekey(字段可能用到的索引),key(字段实际用的索引)
数据库分类:
关系性数据库:基于关系模型组织的数据库,如MySQL。
非关系性数据库:不使用传统表格形式存储的数据库,如:mongodb,redis。
关系型数据库使用结构化查询语言来管理数据,适用于保证数据一致性和完整性的场景。
非关系型数据库则更加灵活,适用于处理大量非结构化数据和高可伸缩的场景。
MySQL的引擎用的为Innodb:
支持外键,支持事务,并发控制。频繁更新和删除操作,支持事务的提交与回滚。
innodb的索引采用b+树的数据结构:
b+树相比于b树的优势:
b+树的非叶子节点不存储数据,只存索引,相比于b树,b+树的非叶子节点可以存储更多的索引,b+树也比较与b树更矮胖,查询效率更快。
b+树的叶子节点直接还有链表链接,可以进行范查询。
b+树在增加和删除时不会发生太大的树结构的变换。
索引的分类:聚簇索引与非聚簇索引(二级索引,联合索引,唯一索引)
聚簇索引的叶子节点存放的是所有数据,且一般设主键为聚簇索引。
非聚簇索引的叶子节点存放是主键值,要是查的数据不在联合索引内,则会拿着查出的主键值,返回聚簇索引内查询。
线程实现的几种方式:
1继承thread类(thread.star)
2实现runnable接口
3实现callable和future(有返回值在callable<定义返回值>)
4使用线程池
使用线程池的目的:
线程池是为了减少频繁创建和销毁线程带来的性能消耗。
线程池的7大核心参数:
核心线程数(corepoolsize):如果此时线程池的线程数量小于核心线程数,此时有任务进来了,也会创建线程来工作,且一旦确定为核心线程后就不会销毁,即使没有任务也会在阻塞队列内,不被销毁。
最大线程数(maximumpoolsize):线程池中核心线程数+非核心线程数的最大数值,创建的线程数大于核心线程,且阻塞队列任务已满,就会创建非核心线程(救急线程)。
救急线程存活时间(keepalivetime):非核心线程存活的时间(数字),没有任务时(空闲时间)大于这个时间就会被销毁。
救急线程存活时间单位(unit):时间单位。
阻塞队列(workqueue):核心线程都有任务时(没有空闲线程),就会将任务打入阻塞队列中。
线程工厂(threadfactory):线程工厂
拒绝策略(handler):四种拒绝策略:
1直接抛出异常
2不做任何处理,静默拒绝提交任务。
3抛弃最老的任务,执行当前任务
4使用线程池的调用者(提交该任务的线程)所在线程去执行被拒绝任务。
自定义拒绝策略,通过实现接口可以自定义任务拒绝策略。
ES
倒排索引:对文章进行分词,记录分词后数据与文本的关系(就是分词与文章id的关系),对分词按字典序排序,查找时用二分查找,使其时间复杂度为Olog(n)。优化倒排索引,tremindex会将分词的前缀相同部分提取出来,以树的方式存分词的偏移量存在内存中,指向磁盘中存储的关系值,这样搜索的时候就是先到内存中偏移量,再直接定位到磁盘中,大大减少磁盘io操作,提高性能。
Stored field:存放文章的完整内容的地方(行式存储结构)。
Doc values:存放文章的时间等碎片信息(多用于排序)
对外提供http接口,任何语言客户端都可以通过访问HTTP接口进行增删改查,
使用es:
1导入依赖
2初始化resthightlevelclient
信息在MySQL与es都存储一份,es主要用于搜索功能,mysql主要用于增删改,保证数据的一致性与事务,让后在从MySQL中讲数据同步到es中,创建两个类,一个存储mysql类型,另一个存储json类型
springboot中统一异常处理与信息返回:
1:创建统一信息返回类(q):包含
code服务端返回的错误码
message服务端返回的错误信息
data服务端返回的数据
创建成功static方法(传入数据),返回200状态码,"success(或者成功的信息提示)",数据, 将这三个数据封装到信息返回类(q)中,然后返回q类。
创建失败方法static方法(传入数据),传入失败的状态码,失败信息,数据可以不传。直接返回 q对象即可。
异常类调用方法getcode与getmassage。
2 创建一个枚举类qexceptioncodemsg:枚举出异常code与异常message。(枚举与业务有关的 异常)
3创建自定义异常类qexception继承runtimeexception,传入枚举的内容。
对于代码中的业务异常直接throw new qexception(异常信息)即可。
4 创建全局统一异常处理类globalexceptionhandler,并在类上加@controlleradvice
在类中创建exceptionhandler方法,传入(Exception e)信息
先判断是不是我们自定义的异常类型,是的话直接getmessage(),与getcode(),不是的话 则返回固定code500与messa"服务端异常"。
Linux常用命令:
1.cd进入主目录
2.pwd查看当前目录
3.ls查看当前文件夹下所有文件和子目录。
4.touch file1 file2 创建多个文件。
5.cat 文件名 (查看文件内容)。
6.rm 文件名(删除文件)。
7.mkdir 目录名(创建目录)。
8.将文件复制到目录里面:cp 文件名 目录名。
9.将文件移动到目录里面:mv 文件名 目录名。(在目录名后加/文件重命名)。
10.删除目录:rmdir 目录名。
11.非空目录删除:rm-r 目录名。
12.编辑文档:vim 文档名。