收集的面试题 一

1、数据库语句是如何优化的

  1. 查询 SQL时 尽量不要使用 select *

  2. 尽量不使用or关键字

  3. 模糊查询时,不要把%放前面

  4. 尽量避免在索引列上使用 MySQL 的内置函数

  5. .使用 explain 分析你的查询过程

3、你使用SpringBoot的时候各种配置文件是怎么引入的

在spring-boot-autoconfigure包下保存大量的自动配置类

类名都保存 META-INFO/spring.factotiries文件下

自动配置类生效需要一定条件,如@ConditionalOnClass,引入某些类时(导入了对应的框架依赖)

启动类上的注解:@SpringBootApplication

包含三个注解:

     1.@ComponentScan 包的扫描

     2.@SpringBootConfiguration 定义配置类

     3.@EnableAutoConfiguration 启动自动配置(将自动配置类加载到内存)

怎么加载类到内存中? Class.forName("完整类名")

@EnableAutoConfiguration --> AutoConfigurationImportSelector --> loadFactoryNames --->

loadSpringFactories --> classLoader.getResources("META-INF/spring.factories")

6、说说你做过的项目和你主要负责的模块

滴哒在线教育平台采用分布式的架构设计,包括后台管理、前台系统、订单系统、单点系统、搜索系统、课程系统、广告系统、支付系统等。教育平台包括前台模块与后台模块。前台主要包括:个人信息管理、课程信息查询、课程信息浏览、课程搜索、智能排序、在线支付、购物车管理、订单确定等。后台主要包括:用户管理、角色管理、权限管理、课程管理、订单管理等模块。

  1. 课程搜索,使用ES实现,服务启动时会对ES进行初始化,获得MySQL的数据,通过ES进行关键字查询,分页查询,多条件过滤、排序获得课程数据。
  2. 课程添加,当课程进行修改时同时修改Redis缓存,然后向RabbitMQ消息队列通知搜索服务,搜索服务会进行ES的数据同步
  3. 单点登录,采用了 JWT 和 RSA 加密算法,鉴权服务生成 token 字符串,网关服务从前端的请求头中获取并解密 token。
  4. 订单模块:使用Sharding-Sphere进行分库分表,通过Seata解决分库分表带来分布式事务问题。
  5. 微信支付,用户点击购买后台会进行下单,后台调用微信支付的统一下单API然后返回一个支付url,后台利用url生成二维码返回给前端,用户扫码支付成功后,微信会通知后台接口,后台会修改订单状态,通知微信支付结果收到。

7、讲讲Redis,你在项目中有用过Redis吗

Redis是一个高性能的内存数据库,以key-value方式存储数据,可以作为缓存使用。

高并发        MySQL的连接数存在瓶颈,连接过大可能导致MySQL宕机

解决方法        部署多个MySQL服务,主从复制        部署缓存,承担一部分的并发

高性能         基于内存,内存IO效率远远高于磁盘

Redis的特点

        性能高(读的速度是110000次/s,写的速度是81000次/s,单机redis支撑万级并发)

        支持多种存储类型

        丰富的特性(发布订阅、事务、过期策略等)

        支持持久化

        单线程 (避免上下文切换,线程同步问题)


项目中在查询及解决消息幂等性时会使用到

9、数据库建表的时候int(1)和int(2)的区别

在 int(M) 中,M 的值跟 int(M) 所占多少存储空间并无任何关系。 int(1)、int(2) 在磁盘上都是占用 4 btyes 的存储空间。除了显示给用户的方式有点不同外,int(M) 跟 int 数据类型是相同的。

int(2)代表默认显示长度是2,当不足2位时,会帮你用0补全,超过时,没有任何影响。

1、#和$的区别

#{xx}应用PreparedStatement的占位符?插入,能防止SQL注入

${xx}应用字符串的拼接,不能防止SQL注入

2、SpringMVC的执行流程

1)用户发送请求

2)前端控制器获得用户请求的URL,发送URL给处理器映射

3)处理器映射将Handler(包装方法信息)返回给前端控制器

4)前端控制器发送Handler给处理器适配器,适配器执行Handler方法

5)执行Handler方法后,返回ModelAndView(逻辑视图)给前端控制器

6)前端控制器将ModelAndView发送给视图解析器,解析出物理视图返回给前端控制器

7)前端控制器渲染视图,发送视图给用户

3、讲讲IOC

IOC(Inverse of Control)控制反转是一种程序设计思想。

控制是什么?

JavaBean(Java对象)的创建和管理

反转是什么?

一般情况下对象的创建和管理由开发者控制,反转是把对象的创建和管理交给容器完成,然后再交给开发者。

4、jvm参数

jvm配置参数分为3大类:

        1.跟踪参数:跟踪、监控JVM状态,用于程序员JVM调优及故障排查

        2.堆分配参数:分配堆内存

        3.栈分配参数:分配栈内存

5、反射的三种创建方式

  1. 类名.class

  2. 对象.getClass()

  3. Class.forName("包名+类名")

6、ArrayList和LinkedList的区别

1.ArrayList是数组,LinkedList是双向链表

2.ArrayList查找性能高(因为通过下标快速定位),插入和删除性能低(移动大量数据)

3.LinkedList查找性能低(因为要向前或向后依次查找),插入和删除姓高(只需要修改前后指针,不用移动)

4.LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一

个指向前一个元素,一个指向后一个元素。

7、ArrayList一次扩容多少

新容量是原来容量的1.5倍        

使用新容量创建新数组,将原数组的数据复制过去,将新数组赋值给原数组的引用

8、Vector是如何实现线程安全的

Vector与ArrayList容器的实现原理是一样的,不过Vector支持多线程并发访问,因为修改容器的方法都加上了synchronized关键字修饰。

9、讲讲你知道哪些排序方法,并说一下他们的时间复杂度

1、mysql的优化

2、StringBuild和StringBuffer的区别

StringBuffer是线程安全的,StringBuilder是非线程安全的

StringBuffer的执行效率没有StringBuilder高

3、HashMap和Hashtable的区别

1.Hashtable是线程安全的,HashMap是非线程安全的

2.HashMap的性能高于Hashtable

3.Hashtable不能接收null作为键和值,HashMap可以

4、一些常见集合的区别

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 键。

5、Vue子父项目怎么实现请求同步

父组件通过 props 传入状态给子组件,子组件通过 props 来初始化另外一个内部的状态,子组件每

次更改状态之后都通知父组件,然后由父组件来更改自己的状态,就是 props on emit 的应用

6、CSS类选择器

类选择器允许以一种独立于文档元素的方式来指定样式。

该选择器可以单独使用,也可以与其他元素结合使用。

只有适当地标记文档后,才能使用选择器,所以使用这两种选择器通常需要先做一些构想和计划。

要应用样式而不考虑具体设计的元素,最常用的方法就是使用类选择器。

7、es的使用 为什么要使用

Elasticsearch具备以下特点:

        分布式,无需人工搭建集群

        Restful风格,一切API都遵循Rest原则,容易上手

        近实时搜索,数据更新在Elasticsearch中几乎是完全同步的。

正排索引

        通过key找到value,如通过id找到文章

        查询内容时,需要逐条遍历,速度比较慢

倒排索引

        通过value找到key

        对内容进行分词,生成倒排索引

8、为什么要用Redis

9、Redis的几种问题和解决方案

1)缓存击穿

高并发的情况下,短时间内缓存会被穿过,请求直接打到数据库上,可能导致数据库压力过大。

解决方案:对代码上锁(双重检查锁)

2)缓存穿透

高并发的情况下,如果查询不存在的数据,因为缓存和数据库都不存在,请求都会打到数据库上,可能导致系统崩溃。

解决方案:

        1) 保存不存在的数据到缓存中,设置一定过期时间

        2) 布隆过滤器(直接过滤掉不存在数据的请求) 不能准确判断是否存在数据,能准确判断数据不存在

        3)缓存雪崩

高并发的情况下,缓存服务器重启或热点数据同时过期,全部访问数据库,导致数据库宕机

解决方案:

        1)配置缓存集群

        2)尽量给热点数据设置不一样的过期时间,相对均匀

10、消息队列的用法

1.最基本的队列模型: 一个生产者发送消息到一个队列,一个消费者从队列中取消息。

2.工作队列,生产者将消息分发给多个消费者,如果生产者生产了100条消息,消费者1消费50条,消费者2消费50条。

实现能者多劳:

channel.basicQos(1);限制队列一次发一个消息给消费者,等消费者有了反馈,再发下一条

channel.basicAck 消费完消息后手动反馈,处理快的消费者就能处理更多消息

basicConsume 中的参数改为false

3.发布/订阅模式和Work模式的区别是:Work模式只存在一个队列,多个消费者共同消费一个队列中

的消息;而发布订阅模式存在多个队列,不同的消费者可以从各自的队列中处理完全相同的消息。

1) 创建交换机(Exchange)类型是fanout(扇出)

2) 交换机需要绑定不同的队列

3) 不同的消费者从不同的队列中获得消息

4) 生产者发送消息到交换机

5) 再由交换机将消息分发到多个队列

4.路由模式的消息队列可以给队列绑定不同的key,生产者发送消息时,给消息设置不同的key,这样

交换机在分发消息时,可以让消息路由到key匹配的队列中。

5.主题模式和路由模式差不多,在key中可以加入通配符:

        * 匹配任意一个单词 com.* ---->com.baidu  com.xxx

        # 匹配.号隔开的多个单词 com.* ---> com.xxx.xxx.baidu

11、常见的设计模式知道几种

1.装饰者设计模式

开闭原则:程序开发过程中,对功能的扩展开放,对功能的修改关闭,提高程序的稳定性

目的:在不修改原有类的代码基础上,对类的功能进行扩展

在Java的IO包下,大量应用了装饰者模式

实现

        1.装饰者和被装饰者都要实现相同的接口或继承相同的父类

        2.装饰者中定义一个被装饰者的对象

        3.给装饰者传入被装饰者对象

        4.调用装饰者的方法时,也调用被装饰者的方法,同时进行功能的扩展

2.单例设计模式

目的:保证一个类只有一个实例(对象)

应用场景:

对于某些大的对象,单例模式能节省系统资源

应用某些特定业务需求,如:保证公司只有一个CEO

实现 PS : Runtime类就是单例模式的

将所有构造方法定义为private

在类中创建一个静态的对象

在类中定义一个静态方法来返回该对象

两种单例模式

饿汉式:类中一开始就创建对象,不管后面是否使用对象,都消耗了内存。

懒汉式:类中一开始不创建对象,调用返回对象方法时再创建对象。

3.代理模式

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

代理模式的作用

        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返回代理对象

12、Spring和SpringCloud的区别

Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都

是Spring的ioc、aop等. ioc 提供了依赖注入的容器, aop解决了面向横切面编程,然后在此两者的

基础上实现了其他延伸产品的高级功能;

SpringCloud是一套目前完整的微服务框架,它是是一系列框架的有序集合。它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot的开发风格做到一键启动和部署

1、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 结构依然存在。

2、list去重,返回去重结果

使用stream进行set和list转换去重 

使用for循环遍历判断去重

4、jq选择器,如何选中元素

JQuery特有的过滤选择器

1) 基本过滤选择器       

 2)内容过滤选择器         

3)可见过滤选择器         

4) 属性过滤选择器

5) 子标签过滤选择器         

6) 表单属性过滤选择器         

7) 表单元素过滤选择器

5、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、java常见的设计模式

7、面向对象六大原则

1)单一职责原则,一个合理的类,应该仅有一个引起它变化的原因,即单一职责,就是设计的这个类

功能应该只有一个;

  优点:消除耦合,减小因需求变化引起代码僵化。

2) 开-闭原则,讲的是设计要对扩展有好的支持,而对修改要严格限制。即对扩展开放,对修改封

闭。

  优点:降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系

统需要增加新的功能时,不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的

模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,这样就无

须为原有模块进行重新测试。

3) 里氏代换原则,很严格的原则,规则是“子类必须能够替换基类,否则不应当设计为其子类。”也

就是说,一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类

对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变

化。

  优点:可以很容易的实现同一父类下各个子类的互换,而客户端可以毫不察觉。

4) 依赖倒换原则,“设计要依赖于抽象而不是具体化”。换句话说就是设计的时候我们要用抽象来思

考,而不是一上来就开始划分我需要哪些哪些类,因为这些是具体。

高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

另一种表述为: 要针对接口编程,不要针对实现编程。

  优点:人的思维本身实际上就是很抽象的,我们分析问题的时候不是一下子就考虑到细节,而

是很抽象的将整个问题都构思出来,所以面向抽象设计是符合人的思维的。另外这个原则会很好的

支持(开闭原则)OCP,面向抽象的设计使我们能够不必太多依赖于实现,这样扩展就成为了可

能,这个原则也是另一篇文章《Design by Contract》的基石。

5) 接口隔离原则,“将大的接口打散成多个小接口”,让系统解耦,从而容易重构,更改和重新部

署。

  优点:会使一个软件系统功能扩展时,修改的压力不会传到别的对象那里。

6) 迪米特法则或最少知识原则,这个原则首次在Demeter系统中得到正式运用,所以定义为迪米特

法则。它讲的是“一个对象应当尽可能少的去了解其他对象”。

优点:消除耦合。

1、SpringMVC执行流程

2、RabbitMQ的用途

1)解耦

服务之间进行解耦,A服务调用B服务时,需要编写相关的代码,调用情况发生改变时,需要修改

调用的代码

2)异步

传统的同步调用方式,需要等待调用完成,才能进行其它业务

异步调用方法,将消息发送到队列中,就可以返回,执行其它业务,速度大大提升

3)削峰

出现流量激增的情况时,消息队列可以设置消息的最大数量,处理一部分消息,其它消息交给队列

排队处理

3、创建线程的三种方式

继承Thread类

1)继承Thread类        

2)重写run方法        

实现Runnable接口

1)实现Runnable接口      

 2)实现run方法

3)创建实现Runnable接口的对象,传入Thread对象中      

实现Callable接口

1)实现Callable接口,实现call方法        

2)创建Callable对象,传入FutureTask对象

3)创建FutureTask对象,传入Thread对象        

4)启动线程

5)调用get方法得到返回结果

4、线程中常用的方法

方法介绍
start()启动
stop()停止(禁用,可能导致线程死锁等问题),停止线程可以让run执行结束
String getName()获得线程的名字
setName(String)设置线程名字
sleep(long)进入睡眠,毫秒
setPriority(int)设置线程的优先级(1~10从低到高)越高抢CPU几率更高
setDaemon(boolean)设置为后台线程 true ,后台线程是为其它线程服务的,如果没有其它线程存在,就自动死亡;使用案例:GC就是一种后台线程
join()线程的加入(合并)让其它线程先执行完,再执行自己的指令

5、list set map 集合特性

List集合的特点:

- 可以添加重复的数据
- 数据可以通过下标单独访问
- 数据可以排序

Set集合的特点:

- 不能添加重复的数据
- 数据不能单独访问

Map集合的特点:

- 数据以键值对保存
- 键不能重复
- 数据可以通过键访问

1、SpringMVC的执行流程

2、jdk8比以前有什么新特性

函数式接口、Lambda表达式、Stream接口、方法的引用、新的日期时间API等

3、map和list

4、RabbitMQ

5、Vue的特性

1) 轻量级的框架

Vue.js 能够自动追踪依赖的模板表达式和计算属性,提供 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API,使读者更加容易理解,能够更快上手。

2) 双向数据绑定

声明式渲染是数据双向绑定的主要体现,同样也是 Vue.js 的核心,它允许采用简洁的模板语法将数据声明式渲染整合进 DOM。

3) 指令

Vue.js 与页面进行交互,主要就是通过内置指令来完成的,指令的作用是当其表达式的值改变时相应地将某些行为应用到 DOM 上。

4) 组件化

组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。

在 Vue 中,父子组件通过 props 传递通信,从父向子单向传递。子组件与父组件通信,通过触发事件通知父组件改变数据。这样就形成了一个基本的父子通信模式。

在开发中组件和 HTML、JavaScript 等有非常紧密的关系时,可以根据实际的需要自定义组件,使开发变得更加便利,可大量减少代码编写量。

组件还支持热重载(hotreload)。当我们做了修改时,不会刷新页面,只是对组件本身进行立刻重载,不会影响整个应用当前的状态。CSS 也支持热重载。

5) 客户端路由

Vue-router 是 Vue.js 官方的路由插件,与 Vue.js 深度集成,用于构建单页面应用。Vue 单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来,传统的页面是通过超链接实现页面的切换和跳转的。

6) 状态管理

状态管理实际就是一个单向的数据流,State 驱动 View 的渲染,而用户对 View 进行操作产生 Action,使 State 产生变化,从而使 View 重新渲染,形成一个单独的组件。

6、es用的什么查询

ElasticSearch常用的几种查询方式,terms 查询是term的扩展,可以支持多个vlaue匹配,只需要一个匹配就可以了。

1 term查询(精准查询)

term是ES中的精准查询,不会参与ES分词查询。

2 math查询(分词匹配查询)

match查询是按ES分词的倒排表进行查询,而keyword不会被分词,match的需要跟keyword的完全匹配可以。可以用于一般性的匹配查询。

3 fuzzy查询(模糊查询)

fuzzy查询可以用于纠正去拼写的问题,fuzziness是可以允许纠正错误拼写的个数

4  wildcard(通配符查询)

通配符查询允许我们指定一个模式来匹配,而不需要指定完整的trem,匹配的方式类似于match的

分词匹配查询。

?将会匹配如何字符;*将会匹配零个或者多个字符。

5 bool查询(布尔查询)

bool查询本身没有查询功能,而是基于逻辑值使用前面几种查询方式进行组合查询。

7、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注解可被应用在方法和方法参数上。

8、Redis的作用

9、HashMap+list什么时候触发红黑树

1.链表的长度达到8个

2.数组的长度达到64个

10、面向对象的理解

封装:

装(把代码装起来,把一个类相关的属性和方法装起来,将一些代码装到方法中,方便调用)

封(信息的隐藏,将某些属性和方法隐藏起来,提供公开的属性和方法供调用者使用)

继承:

子类能够继承父类的属性和方法,实现了代码的重用,多个类具有相同的属性和方法,提取出来放到共同的父类提升了代码重用性、可维护性和可扩展性。

多态:

可以将子类的对象赋值给父类的引用,可以将子类对象当做父类来使用,从而屏蔽不同对象之间的

差异,可以写出更加通用和灵活的代码,以适应不同的业务需求。


11.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 待解压的解压包名 
 

12、数据库的优化

1、mysql跟oracle的区别

(1) 对事务的提交
    MySQL默认是自动提交,而Oracle默认不自动提交,需要用户手动提交,需要在写commit;指令或者点击commit按钮

(2) 分页查询
    MySQL是直接在SQL语句中写"select... from ...where...limit  x, y",有limit就可以实现分页;而Oracle则是需要用到伪列ROWNUM和嵌套查询
(3) 事务隔离级别
      MySQL是read commited的隔离级别,而Oracle是repeatable read的隔离级别,同时二者都支持serializable串行化事务隔离级别,可以实现最高级别的
    读一致性。每个session提交后其他session才能看到提交的更改。Oracle通过在undo表空间中构造多版本数据块来实现读一致性,每个session
    查询时,如果对应的数据块发生变化,Oracle会在undo表空间中为这个session构造它查询时的旧的数据块
    MySQL没有类似Oracle的构造多版本数据块的机制,只支持read commited的隔离级别。一个session读取数据时,其他session不能更改数据,但
    可以在表最后插入数据。session更新数据时,要加上排它锁,其他session无法访问数据
(4) 对事务的支持
    MySQL在innodb存储引擎的行级锁的情况下才可支持事务,而Oracle则完全支持事务
(5) 保存数据的持久性
    MySQL是在数据库更新或者重启,则会丢失数据,Oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,可以随时恢复
(6) 并发性
    MySQL以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。
  虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。
  Oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。所以Oracle对并
  发性的支持要好很多。
(7) 逻辑备份
    MySQL逻辑备份时要锁定数据,才能保证备份的数据是一致的,影响业务正常的dml使用,Oracle逻辑备份时不锁定数据,且备份的数据是一致
(8) 复制
    MySQL:复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换丛库到主库。
    Oracle:既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题是,可以自动切换备库到主库,但配置管理较复杂。
(9) 性能诊断
    MySQL的诊断调优方法较少,主要有慢查询日志。
    Oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、sqltrace、tkproof等    
(10)权限与安全
    MySQL的用户与主机有关,感觉没有什么意义,另外更容易被仿冒主机及ip有可乘之机。
    Oracle的权限与安全概念比较传统,中规中矩。
(11)分区表和分区索引
    MySQL的分区表还不太成熟稳定。
    Oracle的分区表和分区索引功能很成熟,可以提高用户访问db的体验。
(12)管理工具
    MySQL管理工具较少,在linux下的管理工具的安装有时要安装额外的包(phpmyadmin, etc),有一定复杂性。
    Oracle有多种成熟的命令行、图形界面、web管理工具,还有很多第三方的管理工具,管理极其方便高效。
(13)最重要的区别
    MySQL是轻量型数据库,并且免费,没有服务恢复数据。
    Oracle是重量型数据库,收费,Oracle公司对Oracle数据库有任何服务。

(13) 的数据处理
          MYSQL有自动增长的数据类型,插入记录时不用操作此字段,会自动获得数据值。ORACLE没有自动增长的数据类型,需要建立一个自动增长的序列号,插入记录时要把序列号的下一个值赋于此字段。
         CREATE SEQUENCE 序列号的名称 (最好是表名+序列号标记) INCREMENT BY 1        START        WITH        1 MAXVALUE        99999        CYCLE        NOCACHE;
          其中最大的值按字段的长度来定, 如果定义的自动增长的序列号 NUMBER(6) , 最大值为999999
          INSERT 语句插入这个字段值为: 序列号的名称.NEXTVAL
(14) 引号的处理
          MYSQL里可以用双引号包起字符串,ORACLE里只可以用单引号包起字符串。在插入和修改字符串前必须做单引号的替换:把所有出现的一个单引号替换成两个单引号。
(15)  SQL句的处理
          MYSQL处理翻页的SQL语句比较简单,用LIMIT 开始位置, 记录个数;PHP里还可以用SEEK定位到结果集的位置。ORACLE处理翻页的SQL语句就比较繁琐了。每个结果集只有一个ROWNUM字段标明它的位置, 并且只能用ROWNUM<100, 不能用ROWNUM>80。

(16) 长字符串的处理
    
长字符串的处理ORACLE也有它特殊的地方。INSERT和UPDATE时最大可操作的字符串长度小于等于4000个单字节, 如果要插入更长的字符串, 请考虑字段用CLOB类型,方法借用ORACLE里自带的DBMS_LOB程序包。插入修改记录前一定要做进行非空和长度判断,不能为空的字段值和超出长度字段值都应该提出警告,返回上次操作。

(17)  日期字段的处理
    
       MYSQL日期字段分DATE和TIME两种,ORACLE日期字段只有DATE,包含年月日时分秒信息,用当前数据库的系统时间为SYSDATE, 精确到秒,或者用字符串转换成日期型函数TO_DATE(‘<st1:chsdate isrocdate="False" islunardate="False" day="1" month="8" year="2001">2001-08-01</st1:chsdate>’,’YYYY-MM-DD’)年-月-日 24小时:分钟:秒 的格式YYYY-MM-DD HH24:MI:SS TO_DATE()还有很多种日期格式, 可以参看ORACLE DOC.日期型字段转换成字符串函数TO_CHAR(‘<st1:chsdate isrocdate="False" islunardate="False" day="1" month="8" year="2001">2001-08-01</st1:chsdate>’,’YYYY-MM-DD HH24:MI:SS’)
    日期字段的数学运算公式有很大的不同。MYSQL找到离当前时间7天用 DATE_FIELD_NAME > SUBDATE(NOW(),INTERVAL 7 DAY)ORACLE找到离当前时间7天用 DATE_FIELD_NAME >SYSDATE - 7;
(18) 空字符的处理
         
  MYSQL的非空字段也有空的内容,ORACLE里定义了非空字段就不容许有空的内容。按MYSQL的NOT NULL来定义ORACLE表结构, 导数据的时候会产生错误。因此导数据时要对空字符进行判断,如果为NULL或空字符,需要把它改成一个空格的字符串。
(19)字符串的模糊比较
         
 MYSQL里用 字段名 like '%字符串%',ORACLE里也可以用 字段名 like '%字符串%' 但这种方法不能使用索引, 速度不快,用字符串比较函数 instr(字段名,'字符串')>0 会得到更精确的查找结果。

2、mysql的优化

3、ArrayList和LinkedList区别

4、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,括号里面可以填以上的选择器)
 

5、Nginx在项目中具体怎么使用

Nginx作为反向代理服务器可以对服务器的域名和端口进行映射,起到的作用有:

  1. 隐藏真正服务器的地址,提高安全性

  2. 解决跨域问题,将不同的域名和端口映射为相同的

  3. 负载均衡,将大量请求分发给不同的服务器处理

  4. 动静分离,将对不同资源的请求分发给处理各自资源的服务器等

在SpringBoot项目中添加控制器,端口是默认的8080

1. 将localhost映射到域名上
2. 将端口8080映射到80端口上(浏览器默认)

6、SpringBoot有哪些注解

7、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。
 

8、RabbitMQ消息队列

11、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等的形式,同样的使用国际化

后,依旧可以沿用,但需要一点修改。
 

12、单点登录的实现

采用了 JWT 和 RSA 加密算法,鉴权服务生成 token 字符串,网关服务从前端的请求头中获取并解密 token

13、项目开发时为什么想要用es,怎么用

1、#和$的作用

2、在jdbc中是使用什么实现占位符

PreparedStatement 接口:
  1.使用该接口操作的 sql 语句会先预先编译成指令在发送给数据库, 数据库就执行指令即可, 这样就提高了一定速度,
  2.该接口可以避开 sql 需要使用字符串拼接的方式, 从而解决 sql 注入的安全风险,
  而是使用占位符 (?) 来代替原来的字符串拼接.
 

3、vue的生命周期

5、SpringMVC的执行流程,三层的注解

6、mybatis常用注解

@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逻辑,后者负责处理数据过期、增量持久化的文件写入等任务
 

7、消息队列的作用

8、常见的设计模式

9、Redis执行原理

11、三个集合的特性

12、创建线程的方式

13、线程中常用的方法

14、Spring的事务

Spring中隔离级别的配置

@Transactional注解的属性isolation

值:

Isolation.DEFAULT 默认,和数据库隔离级别一致

Isolation.Readuncommitted 读未提交

Isolation.Readcommitted 读已提交

Isolation.Repeatableread 可重复读

Isolation.Serializable 串行化

1、索引的作用

加快查询速度,用户查询时,先找索引,通过索引找到实际数据的位置,再直接定位到实际数据上。

        优点:

        极大提高查询速度

        缺点:

        1. 也是数据,需要占存储空间
        2. 降低增删改的速度
        3. 创建索引也需要一定的时间

2、sql语句的优化

3、Linux常用命令

4、控制反转和注入方式

IOC(Inverse of Control)控制反转是一种程序设计思想。

控制是什么?

JavaBean(Java对象)的创建和管理

反转是什么?

一般情况下对象的创建和管理由开发者控制,反转是把对象的创建和管理交给容器完成,然后再交给开发者。

注入属性的几种方式:

1) set方法注入

2) 构造方法注入

3) 自动装配

类型:

  • no 默认,不自动装配

  • byType 通过类型查找对象,如果相同类型的对象有多个,会出现异常

  • byName 通过名称查找对象,如果找不到对应的id或name的对象,会出现空指针异常

  • constructor 通过构造方法装配

5、linux查看日志文件

 tail:  

       -n  是显示行号;相当于nl命令;例子如下:

            tail -100f test.log      实时监控100行日志

            tail  -n  10  test.log   查询日志尾部最后10行的日志;

            tail -n +10 test.log    查询10行之后的所有日志;

    head:  

        跟tail是相反的,tail是看后多少行日志;例子如下:

            head -n 10  test.log   查询日志文件中的头10行日志;

            head -n -10  test.log   查询日志文件除了最后10行的其他所有日志;

    cat: 

        tac是倒序查看,是cat单词反写;例子如下:

            cat -n test.log |grep "debug"   查询关键字的日志

6、为什么要用FastDFS?相比其他图片上传有什么优势

FastDFS是阿里巴巴开源的一套轻量级,天生就是分布式设计的文件系统,FastDFS的源代码由C语言开发,目前可运行在Linux,FreeBSD,Unix等类操作系统上,FastDFS解决了大数据量文件存储和读写分离,备份容错,负载均衡,动态扩容等问题,这也就是原作者所描述的高性能和高扩展性的文件系统。适合存储4KB~500MB之间的小文件,如图片网站、短视频网站、文档、app下载站等。

优势

  1. 只能通过专用的API访问,不支持posix,降低了系统的复杂度,处理效率高
  2. 支持在线扩容,增强系统的可扩展性
  3. 支持软RAID,增强系统的并发处理能力及数据容错能力。Storage是按照分组来存储文件,同组内的服务器上存储相同的文件,不同组存储不同的文件。Storage-server之间不会互相通信。
  4. 主备Tracker,增强系统的可用性。
  5. 支持主从文件,支持自定义扩展名。
  6. 文件存储不分块,上传的文件和os文件系统中的文件一一对应。
  7. 相同内容的文件只存储一份,节约磁盘存储空间。对于上传相同的文件会使用散列方式处理文件内容,假如是一致就不会存储后上传的文件,只是把原来上传的文件在Storage中存储的id和URL返回给客户端。

7、什么是线程

线程是CPU资源分配的最小单元

进程包含一个或多个线程

线程需要的资源更少,可以看做是一种轻量级的进程

线程会共享进程中的内存,线程也有独立的空间(栈、程序计数器)

线程之间可以相互通信

8、创建线程的几种方式

9、sleep和wait的区别

  1. 调用对象不同

    wait() 由锁对象调用

    sleep() 由线程调用

  2. 锁使用不同

    执行wait后,自动释放锁

    执行sleep后,不会释放锁

  3. 唤醒机制不同

    执行wait后,可以被通知唤醒

    执行sleep后,只能等待时间结束后,自动唤醒

10、深拷贝和浅拷贝的区别

深拷贝复制出来的对象,基本类型和引用类型的属性,都完全是不同的对象

浅拷贝复制出来的对象,能复制所有基本类型以及String的属性,对于引用类型的属性只能复制地址

笔试题

1、方法中定义的临时变量在方法调用完成之后就不存在了,不需要用修饰符定义

2、没问题(不知道)

3、不可以直接调用toString方法

4、在接口中只能定义常量,不能为常量赋值

5、冒泡排序

for(int i = 0;i < array.length - 1;i++){
    for(int j = 0;j < array.length - 1 - i;j++){
        if(array[j] > array[j+1]){
            int temp = array[j];
            array[j] = array[j+1];
            array[j+1] = temp;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值