数据库语句是如何优化的?
1.减少数据访问: 设置合理的字段类型,启用压缩,通过索引访问等减少磁盘IO
2.返回更少的数据: 只返回需要的字段和数据分页处理 减少磁盘io及网络io
3.减少交互次数: 批量DML操作,函数存储等减少数据连接次数
4.减少服务器CPU开销: 尽量减少数据库排序操作以及全表查询,减少cpu 内存占用
5.利用更多资源: 使用表分区,可以增加并行操作,更大限度利用cpu资源
使用SpringBoot的时候各种配置文件是怎么引入的
自动配置类是什么时候导入内存的 启动类上的注解:@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,引入某些类时(导入了对应的框架依赖)
说说你做过的项目和你主要负责的模块
伊顿在线教育平台为学习者提供便捷、实用性强的 IT 技能学习课程,同时支持学习者互动分享、采用分 布式的架构设计,包括后台管理、前台系统。前台主要包括:网关服务、授权服务、课程服务、用户服 务、广告服务、支付服务、订单服务、ES 服务、购物车服务、评论服务等。后台主要包括:用户管理、 角色管理、权限管理、课程管理、订单管理等模块。
项目职责:
1. 课程搜索功能:将 ES 中查询到的数据分页显示到页面,包含基本信息、课程老师,课程方向,课程视频,课程 优惠等,也可以对数据进行一个多条件的分页查询,以及搜索关键字的高亮显示。添加课程信息或修改时,用 RabbitMQ 消息队列通知 ES 服务,实现 MySQL 和 ES 的数据同步。
2. 单点登录:采用了 JWT 和 RSA 加密算法,用户登录成功后鉴权服务生成 token,用户每次访问携带 token, 网关服务解密 token。
3. 微信扫码支付:用户点击课程详情购买课程后生成微信支付二维码,用户可以通过二维码进行课程的扫码支付。
讲讲Redis,项目中有用过Redis吗?
Redis是一个高性能的内存数据库,以key-value方式存储数据,可以作为缓存使用。
Redis的优点
性能高(读的速度是110000次/s,写的速度是81000次/s,单机redis支撑万级并发)
支持多种存储类型
丰富的特性(发布订阅、事务、过期策略等)
支持持久化
单线程 (避免上下文切换,线程同步问题)
数据库建表的时候int(1)和int(2)的区别
在 integer 数据类型中,M 表示最大显示宽度。
在 int(M) 中,M 的值跟 int(M) 所占多少存储空间并无任何关系。 int(3)、int(4)、int(8) 在磁盘上都是占用 4 btyes 的存储空间。说白了,除了显示给用户的方式有点不同外,int(M) 跟 int 数据类型是相同的。
#{}和${}的区别
#{xx}应用PreparedStatement的占位符插入,能防止SQL注入
${xx}应用字符串的拼接,不能防止SQL注入
Springmvc的执行流程
1)用户发送请求
2)前端控制器获得用户请求的URL,发送URL给处理器映射
3)处理器映射将Handler(包装方法信息)返回给前端控制器
4)前端控制器发送Handler给处理器适配器,适配器执行Handler方法
5)执行Handler方法后,返回ModelAndView(逻辑视图)给前端控制器
6)前端控制器将ModelAndView发送给视图解析器,解析出物理视图返回给前端控制器
7)前端控制器渲染视图,发送视图给用户
讲讲ioc
控制反转:一种理论思想,原来的对象由使用者来进行控制,有了spring之后,可以吧对象交给容器进行管理。
DI:依赖注入,把对应的值注入到具体对象中,@Autowired,populateBean完成属性值的注入。
Jvm参数
一、jvm配置参数分为3大类:
1、跟踪参数:跟踪、监控JVM状态,用于程序员JVM调优及故障排查
2、堆分配参数:分配堆内存
3、栈分配参数:分配栈内存
二、各类配置参数常用参数:
1、常用跟踪监控参数:
①打印gc简要信息
第一个:-XX:+PrintGC
第二个:-verbose:gc
这2个参数效果一样,都是在发生gc时,打印gc简要信息的。以
1: [GC (Allocation Failure) 32686K->1648K(123904K), 0.0007230 secs] 2: [GC (Allocation Failure) 34034K->1600K(123904K), 0.0009652 secs]
这个查看结果为例,解释如下:
解释1:总共发生了2次gc,因为打印出的信息标记出了1与2
解释2:以第1次gc为例,32686K表示回收前,对象占用的空间。1648K表示回收后,对象占用的空间。123904K表示还有多少空间可用。0.0007230 secs表示这次垃圾回收花费的时间。
②打印gc详细信息及堆使用详细信息:-XX:+PrintGCDetails
解释1:堆分为新生代、老年代、元空间。
解释2:新生代中又分为伊甸区(eden)和幸存区(from和to)。
解释3:细心的同学可能会发现一种类似于这样的情况:
eden+from+to=65536K+5120K+5120K=75776 并不等于总大小70656K,这是为什么呢?这是因为新生代的垃圾回收算法是采用复制算法,简单的说,就是在from和to之间来回复制(复制过程中再把不可达的对象回收掉),所以必须保证其中一个区是空的,这样才能有预留空间存放复制过来的数据,所以新生代的总大小其实等于eden+from或eden+to=65536K+5120K=70656k。
③将gc日志记录到外部文件中去:-Xloggc:log/gc.log(参数中gc.log就是外部文件的名称)
当java程序出现OOM异常时,总是想查看当时gc的情况,那么使用这个参数记录下gc日志会非常便于故障排查。也可以进行日常JVM监控。
④监控类的加载情况:-XX:+TraceClassLoading
使用这个参数可以监控java程序加载的类。
2、常用堆分配参数
①最大堆:-Xmx,java程序最大能使用多少内存大小,如果超过这个大小,那么java程序会报:out of memory(OOM错误)
②最小堆:-Xms
③指定新生代的内存:-Xmn
④总的堆:目前程序已经配置到的内存大小。一般而言程序一启动,会按照-Xms5m先分配5M的空间,这时总的堆大小就是5M。
⑤空闲堆:程序已经分配的内存大小减去已经使用的内存大小
⑥新生代(eden+from+to)和老年代(不包含永久区)的比值:-XX:NewRatio
Survivor区与Eden区的比值:-XX:SurvivorRatio
这2个比值的计算规则如下:
若-XX:NewRatio=4,则表示新生代:老年代=1:4,那么新生代(eden+from+to)=3072+512+512=4096k,老年代=16384k,新生代:老年代=4096k:16384k=1:4。
若-XX:SurvivorRatio=6,则表示Survivor区:Eden区=2:6,那么Survivor区(from+to)=1024+1024=2048,Eden区=6144,Survivor区:Eden区=2048:6144=2:6,这样的话,一个幸存区占整个新生代区的1:(2+6)=1/8
⑦官方推荐:
新生代占堆的3/8
幸存代占新生代的1/10
⑧发生OOM异常时把堆栈信息打印到外部文件
第1个:-XX:+HeapDumpOnOutOfMemoryError
第2个:-XX:+HeapDumpPath
⑨将堆的最小值-Xms 参数与最大值-Xmx 参数设置为一样即可避免堆自动扩展。因为JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
Arraylist和linklist的区别
1、ArrayList的底层结构数组,LinkedList的底层结构双向链表。
2、对于随机访问,ArrayList优于LinkedList
3、对于插入和删除操作,LinkedList优于ArrayList
4、LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一
个指向前一个元素,一个指向后一个元素。
Arraylist一次扩容多少
扩容1.5倍
Vector是如何实现的安全的
Vector与ArrayList容器的实现原理是一毛一样的,都是封装了一个数组,并且把数组的扩容、缩小交给容器自己管理。不过Vector支持多线程并发访问,因为修改容器的方法都加上了synchronized关键字修饰(this对象锁,锁住整个容器对象)。由于底层是数组,所以随机访问(通过下标访问)效率高,但是在删除节点、插入节点时比较麻烦,删除节点时需要进行大量元素的前移,插入节点时需要进行大量元素的后移,数组容量有限,还需要进行扩容(整个容器中的元素都要复制一遍),效率比较低。
讲讲你知道哪些排序方法,并说下他们的时间复杂度
StringBuild跟StringBuffer的区别
StringBuffer : 对字符串的操作的方法都加了synchronized,保证线程安全。
StringBuilder : 不保证线程安全,在方法体内需要进行字符串的修改操作,可以new StringBuilder
对象,调用StringBuilder对象的append、replace、delete等方法修改字符串。
首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
HashMap跟HashTable区别
1.Hashtable是线程安全的,HashMap是非线程安全的
2.HashMap的性能高于Hashtable
3.Hashtable不能接收null作为键和值,HashMap可以
4.HashMap可以存null的键值对,hashtable不能,HashMap没有多线程机制,所以多线程不安
全,hashtable有线程锁,是线程安全的,hashtable多线程下,会锁住整个code表,效率很
低,为了提高效率,将code表分成了十二个桶,每次锁时只会锁一个桶,提高了效率
一些常见集合的区别
1.List继承了Collection接口 ,可以添加重复的数据,数据可以通过下标单独访问,数据可以排序
2.Set继承了Collection接口,不能添加重复的数据,数据不能单独访问
3.Map数据以键值对保存,键不能重复,数据可以通过键访问
vue子父项目怎么实现请求同步
父组件通过 props 传入状态给子组件,子组件通过 props 来初始化另外一个内部的状态,子组件每
次更改状态之后都通知父组件,然后由父组件来更改自己的状态,就是 props on emit 的应用
css类选择器
类选择器允许以一种独立于文档元素的方式来指定样式。
该选择器可以单独使用,也可以与其他元素结合使用。
只有适当地标记文档后,才能使用选择器,所以使用这两种选择器通常需要先做一些构想和计划。
要应用样式而不考虑具体设计的元素,最常用的方法就是使用类选择器。
es的使用,为什么要用
Elasticsearch具备以下优点:
分布式,无需人工搭建集群
Restful风格,一切API都遵循Rest原则,容易上手
近实时搜索,数据更新在Elasticsearch中几乎是完全同步的。
正排索引
通过key找到value,如通过id找到文章
查询内容时,需要逐条遍历,速度比较慢
倒排索引
通过value找到key
对内容进行分词,生成倒排索引
Redis的几种问题跟解决方案
1)缓存击穿
高并发的情况下,短时间内缓存会被穿过,请求直接打到数据库上,可能导致数据库压力过大。
解决方案:对代码上锁(双重检查锁)
2)缓存穿透
高并发的情况下,如果查询不存在的数据,因为缓存和数据库都不存在,请求都会打到数据库上,可能导致系统崩溃。
解决方案:
1) 保存不存在的数据到缓存中,设置一定过期时间
2) 布隆过滤器(直接过滤掉不存在数据的请求) 不能准确判断是否存在数据,能准确判断数据不存在
3)缓存雪崩
高并发的情况下,缓存服务器重启或热点数据同时过期,全部访问数据库,导致数据库宕机
解决方案:
1)配置缓存集群
2)尽量给热点数据设置不一样的过期时间,相对均匀
消息队列的用法
一对一模型:一个生产者发送消息到一个队列,一个消费者从队列中取消息。
工作队列:工作队列,生产者将消息分发给多个消费者,如果生产者生产了100条消息,消费者1消费50条,消费者2消费50条。 生产者
发布/订阅:发布/订阅模式和Work模式的区别是:Work模式只存在一个队列,多个消费者共同消费一个队列中的消息;而发布订阅模式存在多个队列,不同的消费者可以从各自的队列中处理完全相同的消息。
路由:路由模式的消息队列可以给队列绑定不同的key,生产者发送消息时,给消息设置不同的key,这样交换机在分发消息时,可以让消息路由到key匹配的队列中。
主题:主题模式和路由模式差不多,在key中可以加入通配符:
- \* 匹配任意一个单词 com.* ----> com.hopu com.blb com.baidu
- \# 匹配.号隔开的多个单词 com.* ---> com.hopu.net com.hopu com.163.xxx.xxx.xxx
常见的设计模式知道几种
装饰者设计模式
开闭原则:程序开发过程中,对功能的扩展开放,对功能的修改关闭,提高程序的稳定性
目的:在不修改原有类的代码基础上,对类的功能进行扩展
在Java的IO包下,大量应用了装饰者模式
实现
1.装饰者和被装饰者都要实现相同的接口或继承相同的父类
2.装饰者中定义一个被装饰者的对象
3.给装饰者传入被装饰者对象
4.调用装饰者的方法时,也调用被装饰者的方法,同时进行功能的扩展
单例设计模式
目的:保证一个类只有一个实例(对象)
应用场景:
对于某些大的对象,单例模式能节省系统资源
应用某些特定业务需求,如:保证公司只有一个CEO
实现 PS : Runtime类就是单例模式的
将所有构造方法定义为private
在类中创建一个静态的对象
在类中定义一个静态方法来返回该对象
两种单例模式
饿汉式:类中一开始就创建对象,不管后面是否使用对象,都消耗了内存。
懒汉式:类中一开始不创建对象,调用返回对象方法时再创建对象。
代理模式
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
代理模式的作用
代理模式的作用
1)中介的作用,当调用者不能或不方便调用某个对象时,代理起到中介的作用,帮助调用者间接
的调用对象。
2)符合开闭原则,在不修改原有类代码的前提下,对类的功能进行增强。
代理模式的分类
代理模式分为两种:
1) 静态代理,在运行前,通过编写代码的方式生成代理类
2) 动态代理,在运行后,通过反射机制生成代理类
静态代理
1)代理者和被代理者都实现相同的接口
2)代理者包含被代理者的对象
3)创建代理对象时传入被代理对象
4)代理者执行方法时,会调用被代理者的方法,同时扩展新的功能
静态代理的问题:一个代理类只能代理一种业务,如果有多种业务,就必须创建大量的代理类。
动态代理
和静态代理不同,动态代理是在运行时,通过反射机制动态生成代理类。开发者不需要手动编写新
的代理类。
动态代理分类
JDK动态代理
JDK自带的,前提是:被代理类必须实现过接口。
实现步骤
1) 实现InvocationHandler接口
2)实现invoke方法
3)通过Proxy.newProxyInstance方法返回代理对象
CGLib动态代理
需要引入CGLib依赖,它的原理是:通过反射+继承机制动态生成被代理类的子类,所以被代理类
不能是final的。
实现步骤
1)引入cglib
2)实现MethodInterceptor接口
3)实现intercept方法
4)通过Ehancer返回代理对象
Spring跟SpringCloud区别
Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都
是Spring的ioc、aop等. ioc 提供了依赖注入的容器, aop解决了面向横切面编程,然后在此两者的
基础上实现了其他延伸产品的高级功能;
Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都
是Spring的ioc、aop等. ioc 提供了依赖注入的容器, aop解决了面向横切面编程,然后在此两者的
基础上实现了其他延伸产品的高级功能;
vue的生命周期
Vue 的生命周期总共分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后。
1、beforeCreate(创建前)
表示实例完全被创建出来之前,vue 实例的挂载元素$el和数据对象 data 都为 undefined,还未初
始化。
2、created(创建后)
数据对象 data 已存在,可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成,$el
未存在 。
3、beforeMount(挂载前)
vue 实例的 $el 和 data 都已初始化,挂载之前为虚拟的 dom节点,模板已经在内存中编辑完成
了,但是尚未把模板渲染到页面中。data.message 未替换。
4、mounted(挂载后)
vue 实例挂载完成,data.message 成功渲染。内存中的模板,已经真实的挂载到了页面中,用户
已经可以看到渲染好的页面了。实例创建期间的最后一个生命周期函数,当执行完 mounted 就表
示,实例已经被完全创建好了,DOM 渲染在 mounted 中就已经完成了。
5、beforeUpdate(更新前)
当 data 变化时,会触发beforeUpdate方法 。data 数据尚未和最新的数据保持同步。
6、updated(更新后)
当 data 变化时,会触发 updated 方法。页面和 data 数据已经保持同步了。
7、beforeDestory(销毁前)
组件销毁之前调用 ,在这一步,实例仍然完全可用。
8、destoryed(销毁后)
组件销毁之后调用,对 data 的改变不会再触发周期函数,vue 实例已解除事件监听和 dom绑定,
但 dom 结构依然存在。
List去重,返回去重结果
使用java8新特性stream进行List去重
双重for循环去重
set集合判断去重,不打乱顺序
遍历后判断赋给另一个list集合
set和list转换去重
jq选择器,如何选中元素
JQuery特有的过滤选择器
1) 基本过滤选择器 2)内容过滤选择器 3)可见过滤选择器 4) 属性过滤选择器
5) 子标签过滤选择器 6) 表单属性过滤选择器 7) 表单元素过滤选择器
Spring事务配置的具体流程
(1)事务的传播性:@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
(2)事务的超时性:@Transactional(timeout=30) //默认是30秒
注意这里说的是事务的超时性而不是Connection的超时性,这两个是有区别的
(3)事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED) ,未提交
读,就是一个事务可以读取另一个未提交事务的数据。读取未提交数据(会出现脏读, 不可重复读)
基本不使用;
@Transactional(isolation = Isolation.READ_COMMITTED),已提交读,就是一个事务要等另
一个事务提交后才能读取数据。可以解决脏读,可能会出现不可重复读问题;
@Transactional(isolation = Isolation.REPEATABLE_READ),重复读,就是在开始读取数据
(事务开启)时,不再允许修改操作,重复读可以解决不可重复读问题。不可重复读对应的是修
改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不
是UPDATE操作。
@Transactional(isolation = Isolation.SERIALIZABLE) ,是最高的事务隔离级别,在该级别下,
事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较
耗数据库性能,一般不使用。
面向对象6大原则
1)单一职责原则,一个合理的类,应该仅有一个引起它变化的原因,即单一职责,就是设计的这个类
功能应该只有一个;
优点:消除耦合,减小因需求变化引起代码僵化。
2) 开-闭原则,讲的是设计要对扩展有好的支持,而对修改要严格限制。即对扩展开放,对修改封
闭。
优点:降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系
统需要增加新的功能时,不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的
模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,这样就无
须为原有模块进行重新测试。
3) 里氏代换原则,很严格的原则,规则是“子类必须能够替换基类,否则不应当设计为其子类。”也
就是说,一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类
对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变
化。
优点:可以很容易的实现同一父类下各个子类的互换,而客户端可以毫不察觉。
4) 依赖倒换原则,“设计要依赖于抽象而不是具体化”。换句话说就是设计的时候我们要用抽象来思
考,而不是一上来就开始划分我需要哪些哪些类,因为这些是具体。
高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
另一种表述为: 要针对接口编程,不要针对实现编程。
优点:人的思维本身实际上就是很抽象的,我们分析问题的时候不是一下子就考虑到细节,而
是很抽象的将整个问题都构思出来,所以面向抽象设计是符合人的思维的。另外这个原则会很好的
支持(开闭原则)OCP,面向抽象的设计使我们能够不必太多依赖于实现,这样扩展就成为了可
能,这个原则也是另一篇文章《Design by Contract》的基石。
5) 接口隔离原则,“将大的接口打散成多个小接口”,让系统解耦,从而容易重构,更改和重新部
署。
优点:会使一个软件系统功能扩展时,修改的压力不会传到别的对象那里。
6) 迪米特法则或最少知识原则,这个原则首次在Demeter系统中得到正式运用,所以定义为迪米特
法则。它讲的是“一个对象应当尽可能少的去了解其他对象”。
优点:消除耦合。
RabbitMQ的用途
1)解耦
服务之间进行解耦,A服务调用B服务时,需要编写相关的代码,调用情况发生改变时,需要修改
调用的代码
2)异步
传统的同步调用方式,需要等待调用完成,才能进行其它业务
异步调用方法,将消息发送到队列中,就可以返回,执行其它业务,速度大大提升
3)削峰
出现流量激增的情况时,消息队列可以设置消息的最大数量,处理一部分消息,其它消息交给队列
排队处理
创建线程的三种方式
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口
线程中常用的方法
start() 启动
stop() 停止(禁用,可能导致线程死锁等问题),停止线程可以让run执行结束
String getName() 获得线程的名字
setName(String) 设置线程名字
sleep(long) 进入睡眠,毫秒
setPriority(int) 设置线程的优先级(1~10从低到高)越高抢CPU几率更高
setDaemon(boolean) 设置为后台线程 true ,后台线程是为其它线程服务的,如果没有其它线程存在,就自动死亡;使用案例:GC就是一种后台线程
join() 线程的加入(合并)让其它线程先执行完,再执行自己的指令
Jdk8比以前有什么新特性
函数式接口,Lambda表达式,方法引用,Stream接口, Optional类等。
Elasticsearch用的什么查询
1 term查询(精准查询)
term是ES中的精准查询,不会参与ES分词查询。
2 math查询(分词匹配查询)
match查询是按ES分词的倒排表进行查询,而keyword不会被分词,match的需要跟keyword的完全匹配可以。可以用于一般性的匹配查询。
3 fuzzy查询(模糊查询)
fuzzy查询可以用于纠正去拼写的问题,fuzziness是可以允许纠正错误拼写的个数
4 wildcard(通配符查询)
通配符查询允许我们指定一个模式来匹配,而不需要指定完整的trem,匹配的方式类似于match的
分词匹配查询。
?将会匹配如何字符;*将会匹配零个或者多个字符。
5 bool查询(布尔查询)
bool查询本身没有查询功能,而是基于逻辑值使用前面几种查询方式进行组合查询。
SpringBoot有什么注解
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
根据方法返回的类型,去容器中捞出对应
16、@Qualifier
申明bean名字,且可以按bean名字加载bean
17、@Required
检查bean的属性setXXX()方法,要求属性砸死配置阶段必须已配置
18、@Description
添加bean的文字描述
19、@EnableAspectConfiguration
启动AspectJ自动配置
20、EnableLoadTimeWeaving
启动类加载器动态增强功能,使用instrumentation实现
21、@AutoConfigurationPackage
包含该注解的package会被AutoConfigurationPackages注册
22、@AutoConfigureBefore
在指定配置类初始化前加载
23、@AutoConfigureAfter
在指定配置类初始化后加载
24、@AutoConfigureOrder
指定配置类初始化顺序,越小初始化越早
25、@ModelAttribute
@ModelAttribute注解可被应用在方法和方法参数上。
HashMap+List什么时候触发红黑树
情况一:链表长度到满足8,先尝试转红黑树
情况二:校验数组长度满足64
MIN_TREEIFY_CAPACITY:64
调用treeifyBin()的方法,先判断数组长度是否小于64,小于则进行扩容;否则,转红黑树。
面向对象的理解
万物皆对象,对象是一类事物的抽象。
封装性:封装是一种信息隐蔽技术,它体现于类的说明,是对象的重要特性。封装使数据和加工该
数据的方法(函数)封装为一个整体,以实现独立性很强的模块,使得用户只能见到对象的外特性
(对象能接受哪些消息,具有那些处理能力),而对象的内特性(保存内部状态的私有数据和实现
加工能力的算法)对用户是隐蔽的。封装的目的在于把对象的设计者和对象者的使用分开,使用者
不必知晓行为实现的细节,只须用设计者提供的消息来访问该对象。
继承性:继承性是子类自动共享父类之间数据和方法的机制。它由类的派生功能体现。一个类直接
继承其它类的全部描述,同时可修改和扩充。继承具有传递性。继承分为单继承(一个子类只有一
父类)和多重继承(一个类有多个父类)。类的对象是各自封闭的,如果没继承性机制,则类对象
中数据、方法就会出现大量重复。继承不仅支持系统的可重用性,而且还促进系统的可扩充性。
可以将子类的对象赋值给父类的引用,可以将子类对象当做父类来使用,从而屏蔽不同对象之间的
差异,可以写出更加通用和灵活的代码,以适应不同的业务需求。
多态性:对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行
动,这种现象称为多态性。利用多态性用户可发送一个通用的信息,而将所有的实现细节都留给接
受消息的对象自行决定,如是,同一消息即可调用不同的方法。例如:Print消息被发送给一图或表
时调用的打印方法与将同样的Print消息发送给一正文文件而调用的打印方法会完全不同。多态性的
实现受到继承性的支持,利用类继承的层次关系,把具有通用功能的协议存放在类层次中尽可能高
的地方,而将实现这一功能的不同方法置于较低层次,这样,在这些低层次上生成的对象就能给通
用消息以不同的响应。在OOPL中可通过在派生类中重定义基类函数(定义为重载函数或虚函数)
来实现多态性。
Linux常用命令
切换目录
cd 目录名
查看目录
ls 目录名(不写就是查看当前目录)
-l 详细列表
-a 所有文件
查看目录详情
ll 目录名
创建目录
mkdir 目录名
删除目录
rm 目录名
-r 遍历所有子目录
-f 强制删除
创建\打开文件
vi 文件名
三种模式:
命令模式 能删除、复制、粘贴,无法编辑
输入模式 编辑内容
命令行模式 退出、保存文件
操作方式:默认进入命令模式,按i进入输入模式,按esc回到命令模式,按:进入命令行模式
命令模式
x 删除一个字符
dd 删除一行
yy 复制一行
p 粘贴
u 撤销
命令行模式
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表示强制杀死)
CSS有哪些选择器
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,括号里面可以填以上的选择器)
Radis怎么实现数据同步
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。
Vue怎么实现中英文切换,用什么实现
一、安装 vue-i18n插件
二、main.js文件的配置
三、定义两套中英文的 js 文件,并通过 require 的形式引入到 main.js。
在 main.js 中的代码中,可以看到,当 locale 的值为‘zh-CN’时,版本为中文;当 locale 的值为‘en-
US’,版本为英文。当然你也可以换成 zh 和 en,这个自定义就好,对应上就可以。
四、绑定点击事件,来修改 locale 的值去调用对应的语言包实现语种切换。
五、vue-i18n 数据渲染的模板语法
我们知道 vue 中对于文字数据的渲染,有以‘’{{}}‘’或者 v-text、v-html等的形式,同样的使用国际化
后,依旧可以沿用,但需要一点修改。
MySQL跟Oracle的区别
一、宏观上:
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的诊断调优方法较少,主要有慢查询日志。
在jdbc中是使用什么实现占位符
Statement和PreparedStatement
Statement 接口的两个问题:
第一个问题: 使用 Statement 接口 对象发送的 sql 语句需要再数据库进行一次编译之后成为指令才能执行,
每条 sql 语句都需要编译一次, 这样是很慢的.
第二个问题: 使用 Statement 接口 操作的 sql 语句需要使用字符串的拼接方式实现,
这样的方式可能存在 sql 注入的安全风险并且拼接字符串比较麻烦.
对比 Statement 接口, PreparedStatement 接口的优点:
1.使用该接口操作的 sql 语句会先预先编译成指令在发送给数据库, 数据库就执行指令即可, 这样就提高了一定速度,
2.该接口可以避开 sql 需要使用字符串拼接的方式, 从而解决 sql 注入的安全风险,
而是使用占位符 (?) 来代替原来的字符串拼接.
MyBaits常用注解
@Insert : 实现新增
@Update: 实现更新
@Delete:实现删除
@Select:实现查询
@Result:
实现结果集封装
@Results:
可以与@Result 一起使用,封装多个结果集
@ResultMap:
实现引用@Results 定义的封装
@One:
实现一对一结果集封装
@Many:
实现一对多结果集封装
@CacheNamespace:
实现注解二级缓存的使用
复杂关系映射的注解说明
@Results 注解
代替的是标签<resultMap>
@Resutl 注解
代替了 <id> 标签和<result> 标签
@One 注解(一对一)
代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
@Many 注解(多对一)
代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
Redis的执行原理
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. 创建索引也需要一定的时间
sleep和wait的区别
-
调用对象不同
wait() 由锁对象调用
sleep() 由线程调用
-
锁使用不同
执行wait后,自动释放锁
执行sleep后,不会释放锁
-
唤醒机制不同
执行wait后,可以被通知唤醒
执行sleep后,只能等待时间结束后,自动唤醒
深复制和浅复制的区别
浅复制:复制出来的对象,能复制所有基本类型以及String的属性,对于引用类型的属性只能复制地址
深复制:复制出来的对象,基本类型和引用类型的属性,都完全是不同的对象
实现方式:序列化和反序列化