这里是引用
这里是引用
1.用户发送请求至前端控制器DispatcherServlet
2.DispatcherServlet收到请求调用HandlerMapping处理器映射器
3.处理器映射器找到具体的处理器,生成处理器对象并返回给DispatcherServlet
4.DispatcherServlet调用HandlerAdapter处理器适配器
5.HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)
- 构造器注入
- set方法注入(支持循环依赖)
- 工厂方法注入
链接: Spring Cloud Alibaba与Spring Cloud Netflix区别
Spring Cloud Alibaba是阿里开源的一套Sping Cloud规范的实现,配置比 NetFlix 更简单易用
链接: Nacos 原理
一级缓存,默认开启(只针对同一个会话,一旦表出现更新操作,则会话失效)
二级缓存是基于namespace级别的缓存
基于namespace,也就是我们项目中的xml文件
- mysql是免费的,oracle是收钱的。
- 对于互联网应用来说,数据库只是作为存储数据的服务来用,因此oracle那样的强大功能用不上,mysql足够
- mysql更加轻便且操作简单、Oracle更加重且操作复杂
这里是引用
常用的存储引擎是InnoDB,InnoDB有个聚簇索引,所有数据都是放在聚簇索引的叶子节点上,检索数据时,根据主键就检索到对应的数据
链接: MySQL千万级数据查询的优化技巧及思路
合理创建索引、进行表分区、优化SQL语句
总共有7个核心参数:
- 核心线程数:核心线程会一直存活
- 最大线程数:线程池能生产的最多的线程数量
- 空闲线程存活时间单位
- 空闲线程存活时间
- 阻塞队列:用于存放多余的任务
- 线程工厂:用于创建线程
- 拒绝策略:当线程达到最大数且队列也满了的时候,对于新的任务的处理方式,共有四种策略(回退主线程、抛出异常、丢弃任务、丢弃队列中第一个任务)
带返回值的任务都是通过Callable+FutureTask的方式来实现,执行Callable接口后,可以获得一个Future的一个对象,通过Feture的get方法就能获得返回的Object数据了。
提示:有返回值的任务必须实现Callable接口,没有返回值的任务实现Runnable接口
高是16位用来表示读锁(共享锁),低16位用来表示写锁(独占锁)
AQS如何用一个Int值来表示读写两种状态
没用到
没用到
root 和 alias 都可以定义在 location 模块中,都是用来指定请求资源的真实路径
alias 是一个目录别名的定义,root 则是最上层目录的定义。
nginx负载均衡的5种策略
轮询(默认)、权重、ip_hash、响应时间短优先、url_hash
ip_hash,同一个IP地址的hash值一样,因此就可以会话保持
B+树结构
从根节点开始往下检索、同时也可以从左边的叶子节点开始往后检索
不是,索引过多会占用更多的内存,并且索引越多,维护成本就越高
因为没次更新数据,都需要去重新构建索引(对索引中的数据更新)
- 频繁作为 WHERE 查询条件的字段
- 经常 GROUP BY 和 ORDER BY 的列
- UPDATE、DELETE 的 WHERE 条件列
- DISTINCT 字段需要创建索引
- 区分度高(散列性高)的列适合作为索引
聚簇索引只存在Innodb存储引擎中,且每个InnoDB表都有一个聚簇索引 ,聚簇索引使用B+树构建,叶子节点存储的数据是整行记录。一般情况下,聚簇索引等同于主键索引,当一个表没有创建主键索引时,InnoDB会自动创建一个ROWID字段来构建聚簇索引
便于项目中线程的管理,避免了线程的来回创建于销毁,减轻服务器压力,可以最大程度的重复利用线程
- 退回调用者
- 抛出异常
- 丢弃任务
- 丢弃队列中等待最久的任务
使用异步的时候都会用到线程池:比如异步生产报告、异步保存最新上报数据等
ThreadLocal 是线程本地存储,在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。通过这种方式,避免资源在多线程间共享。
ThreadLocal的应用场景
ThreadLocal用在请求头里面存放租户code
ThreadLocal如果使用不当会造成脏数据、内存泄露等问题
面试官:ThreadLocal的应用场景和注意事项有哪些?
线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。
- 新生代占堆内存的三分之一,而老年代占三分之二
- 新生代主要用于存储新创建的对象及对象年龄小于15岁的对象,而老年代主要存储年龄大于15岁以上的对象
- 新生代主要发生的是YGC,而老年代是FGC
- 新生代的GC回收算法为复制算法,老年代一般为标记压缩和标记清除
排查生产环境下CPU飙高的原因
线上CPU飙升100%问题排查,一篇足矣
根据工作中的实际情况回答
1.Mybatis将sql放到了独立的xml文件中,实现了代码和sql的分离,降低了代码的耦合度
2.Mybatis上手更容易,代码更容易维护
3.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集
4.mybatis还给我们提供了很多第三方插件(代码生成器)
两者是不同的东西,OpenFeign底层是Feign,Feign的底层是Rribbon+RestTemplate,
RestTemplate是Spring提供的用于发送HTTP请求的客户端工具
Reentrant的意思为可重入,顾名思义ReentrantLock是一个可重入锁
- synchronized是关键字,Lock是接口
- synchronized是隐式的加锁,lock是显式的加锁;
- synchronized可以作用于方法上,lock只能作用于方法块
- synchronized底层采用的是objectMonitor,lock底层采用的AQS
- synchronized是阻塞式加锁,lock是非阻塞式加锁支持可中断式加锁,支持超时时间的加锁
- synchronized只支持非公平锁,lock支持非公平锁和公平锁
AtomicReference、AtomicLong等 底层通过Unsafe类来实现, 利用了CPU指令保证了操作的原子性
- CAS是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新的原子性
CAS
通过Unsafe类来实现,Unsafe是CAS的核心类,由于Java方法无法直接访问底层系统,而是通过本地(native)方法来访问,Unsafe相当于一个后门。基于该类可以知己操作特定内存的数据。Unsafe类存在于sun.misc(jre文件夹下rt.jar)包中,其内部方法操作可以像C的指针一样直接操作内存,因为java中的CAS操作的执行依赖于Unsafe类的方法
用过,用的是Rediison或者lua脚本
- Redisson可以用来提供布隆过滤器
- Redisson也可以实现消息队列
- Redisson还可以用于实现延迟队列
在HttpServlet中,通常从request对象中获取的Stream是不能重复读取的。这是因为Stream一旦被读取,就会被标记为已读,并且指针已经移动到了文件的结尾位置,所以无法再次读取。
如果你需要多次读取Stream中的内容,可以使用缓存技术,将Stream的内容先读入到缓存中,然后在对缓存进行操作,这样就可以实现多次读取Stream的目的。具体实现可以使用ByteArrayOutputStream将Stream写入到内存中的字节数组中,然后再使用ByteArrayInputStream将数据从字节数组读取出来进行操作。
Spring是一个开源的、轻量级Java框架,它提供了一系列的组件和工具,用于简化企业级应用程序的开发,这些组件包括IoC容器、AOP、ORM、事务管理等。
Spring MVC是Spring框架中的一个组件,用于基于MVC架构的Web应用程序的开发。它可以帮助开发人员将应用程序模块化,以便于开发、维护和扩展。
因此,Spring和Spring MVC的区别主要在于它们的应用场景和功能:
- Spring是一个通用的框架,可以用于开发各种类型的应用程序,例如Web应用程序、窗体应用程序、批处理应用程序等;而Spring MVC则专注于Web应用程序的开发,特别是基于MVC架构的Web应用程序。
- Spring提供了IoC容器、AOP、ORM等核心功能,它们可以被Spring MVC所使用;而Spring MVC则提供了专门针对Web应用程序的功能,例如DispatcherServlet、视图解析器、处理器映射器等,这些功能可以被Spring所使用。
- Spring和Spring MVC都提供了良好的可扩展性,可以通过插件或者自定义实现来扩展其功能。
总之,Spring是一个通用的Java框架,Spring MVC是基于Spring框架的一个Web应用程序开发框架,两者之间存在一定的关联和依赖关系。
在Spring MVC中,MVC代表的是Model-View-Controller,是一种软件设计模式。
Model-View-Controller(MVC)模式是一种分离应用程序三个主要方面的方法,即模型(Model)、视图(View)和控制器(Controller)。每个方面都处理应用程序的不同方面:
- 模型(Model)代表应用程序中使用的数据和业务规则。
- 视图(View)代表用户界面,包括图形、文本、音频等各种元素。
- 控制器(Controller)负责处理用户输入,并将其传递给模型或视图进行处理。
在Spring MVC中,控制器(Controller)通过DispatcherServlet来接收用户的请求,并将请求转发给相应的控制器进行处理。控制器从模型(Model)中获取数据,并将其传递给视图(View)进行渲染。视图会将模型中的数据渲染成HTML或其他格式,并返回给客户端进行展示。
MVC模式的设计思想使得应用程序呈现出高度的灵活性和可扩展性,有助于应对不断变化的需求。同时,将应用程序分离为不同的组成部分也使得开发人员可以分别关注应用程序的不同方面,提高了开发效率和代码重用性。
面向切面编程(Aspect-Oriented Programming,AOP)是一种软件设计模式,它可以在程序运行时动态地将代码片段(即“切面”)切入到现有代码中,以改变或增强原有的功能。
AOP通过将横向关注点(即与业务逻辑无关的问题,如日志、事务、安全等)从纵向业务逻辑中分离出来,使得代码更具有可维护性、可重用性和可扩展性。AOP通常被用于:
- 实现跨越多个对象和模块的日志记录和事务处理等公共功能;
- 分离系统的关注点,使之更易于维护和理解;
- 简化代码,减少重复代码的编写。
在AOP中,切面是一些与业务逻辑无关的代码片段,它们可以与一个或多个对象进行连接,并在该对象上执行一些操作。连接点是指程序中可以插入切面的特定位置,例如方法调用、异常处理、属性访问等。当连接点匹配到某个切面时,则会执行该切面中定义的代码。
Spring框架中提供了对AOP的支持,可以很方便地实现AOP功能。在Spring AOP中,切面通常是由Spring Bean提供,并且通过Advice和Pointcut定义。
总之,面向切面编程是一种增强程序模块化、降低耦合度的编程方式,可以使得代码更具有可维护性和可扩展性。
先遍历链表,然后将遍历得节点放入栈中,然后再一次从栈中取出来即可
IOC:控制反转
AOP:面向切面编程
过滤器 和 拦截器的 6个区别
1、实现原理不同(过滤器是基于函数回调,拦截器基于Java的反射机制(动态代理))
2、使用范围不同(过滤器Filter只能在WEB中使用,拦截器是一个Spring组件可以单独使用)
3、触发时机不同
- 过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后
- 拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。
4、拦截的请求范围不同
- 过滤器几乎可以对所有进入容器的请求起作用
- 拦截器只会对Controller中请求或访问static目录下的资源请求起作用
5、注入Bean情况不同
6、控制执行顺序不同
- 过滤器用@Order注解控制执行顺序,通过@Order控制过滤器的级别,值越小级别越高越先执行
- 拦截器默认的执行顺序,就是它的注册顺序,也可以通过Order手动设置控制,值越小越先执行。
- 过滤器用@Order注解控制执行顺序,通过@Order控制过滤器的级别,值越小级别越高越先执行
- 拦截器默认的执行顺序,就是它的注册顺序,也可以通过Order手动设置控制,值越小越先执行。
jdk中Executors工具类创建的3种(固定长度的线程池,单线程的线程池、可扩容的线程池)以及我们自定义的还有spring框架自带的线程池等
单例、多例、reqeust、session、 globalSession
??
为了提高性能少创建实例垃圾回收缓存快速获取,因为实例的创建和垃圾的回收都是要消耗性能的
@Resource:默认按名称注入,名称注入失败后选择按类型注入,时java自带的注解
@Autowired:按类型注入,是spring框架的注解
List 和 Set,一般为ArrayList 、LinkedList、 HastSet
HashMap底层是数组+链表+红黑树构成,往HashMap中添加元素时,首先对key进行hash运算计算出在数组中的下标,然后放到该位置的链表上,如果链表的长度达到一定的阈值时链表则会转换成红黑树
HashMap底层实现原理概述
不安全,线程安全的有HashTable、SynchronizedMap、ConcurrentHashMap等
懒汉式、饿汉式、枚举
常用的: 字符串、Hash、列表、无序Set、有序Set
不常用的:BitMap、HyperLogLog、GEO
集合框架、Spring、业务开发
非常的有意义,代码规范不仅可以提高我们的开发效率,还可以便于我们管理项目
参考博客、官网等等先了解该技术点,然后写demo进行验证,如果成功则在运用到项目当中
池化技术都有共同的好处,就是可以最大程度的利用资源,可以进行统一的链接管理,可以有效地控制项目中连接池的最大数等等
曾今用Nginx做过反向代理和负载均衡
注解是种更加优雅的开发方式,但是理解的难度可能稍微要大一些,使用注解可以大大的提高我们的开发效率
没用过,以前用过fastdfs,主要是用于进行项目中图片和各种文件的存储问题等
尾递归,顾名思义递归方法的调用放在了方法的尾巴上,调用递归方法是 本次方法已经结束了,栈中对应的栈帧已经消失了,可以有效地避免栈的溢出问题
没写过存储过程,存储过程是个过时的东西,不推荐使用了
字段的长度问题、创建的表的字段是否规范、风格是否和项目组统一、后续扩展问题、以及当前表的数据量级问题、后续的优化等
有过,因为业务数据量太大,因此进行分表操作
平时开发的时候会用docker部署需要使用的中间件
没用过
没用过
没用过
视情况而定、优化SQL、加索引、表分区等等
单例模式、工厂模式、策略模式、模板模式、代理模式
1.由于系统中内存只存在一个对象,因此可以节约系统的的资源,对于一些频繁的创建和销毁的对象单例模式无意可以提供系统的性能;
2.避免对资源的多重占用;
3.提供了对唯一实例的受控访问
详解Nacos和Eureka的区别
简单来说, Spring Boot 通过 @EnableAutoConfiguration 开启自动装配,通过 SpringFactoriesLoader 最终加载 META-INF/spring.factories 中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional 按需加载的配置类,想要其生效必须引入 spring-boot-starter-xxx 包实现起步依赖
高频面试题:谈谈你对 Spring Boot 自动装配机制的理解
SpringBoot事件监听的4种实现方式
- 手动向ApplicationContext中添加监听器
- 将监听器装载入spring容器
- 在application.properties中配置监听器
- 通过@EventListener注解实现事件监听
Seata的四种模式介绍
XA、AT、TCC、Seaga
HashTable、SynchronizedMap、ConcurrentHashMap
用过,比如用函数ST_Distance查询某个坐标查询指定范围内的设备
进行接口地址的统一,进行动态路由、鉴权、过滤、负载均衡等
Ribbon的负载均衡一般是指客户端的负载均衡
Nginx的负载均衡值得是服务器端的负载均衡
Java多线程:向线程传递参数的三种方法
- 创建线程时通过构造方法
- 通过set方法
- 通过回调函数
-通过InheritableThreadLocal (ITL)
ThreadLocal是用于线程之间进行参数隔离的,因此不可以在线程间传递参数,不过如果是子线程想获取父线程的参数可以使用ThreadLocal的子类InheritableThreadLocal
ITL是InheritableThreadLocal,是ThreadLocal的子类,可以用于父子线程之间参数传递,子线程中可以获取父线程的值
TTL是TransmittableThreadLocal,是ITL的子类,ITL虽然解决了父子线程间参数线程传递的问题,但是如果是结合线程池使用还是会存在问题,因此阿里出了一个TTL以解决该问题
提示:ITL是jdk的类,TTL是阿里自己实现的,使用TTL需要导入相关的jar包
彻底理解ThreadLocal、ITL、TTL
IO密集型:最大线程数=CPU核数 / (1 - 阻塞系数) [ 阻塞系数在0.8 ~ 0.9左右 ]
CPU密集型:最大线程数 = CPU核数 + 1
覆盖索引是select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖
通过 @ApiVersion()注解
如何用SpringMVC做api接口版本控制
实现CommandLineRunner接口或实现ApplicationRunner接口,并加入到容器中即可
如何在Springboot 项目启动后执行某些自定义代码逻辑
1、@Transactional 应用在非 public 修饰的方法上
2、@Transactional 注解属性 propagation 设置错误
3、@Transactional 注解属性 rollbackFor 设置错误
4、同一个类中方法调用,导致@Transactional失效
5、异常被你的 catch“吃了”导致@Transactional失效
6、数据库引擎不支持事务
@Transactional注解什么情况会失效?
元空间也会溢出,虽然发生的概率很小,但确实也会溢出的,因为元空间主要存储的是类的元数据(class相关信息,包括class对象的Method,Field等),因此如果元空间设置的较小且系统产生的类足够的多的情况下也还是会溢出的。
Vector、CopyOnWriteArrayList、SynchronizedList
用过,用它进行数据存储、使用Queue时用到了;
Queue q = new LinkedList<>();