Java面试题大全

文章讨论了Java编程中ArrayList和LinkedList的区别,包括它们的底层实现和性能特点。还涉及了JVM调优的步骤,如分析GC日志和dump文件,以及如何进行内存和线程优化。此外,文章提到了SpringMVC框架的工作原理,如DispatcherServlet的角色和自动装配。数据库方面,讲解了MySQL的InnoDB与Myisam引擎的差异,以及Redis的数据类型和持久化策略。
摘要由CSDN通过智能技术生成
ArrayList 和 LinkedList 的区别是什么?

最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 查找的时间复杂度是 O(1),而 LinkedList 是 O(n)

如何实现数组和 List 之间的转换?

List转换成为数组:调用ArrayList的toArray方法。

数组转换成为List:调用Arrays的asList方法。

ArrayList 和 Vector 的区别是什么?

ArrayList是非同步的,而Vector是同步的,因此ArrayList是线程不安全的,Veror是线程安全的,在不考虑线程安全性我们优先选用ArrayList

当ArrayList与Vector的存储数据大于初始化长度时,ArrayList的扩容大小时原长度的50%,而Vetcor的扩容率是100%。

finally块中需要注意的问题

1、如果在try块或者catch块中使用System.exit(1);此语句是用来退出虚拟机,则finally块将失去执行的机会,但是在实际开发中不会这么做。

2、如果在finally中存在return、throw等方法,将会导致try、catch块中的return、throw语句失效

​ 由于在try。。。catch。。。finally中运行retrun、throw的顺序:先检查finally中是否有该语句,当finally中出现return、throw语句时,则执行并终止了该方法,系统就不会再跳回去执行try、catch中的任何代码

J2SE与J2EE

J2SE:语言基础+jdk的API

J2EE:企业级应用;java规范(13个规范),例如:jdbc、jms规范、servlet规范web服务器,比如tomcat、jetty、undertow

​ 在启动tomcat的时候,为什么spring的IOC容器回会自动启动?这就是依赖于servlet的规范,tomcat启动后,通过监听(tomcat.addwebapp())的方法来启动springIOC

jdk提供接口,由厂家提供实现,为了统一接口

抽象类与接口

相同点:

1、接口和抽象类都不能实例化

2、接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

不同点:

1、接口中不能含有普通方法,而抽象类中可以包含普通方法

2、接口中只能定义静态常量,不能定义成员变量。抽象类中都可以

3、接口中不能包含构造器,抽象类中可以包含构造器

4、接口中不能包含初始化块,抽象类中可以包含初始化块

5、只能继承一个抽象类,而可以实现多个接口

==与equals的区别

1、==是基本运算符,适用于所有的类型的变量与变量的对比

​ equals()是Object类定义的方法,由于Object是java的基类,所以任何对象都可以调用equals()方法实现对比, 但是基本类型不是对象,无法调用该方法实现对比

2、==对比的是变量的值

​ 如果是基本数据类型,比较的是字面量,如果是引用数据类型,比较的是引用地址

​ 默认情况下,它与==的结果是相同的,方法可以被重写,在java中,许多类都被重写了equals()方法,例如:

​ String、包装类等

​ 尽管是不同的对象,但equals()的结果可能也是true

特殊情况:

1、直接声明的字符串使用==也是成立的。

例如:

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TuMObTdd-1677664772898)(file:///C:\Users\lenovo\AppData\Local\Temp\ksohtml21096\wps1.jpg)]

2、使用[-128,127]的区间值对整型包装类(Byte、Short、Integer、Long)对象使用==也是成立的

hashCode

hashCode是Object定义的方法,它将返回一个整型值

注意1:hashCode不是对象的内存地址

论证:

(1)JVM(java虚拟机)在进行垃圾管理时,会移动对象的位置,即:经过某次垃圾回收之后,对象内存中的位置可能就已经发生了变化,但hashCode值并不会变化。

(2)Integer类型的值区间是-231—231-1,java管理的内存已经超过了4GB,所以,hashCode不可能是内存地址。

注意2:hashCode不需要自己手动使用

原因:hashCode的设计是提供给JVM管理对象时使用的,并不是让开发者自行去使用的

hashCode的作用:

1、Hash容器可以通过HashCode定位所需要使用的对象。典型的Hash容器:HashSet、HashMap

2、Hash容器通过hashCode来排除两个不相同的对象

​ hashCode值相同+调用equals()方法返回为true时,视为两个对象相同

JVM调优步骤

1、分析GC日志及dump文件,判断是否需要调优,确定颈瓶问题点

2、确定JVM调优量化目标

3、确定JVM调优参数

4、调优一台服务器,对比观察调优前后的差异

5、不断分析和调整,找到最适合的参数配置‘

6、将最适合的参数应用到所有的服务器,并进行后续跟踪

SQL语句的优化

(1)正确创建索引

(2)对SQL语句进行优化,例如:能用between就不用in, select语句查询字段禁止采用*来查询、只查询一条数据用limit 1、对于组合索引来说,满足最左前缀

​ 在where子句中使用or来连接的条件,如果有一边没有索引,会导致引擎放弃使用索引而进行全表查询、正确使用explain关键字、尽可能使用varchar替代char、当索引的列大量重复数据时,就可以把索引删除

索引优化

对作为查询条件和order by的字段建立索引

避免建立过多的索引,多使用组合索引

索引什么时候会失效

1、对列进行计算或者使用函数

2、使用反向操作或link操作

3、在where语句中,如果有一个列用到索引,另一个列没用索引

索引的类型

1、普通索引(没有任何限制,用于加速查询)

2、唯一索引(索引列的值必须唯一,允许有空值)

3、全文索引(主要用来查询文本中的文字,而不是直接与索引的值相比较)

4、主键索引(一个表只有一个主键,不允许有空值,一般在创建表的时候同时创建主键索引)

5、组合索引(遵循最左前缀)

Nacos心跳机制

Nacos内部注册的服务分为两大类:

(1)临时实例

启动项目后,每个模块会每隔5秒向Nacos发送心跳包,如果当前服务不在注册列表中,就会进行注册,如果该服务在注册列表中,则表明该服务为健康的,当Nacos在15秒内没接收到该服务的心跳包,标记该服务为不健康网站,当30秒内还未接收到该服务的心跳包,则Nacos会将该服务在注册列表中删除。

(2)持久化实例

与临时实例相似,只是在30秒内未接收到该服务的心跳包,不会将该服务在注册列表中剔除。

HashMap与HashTable的区别

(1)HashMap允许Key与Value为Null,HashTable不允许

(2)HashTable的方法是同步的,而HashMap不是,因此,HashTable为线程安全的,而HashMap为线程不安全的。 HashTable适用于多线程环境,HashMap用于单线程环境。

(3)在Java1.4中引入了LinkedHashMap, HashMap的一个子类,假如你想要遍历顺序,你很容易从HashMap转向LinkedHashMap,但是HashTable不是这样的,它的顺序是不可预知的。

HashMap与HashSet的区别

1、HashMap实现的是Map的接口,而HashSet是实现Set的接口

2、HashMap是通过键值对存储,而HashSet是存储对象

3、HashMap允许有重复的值,而HashSet不允许有重复的值

4、HashMap允许有多个值为空,而HashSet只允许有一个空值

5、HashMap使用put()将元素加入map中,而HashSet使用add()将元素放入set中

HashMap的遍历

1、迭代器遍历(EntrySet与KeySet遍历)

2、Foreach遍历(EntrySet与KeySet遍历)

3、Lambda表达式

4、Streams API遍历(单线程和多线程遍历)

HashMap的实现原理

HashMap是基于Hash表接口的非同步实现,此实现提供所有可选的映射操作,并且可将key于value为null。此类不保证该顺序恒久不变。

HashMap的数据结构:HashMap是一个“链表散列”,即数组和链表的结合体,当在碰撞过程中碰撞次数超过8次(默认)时,使得红黑树来替代链表,红黑树的查找时间复杂度为O(logn)优于链表查询的时间复杂度O(n)

HashSet的原理

HashSet底层是由HashMap实现的,HashSet的值是存放在HashMap的key上,HashMap的value统一为present;

List数组进行一个随机打乱的排序

方法一:直接掉用Collections.shuffle(list)方法

方法二:算法:顺序遍历,每次生成一个随机位置,和当前位置的元素互换。

MVC的设计模式

MVC设计模式一般指MVC框架,其中:M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。使用MVC的目的是将M与V的实现代码分离,使得同一个程序有不同的表现形式。

数据模型层:拥有最多的处理任务,是应用程序的主体部分,负责数据逻辑的处理和实现数据操作

控制层:负责接收并转发请求,指定视图并将响应结果发送给客户端

视图层:负责格式化数据并把他们呈现给用户。

MVC的优缺点

优点:

1、多视图共享一个模型,大大提高了代码的可重用性

2、MVC三个模块相互独立,松耦合架构

3、控制器提高了应用程序的灵活性和可配置性

4、有利于软件工程化管理

总结:松耦合+高可重用性+高可试用器

缺点:

1、原理复杂

2、增加了系统结构的实现的复杂性

3、视图对模型数据的低效率访问

SpringMVC+Tomcat一套的DispatcherServlet底层工作原理

一个Tomcat底层有多个DispatcherServlet,每个DispatcherServlet都内置了一个spring容器

在启动tomcat的时候,它会解析web.xml文件,这个文件里面配置了一些Servlet,解析web.xml文件就会创建applicationContext,在此期间就会创建XmlwebApplicationContext容器(即Spring容器)

Tomcat启动-------------->servlet初始化------------->applicationContext--------------->XMLwebApplication(Spring容器)

SpringMVC+Tomcat的底层原理

一个Tomcat底层有多个DispatcherServlet,每个DispatcherServlet都内置了一个spring容器,在里面创建一个父容器,原本在xml中要扫描多个spring容器中的controller,但是创建了父容器之后,只要在xml中扫描父容器中的service即可,就可以多个controller共用一个service中扫描进来的Bean。

在SpringMVC的官方文档中,也可以使用零配置来替换XML文件(创建MyWebApplicationInitializer实现WebAplicationInitializer中的onStartup方法,其中该方法通过反射Appconfig类,该类就是创建一个父容器)

流程:Tomcat在启动的时候会找到SpringMVCjar包里面的文件,然后找到该文件中的类,然后调用该类中的onStartup方法,在调用该方法之前会找到该接口中的实现类,找到之后会传入onStartup方法中的参数,再在该类后面调用我们自己写的类中实现的WebAplicationInitializer中的onStartup方法。

SpringBoot+Tomcat的底层原理

谈谈SpringBoot的理解

1、可以快速搭建项目

2、可以对主流开发框架的无配置集成

3、项目可以独立运行,不需要依赖Servlet容器

4、可以极大体改开发、部署效率

5、可以与云计算天然集成

SpringBoot的自动装配流程

@EnableAutoConfiguration注解、@Configuration注解和@ConditionalOnClass注解(条件注解)组成了SpringBoot自动配置的核心,首先它得是一个配置文件,其次根据类路径下是否有这个类自动配置,具体是通过maven读取每个starter中的Spring.factories文件,该文件配置了所有需要被创建在spring容器中的bean。

SpringBoot的注解

1、@SpringBootApplication

在SpringBoot入口类中,唯一的一个注解就是SpringBootApplication,它是SpringBoot项目的核心注解,用于开启自动配置,准确说是通过该注解内组合的@EnableAutoConfiguration里开启了自动配置。

2、@EnableAutoConfiguration注解

允许SpringBoot自动配置注解,开启这个注解后,SpringBoot就能根据当前类路径下的包或者类来配置Spring Bean

3、@Conditional注解

@Conditional注解是由Spring4.0版本引入的新特性,可以根据是否满足指定条件来决定是否进行Bean的实例化及装配


@Autowired与@Resource的异同点

相同点:

在使用Spring框架及基于它的进阶框架(例如:Spring MVC、Spring Securiy、SpringBoot等)时,都可以实现自动装配:

public class UserController{

@Autowired

private IUserService userService;

}

public class UserController{

@Resource

private IUserService userService;

}

都可以用于属性或Setter方法,实现装配;

不同点

1)@Autowired是Spring框架中的注解

仅当使用Spring框架时才可以使用;

—主流的开发模式下,都会使用Spring框架,该约束影响不大

@Resource是Javax包下的注解

JSR-250标准

—在EJB33.0和Spring中均可使用

2)@Autowired可以添加在构造方法声明之前

@Resource不可以添加在构造方法声明之前

@Resource还可以添加在类的声明之前,但不会装配属性的值

在Spring容器中存在多个相同类型的对象,在自动注入时,需要根据名称匹配,使用@Autowired必须结合@Qualifier注解以指定Bean id/name,用于属性时,在属性的声明之前同时添加这两个注解,用于方法时,在方法声明之前添加@Autowired,在方法的参数之前添加@Qualifier注解,而使用@Resource时则是配置该注解的name属性。

3)@Autowired先尝试根据类型进行装配,再尝试根据名称进行装配

过程:

先查找匹配类型的数量

—1个:直接装配

—0个:判断@Autowired的required属性

—true:抛出异常

—false:不装配,即属性值为null;

—超过1个:尝试根据名称装配:

—存在符合的对象:装配

—不存在符合的对象:抛出异常

@Resource是先尝试根据名称装配,再尝试根据类型装配

—能装配则装配,最后装配不了则抛出异常;

依赖注入的几种方法

1)属性注入

在属性的声明之前添加@Autowired注解

该类必须是Spring管理对象的

优点:简单便捷

缺点:不安全;

在属性上添加@Autowired是不安全的,在执行单元测试 (不依赖任何非测试环境,包括spring环境,如果加载了非测试环境,则称为:集成测试)时,由于不加载Spring环境,属性将不会注入值,相关代码会出现空指针异常。

2)Setter注入

在需要被Spring调用的Setter方法声明之前添加@Autowired注解

该类必须是Spring管理对象的

优点:直观,相比属性注入,安全性略有提升;

即使属性是private的,在没有加载Spring环境时,也可以手动调用Setter方法,以避免出现空指针异常。

缺点:相对麻烦,且未彻底解决安全问题;

增减属性都要相应的调整;

如果使用lombok,源代码中根本没有Setter方法,无法添加注解;

在没有加载Spring环境时,如果未手动调用Setter方法,仍会导致空指针异常

3)构造方法注入

在需要被Spring调用的构造方法的声明之前添加@Autotiwed注解。

该类必须是Spring管理的类;

仅当该类中有多个构造方法时才需要添加该注解,只有一个构造方法时会自动调用。

优点:能保障安全性;

如果构造方法唯一的,任意环境下都必须调用的,不会出现空指针异常。

缺点:不直观,相对麻烦;

1)构造方法的参数列表可能很长;

2)必须结合构造方法,才能明确哪些属性将被注入值;

3)必须保证构造方法唯一;

4)增减属性都要做相应的调整;

各个框架的核心注解
SpringMVC框架:

@Controller、@RequestMapping、@RequestBody、@RestController=@ResponseBody+@Controller、@Autowired、@Resource

@PathVariable、@RequestParam

Spring框架:

@Component泛指各种注解包括:@Controller控制层、@Service业务层、@Repository数据访问层

@ComponentScan、@Configuration

切面相关注解:@Aspect声明切面、@After在方法之后执行、@Before在方法之前执行、@PointCut声明切点

Mybatis的优缺点

优点:

1、内嵌了JDBC,减少了代码量(只要是用Java语言实现数据库编程,其底层一定是用JDBC实现的)

2、Mybatis是最简单的持久化框架,一个半ORM(对象映射框架),自动封装查询结果,当字段名与封装结果中的属性不完全一致时,可以自动配置节点,进行字段名与属性名的映射

3、解耦SQL语句,可以使用专门的xml文件进行管理SQL语句,实现了数据库语句与java代码分离

4、与Spring系列框架高度集成,只需要极其简单的配置

5、SQL代码可以进行复用利用sql节点

缺点:

1、需要编写大量的SQL语句

2、数据库移植性较差

Mybatis中的#{}与${}的异同点

相同点:

都是写在SQL语句中的,用来表示参数的

不同点:

#{} 只能表示某个值,不能表示SQL语句的某个片段 是预编译的,在预编译后#{}会替换为? 不需要考虑参数类型(例如:不需要在String类型的两边加上单引号) 不会存在SQL的注入风险

${} 可以表示SQL中语句的任意片段,只需要保证最后拼接出来的SQL语句合法就行 ,需要考虑参数的返回值类型(例如:要在String类型的两边加上单引号),

需要考虑SQL注入的风险

Mybatis的一级缓存与二级缓存

一级缓存是基于SqlSession默认开启的,在操作数据时要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据,不同的SqlSession之间的缓存数据区域是互不影响的。一级缓存的作用域是同一个SqlSession,在同一个SqlSession中执行两次执行相同的sql语句,第一次执行完毕就会将数据库中查询的数据写到缓存,第二次直接从缓存中获取数据,提高了查询效率。

二级缓存是mapper级别的缓存,是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的SqlSession两次执行相同的namespace下的执行相同语句时,第一次执行完毕就会将数据库中查询的数据写到缓存,第二次直接从缓存中获取数据,提高了查询效率。

缓存穿透

正常业务下,从数据库查询出的数据可以保存在Redis中

下次查询时直接从Redis中获得,大幅提高响应速度,提高系统性能

所谓缓存穿透,就是查询了一个数据库中都不存在的数据

我们Redis中没有这个数据,它到数据库查,也没有

如果这样的请求多了,那么数据库压力就会很大

前面阶段我们使用向Redis中保存null值,来防止一个查询反复穿透

但是这样的策略有问题

如果用户不断更换查询关键字,反复穿透,也是对数据库性能极大的威胁

使用布隆过滤器来解决这个问题

事先创建好布隆过滤器,它可以在进入业务逻辑层时判断用户查询的信息数据库中是否存在,如果不存在于数据库中,直接终止查询返回

缓存击穿

正常运行的情况,我们设计的应该在Redis中保存的数据,如果有请求访问到Redis而Redis没有这个数据

导致请求从数据库中查询这种现象就是缓存击穿

但是这个情况也不是异常情况,因为我们大多数数据都需要设置过期时间,而过期时间到时这些数据一定会从数据库中同步

击穿只是这个现象的名称,并不是不允许的

缓存雪崩

大量的缓存击穿导致了缓存雪崩

同一时间发生少量击穿是正常的

InnoDB与Myisam的区别

1、InnoDB支持事务、而Myisam不支持事务

2、InnoDB支持外键、而Myisam不支持外键

3、InnoDB和Myisam的索引都是基于B+树的单具体实现不一样,InnoDB的B+树的叶子结点存储数据的,而Myisam的B+树的叶子结点存储指针的

MySQL默认使用InnoDB,如果要用事务和外键就使用InnoDB,如果这张表只用来查询,就可以用Mysiam,如果更新和删除增加频繁就使用InnoDB。

4、innodb默认表锁,使用索引检索条件时是行锁,而myisam是表锁(每次更新增加删除都会锁住表)

控制反转原理(IOC

控制反转,它是吧传统上有程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的控制反转就是对组件对象控制权进行转移,从程序代码转移到外部容器

SpringIOC负责创建对象、管理对象、装配对象、配置对象、管理对象的整个生命周期

Spring Bean的作用域

1、singleton(单例作用域)

Spring IOC容器只会创建一个共享的bean实例,对于所有的bean请求,只要id与该bean定义相匹配,nameSpring在每次需要时都会返回同一个bean实例

2、prototype(原型作用域)

它在我们创建容器时并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象

3、request(请求作用域)

每增加一个HTTP请求时,Spring就会创建一个新的bean,在请求处理完成之后便及时销毁这个bean

4、session(会话作用域)

Session中所有http请求共享同一个请求的bean实例。Session结束后就销毁bean

5、global-session(全局作用域)

面向切面编程(AOP)

面向切面编程是通过预编译和运行期的·实现程序功能的维护和统一的一种技术

AOP是OOP的一个延续,是Spring框架的一个重要内容,是函数编程的一种衍生范型,利用AOP可以对业务逻辑的各个部分进行隔离,使得业务逻辑的各耦合度降低,提高程序的可重用性,便于维护。

动态代理

当想要给某个接口的类中的方法,加一些额外的处理,比如说事务、日志等。可以给这个类创建一个代理,顾名思义就是的创建一个新的类,这个类不仅包含原来的方法的功能,而且在原来的基础上添加了额外处理的新的类。动态代理的应用场景有很多,比如说:AOP的实现、Java注解对象获取、日志框架、事务处理等。在动态代理中其中很重要的是JDK动态代理,在JDK动态代理中,实现了InvocationHandler的类可以看做代理类(因为类也是一种对象),JDK动态代理就是围绕实现InvocationHandler的代理类进行的。在代理类中一个最重要的方法时Invoke,它有三个参数:动态代理对象、最终执行的方法、向目标方法传递的参数。

AOP的底层实现

实际上,AOP的底层是通过Spring提供的动态代理技术实现的,在运行期间,Spring通过动态代理技术动态的生成动态代理对象,代理对象方法执行时进行增强功能的介入,再去调用目标对象的方法。

常用的动态代理技术: JDK代理、Cglib代理

反射机制

反射机制是一个非常重要的特性,它允许程序在运行时进行自我检查,同时也允许对内部成员进行操作。由于反射机制能够实现在运行时对类进行装载,因此能够增强程序的灵活性。不恰当的使用反射机制,严重影响系统的性能。

反射机制的主要功能:

1、得到一个对象所属的类

2、获取一个类的所有成员变量和方法

3、在运行时创建和调用对象的方法

Redis目前支持的5种数据类型

1、String(字符串)

2、List(列表)

3、Hash(字典)

4、Set(集合)

5、Zset(有序集合)

Redis的持久化

RDB 快照/内存快照 RDB持久化是把当前进程数据生成快照保存在磁盘上的过程,由于是某一时刻的快照,那么快照中的值要早于或等于内存中的值

​ 触发方式有两种:手动触发(save与bgsave)与自动触发

优点:

​ RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景;

​ Redis加载RDB文件恢复数据要远远快于AOF方式;

缺点:

​ RDB发昂视实时性不够,无法做到秒级持久化

​ 每次调用bgsave都要fork子线程,fork子线程属于重量级操作,频繁执行成本较高

​ RDB文件是二进制,没有可读性

AOF 写后日志(先写内存,后写日志)

​ 原因:Redis要求高性能,采用写后日志有两大好处

​ 1、避免额外的检查开销

​ 2、不会阻塞当前的写操作

过滤器和拦截器的区别

1、实现原理不同:

过滤器是通过函数的回调,拦截器则是基于Java的反射机制(动态代理)实现的。

2、使用范围不同:

过滤器要依赖于Servlet容器,导致它只能在web程序中使用。拦截器是一个Spring组件,由Spring容器管理,因此它可以单独使用,不仅仅能应用到web中

3、触发时间不同:

过滤器是进入servlet之前到servlet处理完成后,拦截器是servlet完成后到controller之前进行预编译

4、拦截的请求范围不同

过滤器执行了两次,拦截器只执行一次。因为过滤器几乎对所有进入容器起作用,而拦截器只会对Controller中请求或访问静态资源起作用

Mybatisplus在Mybatis上新增了两个功能

1、提供了代码生成器

可以根据指定的数据库表自动生成基本的实体类、控制层、业务层、持久层等相关文件

2、自动提供基本增删改查方法的默认实现

单点登录

SpringSecurity+Oauth2+JWT实现单点登录(SSO)

SpringMVC与SpringBoot的区别

1、SpringMVC是Spring的一个模式,是一个Web框架,提供了一个轻度耦合的方式来开发Web应用

2、SpringBoot是约定大于配置,降低了项目搭建的难度

3、SpringMVC需要使用到Tomcat服务器,而SpringBoot内嵌了Tomcat服务器

SpringMVC的执行流程

  1. 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
  2. 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
  3. DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
  4. HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
  5. Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
  6. HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
  7. DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
  8. ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
  9. DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
  10. 视图负责将结果显示到浏览器(客户端)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aZkU9nDz-1677664772899)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220701194209323.png)]

三次握手四次挥手原则

三次握手原则:所谓的三次握手即建立在TCP的基础上,这个连接必须是一方主动打开,另一方被动打开。以下是客户端主动发起连接的图解:

img

其中里面主要的字段:

1、序号(Seq):占32位,用来表示TCP源端向目的端发送字节流,发起方发送数据时对此进行标记。

2、确认号(Ack):占32位,只有ACK’标志位为1时,确认序号字段才有效,ack=Seq+1。

3、标志位(Flags):共有6个:即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:

URG:紧急指针(urgent pointer)有效。

ACK:确认序号有效。

PSH:接收方应该尽快将这个报文交给应用层。

RST:重置连接。

SYN:发起一个新连接。

FIN:释放一个连接。

三次握手的好处:

为了防止服务端开启一些无用的连接增加服务器开销以及防止已失效的连接请求报文段突然又传送到了服务端而产生的错误

四次挥手原则:

前"两次挥手"既让服务器端知道了客户端想要释放连接,也让客户端知道了服务器端了解了自己想要释放连接的请求。于是,可以确认关闭客户端到服务器端方向上的连接了

后“两次挥手”既让客户端知道了服务器端准备好释放连接了,也让服务器端知道了客户端了解了自己准备好释放连接了。于是,可以确认关闭服务器端到客户端方向上的连接了,由此完成“四次挥手”。

img

悲观锁和乐观锁

乐观锁:总是假设最好的情况,每次去拿数据的时候都认为别人不会去修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,乐观锁适用于多读的应用类型,这样可提高吞吐量

悲观锁:总是假设最坏的情况,每次都拿数据的时候都认为别人已修改,所以每次在拿数据的时候会上锁,所以别人想拿到这个数据就会阻塞,直到它拿到锁(共享资源每次只给一个线程使用,直到线程使用完再给其他线程使用),传统的关系型数据库就用到了这里面锁的很多机制,就是在操作之前上锁。

共享锁和独享锁

独享锁:一次只能被一个线程访问(公平锁和非公平锁是独享锁)

共享锁:资源可以被多个线程所持有,读锁是可以共享的,而写锁每次只能被独占,读锁共享可以保证并发读是非常高效的、

关于Iterator

1、Iterator功能比较简单,并且只能单向移动

2、使用Iterator()方法要求容器返回一个Iterator。第一次调用Iterator的next()的方法时,它将返回序列的第一个元素

3、hasNext()是检查序列是否还有下一个元素

4、next()获取序列的下一个元素

5、remove()是将迭代器新返回的元素删除

Session与Cookie

Cookie是会话技术,将用户的信息保存到浏览器的对象

区别:

1、cookie数据是存放在客户的浏览器上,session数据是存放在服务器端上

2、cookie不是很安全的,别人可以截取存放在本地的Cookie进行Cookie欺骗,如

​ 果保证安全应当存放在Session中

3、Session会在一定的时间内保存在服务器上,当访问增多,会占用服务器的性

​ 能,如果要减轻服务器的压力,应当使用Cookie

4、单个Cookie在客户端的限制为3k。就是说一个站点在客户端存放的内存不能超

​ 过3k

Eureka的运行机制

1、客户端启动时,会反复连接注册中心尝试注册,直到注册成功为止。

2、客户端每30秒发送一个心跳包,服务器连续,3次接收不到一个服务的心跳,会在注册列表中删除注册信息

3、客户端每30秒拉取一次注册表,刷新本地注册表缓存

4、自我保护,由于网络中断,15分钟之内,85%的服务器发生心跳异常,自动进入保护模式,自我保护下的所有注册信息都不能删除,网络恢复后,自动退出保护模式。

负载均衡

什么是负载均衡:尽可能访问较闲的服务器提供服务

在实际开发过程中,一个服务基本都是集群模式的,也就是多个功能相同的项目在运行,这样才能承受更高的并发,这一个请求到这个服务,就需要确定哪一个服务器,Bubbo框架支持负载均衡算法,能够尽可能的请求在相对空闲服务器上运行。

Dubbo内置负载均衡算法:

1、随机分配策略(生成随机数,在哪个范围就让哪个服务器运行)

2、权重平均分配(权重一致就依次运行、权重不一致就平均分配)

在Dubbo2.7后,更新了这个算法,叫平滑加权算法

3、活跃度自动感知分配(记录每个服务器处理一次请求时间按照时间比例来分配任务数)

4、一致性哈希算法(根据请求的参数进行Hash算法)

SpringCloud的五大核心组件

1、服务发现(Eureka)

负责将这个服务的信息注册到Eureka服务端中

2、客户端的负载均衡(Ribbon)

主要提供客户端的负载均衡算法

3、断路器(Hystrix)

可以防止一个应用程序多次试图执行一个操作。允许它继续而不等待故障恢复而或者浪费CPU的周期

4、服务网关(zuul)

5、分布式配置(Spring Clound Config)

这个还是静态的,得配合Spring Cloud Bus实现动态的配置更新

Java实现分页查询

事务的四大特性

1、原子性

2、一致性

3、隔离性

4、永久性

Linux常见命令

1)cd命令 用于切换当前目录路径

2)ls命令 查看文件和目录

3)find命令 查找功能非常强大

4)cp命令 复制文件,可以将多个文件一次复制到一个目录下

5)mv命令 用于移动文件、目录或更改名字

6)rm命令 删除文件或目录

Kafka面试题

什么是Apache Kafka

Apache是由Apache开发的一种发布订阅消息系统,它是一个分布式的、分区的和可复制的提交日志服务

Kafka的应用场景

异步处理、应用解耦、流量削峰、日志处理、消息通讯

使用Kafka的优缺点

优点:

1、支持跨数据中心的消息复制

2、吞吐量高

3、时效性好:ms级

4、可用性高

5、消息可靠性

缺点:

1、由于是批量发送,数据并非真实的实时,仅支持统一分区内部消息有序,无法保证全局消息有序

2、有可能消息重复消费

3、依赖Zookeeper进行元数据管理

Kafka性能好体现在哪

Kafka对硬盘的读取规则进行优化后,效率能够接近内存

1、顺序读写 2、零拷贝 3、分区 4、批量发送 5、数据压缩

消息队列异常处理
使用JmsTemplate接收消息

消息信息通常分为两种:拉取模式pull(默认)和推送模式push

拉取模式是指请求消息一直等待直到消息到达位置

推送模式指消息可用的时候自动在代码中执行

RabbitMQ与Kafka的对比
  1. 应用场景方面

    RabbitMQ:用于实时的,对可靠性要求较高的消息传递上。

    Kafka:用于处于活跃的流式数据,大数据量的数据处理上。

  2. 架构模型方面

    RabbitMQ:以broker为中心,有消息的确认机制。

    Kafka:以consumer为中心,没有消息的确认机制。

  3. 吞吐量方面

    RabbitMQ:支持消息的可靠的传递,支持事务,不支持批量操作,基于存储的可靠性的要求存储可以采用内存或硬盘,吞吐量小。

    Kafka:内部采用消息的批量处理,数据的存储和获取是本地磁盘顺序批量操作,消息处理的效率高,吞吐量高。

  4. 集群负载均衡方面

    RabbitMQ:本身不支持负载均衡,需要loadbalancer的支持。

    Kafka:采用zookeeper对集群中的broker,consumer进行管理,可以注册topic到zookeeper上,通过zookeeper的协调机制,producer保存对应的topic的broker信息,可以随机或者轮询发送到broker上,producer可以基于语义指定分片,消息发送到broker的某个分片上。

activeMQ知识点

ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

JMS:异步通信:一个应用程序向另一个应用程序间接发送信息的一种方式

1、JMS包括以下基本构件

连接工厂,
是客户用来创建连接的对象,ActiveMQ提供的是ActiveMQConnectionFactory;
连接connection;
会话session,是发送和接收消息的上下文,用于创建消息生产者,消息消费者,相比rocketMQ会话session是提供事务性的;
目的地destination,指定生产消息的目的地和消费消息的来源对象;
生产者,由会话创建的对象。
消费者,由会话创建的对象

2、消息通信机制
点对点模式,每个消息只有1个消费者,它的目的地称为queue队列;
发布/订阅模式,每个消息可以有多个消费者,而且订阅一个主题的消费者,只能消费自它订阅之后发布的消息。
消息确认机制
Session.AUTO_ACKNOWLEDGE,直接使用receive方法。Session.CLIENT_ACKNOWLEDGE,通过消息的acknowledge 方法确认消息。Session.DUPS_ACKNOWLEDGE,该选择只是会话迟钝第确认消息的提交。如果JMS provider 失败,那么可能会导致一些重复的消息。如果是重复的消息,那么JMS provider 必须把消息头的JMSRedelivered 字段设置为true。

双亲委派

从顶级到底级有三个类加载器

BootStrapClassLoader(rt.jar)

ExtClassLoader(lib)

AppClassLoader(classpath)

应用在加载一个类的时候会委托给上层类加载,如果上层的类类加载器发现该类不在自己的加载路径里面,才会由应用加载器加载,所有的类必须传递到顶层类加载器

优点:可以保证类的安全

java.jdbc.Driver Class.forName(“com.mysql.jdbc.Driver”) META-INF/services

DriverManager.getConnection(“jdbc:ip:port”)

当前被加载的类的依赖类,也由当前类加载器加载 上下文类加载器(所有类加载器的共享区域)

三级分类树

本项目使用固定的三级分类树

是自关联分类(所有分类信息在一张表中)

思路

1.一次性查询出所有分类对象(List集合)

2.遍历集合将当前分类对象以父分类id为Key,以当前对象作为value,保存在一个Map中,这个Map对象

的Key(父级分类ID)对应的value,会包含它的所有子分类对象

3.遍历所有分类对象,以当前分类对象id为key,从Map中获取它的子分类,关联到三级分类树对象中

最后返回包含三级分类树结构的集合

如何实现spu列表

显示它们的注意事项就是分页(JsonPage)

分类id查询数据库,分页是PageHelper

搜索查询是ES,分页SpringData

如何显示一个商品的详情

商品详情页面有4个查询

1.SpuId查询spu表中信息显示的内容有默认价格title\name\默认图片等

2.SpuId查询spu_detail表中信息,内容是商品详情大图片

3.根据SpuId查询商品的所有属性

是先用spuid关联到分类id,再由分类id关联到属性id,在获得属性id包含的所有属性,是一个关联查询

如果是一个智能手机分类下的spu,能够查询到例如内存\处理器\颜色等规格属性

4.根据spuId查询Sku列表

只有查询到Sku列表,才知道具体的真实价格\图片\库存的情况

才选择对应规格属性时,才能知道有货无货

如何实现购物车的管理

用户在商品详情页选择属性之后,能够确定sku

将用户选中的sku保存在购物车中,

需要用户登录,因为所有购物车操作都需要用户身份

在控制器方法前添加@PreAuthorize(“hasRole(‘ROLE_user’)”) SpringSecurity单点登录

我们新增到购物车中的商品要检查是否已经在购物车中,如果不在新增到购物车,如果在的话,修改数量即可

删除或清空购物车功能就是按照购物车id进行操作即可

修改购物车中商品数量时,可以判断一下库存是否允许,如果没有库存就修改失败

排序算法 查找算法

直接插入排序 O(n^2) 顺序查找 O(n)

希尔排序 O(n^1.3) 二分查找(折半查找) O(logn)

直接选择排序 O(n^2) 斐波那契查找 O(logn)

堆排序 O(nlogn)

冒泡排序 O(n^2)

快速排序 O(nlogn)

归并排序 O(nlogn)

JSP与servlet的区别

数据库内连接查询:(内连接是指关联条件成立的会被检索出来,不成立的会过滤掉)

​ select student.student_no,student.student_name,classes.class_name

​ from student (inner) join classes

​ on student.class_no=classes.class_no

select 表名.字段名 from 表名1 join 表名2 on 关联条件

select s.student_no,s.student_name,c.class_name

​ from student s join classes c (命名别名)

​ on s.class_no=c.class_no

注意:(1)表在命名别名之后,就不再识别原表名,只能使用别名

​ (2)字段只在一张表中出现,则可以省略字段名前面的表名或者别名(不建议)

在where子句中使用内连接的语法:

select 表名.字段名 from 表1, 表2 where 关联条件

select s.student_no,s.student_name,c.class_name from student s,classes c where s.class_no=c.class_no

多表内连接:select 表名.字段名 from 表1

​ join 表2 on 关联条件1

​ join 表3 on 关联条件2

​ join 表4 on 关联条件3

数据库的外连接查询:外连接是内连接结果集+关联条件匹配不上的信息

左外连接 : select 字段列表 from 表名1 left join 表名2 on 关联条件

右外连接 : select 字段列表 from 表名1 right join 表名2 on 关联条件

条件判断:

1、比较运算符(>、<、<>(!=)、>=、<=)

select * from student where score>=60; 查找分数大于60分

2、between…and

select * from choose where score between 60 and 90; 查找分数在60-90之间

3、is null(判断为空)

列出没有班级的学生的信息(子表查询,不需要关联表)

select student_no,student_name from student where class_no is null;

列出没有学生的班级的信息(主表中匹配不上的数据,使用外连接进行连接)

select c.class_no 班号,c.class_name 班级名称,c.department_name 院系名称 from classes c join student

s on c.class_no=s.class_no where s.student_no is null;

4、in(值1,值2,…)

注意:在使用not in时,括号里面的条件不能包含null

列出选修了‘c语言’和‘java语言’的信息,包括学号、课程名称和成绩

select ch.student_no 学号,c.course_name 课程名称,ch.score 成绩 from course c left

join choose ch on c.course_no=ch.course_no where c.course_name in (‘c语言’,‘java语言’)

5、like(模糊查询)

% 任意长度的任意字符 _一个长度的任意字符

列出学生表中姓张的学生的信息

select student_no,student_name,student_contact,class_no from student where student_name like ‘张%’

6、and

select s.student_no,s.student_name,ch.score from student s,choose ch where s.student_no=ch.student_no

and student_name like ‘张%’;

7、or

select ch.student_no,cs.course_name,ch.score from choose ch,course cs where ch.course_no=cs.course_no

and (cs.course_name=‘C语言’ or cs.course_name=‘java’);

8、非运算not(!)

select * from course where up_limit!=60;

select * from course where !(up_limit=60);

select * from course where not(up_limit=60);

排序

order by子句

1、单列进行排序

例如:按照考试成绩,降序显示学号、考试成绩、平时成绩

select * from score order by exam_grade desc;

将综合成绩排序

select stu_no,exam_score,regular_score,exam_score0.8+regular_score0.2 total_score from exam order by total_score desc;

排序字段也可以写字段的列数(其中4表示查询出来的字段第四列的total_score)

select stu_no,exam_score,regular_score,exam_score0.8+regular_score0.2 total_score from exam order by 4 desc;

2、多列进行排序

select table_schema,table_name from information_schema.tables order by table_schema,table_name desc;

注意:desc只修饰table_name,table_schema没有修饰默认为升序,因此该语句是实现先对table_schema进行升序排序,在

它相同的情况下按照table_name进行降序排序

空值在mysql中默认按照最小值处理的

聚合函数

count(expr) 返回expr的非空值的数量

max(expr) 返回expr的最大值

min(expr) 返回expr的最小值

sum(expr) 返回expr的累加和

avg(expr) 返回expr的平均值

基本用法

select count(*) from choose;

select max(choose_time),min(choose_time) from choose;

select sum(score),avg(score) from choose where student_no=‘2018001’;

注意:1、聚合函数在对null值的处理是忽略的,是非空的汇总

​ 2、聚合函数的参数可以用distincrt修饰的

分组

group by 字段列表 [having 条件表达式]

单列分组

统计每个学生的总分、平均分

select student_no,sum(score) 总分,avg(score) 平均分 from choose group by student_no;

内连接分组查询

要采取连接查询的原因:在查询student_name是依赖于分组字段,如果不进行连接查询,会报错

多列分组

select s.student_no,student_name,sum(score) 总分,avg)(score) 平均分

from student s ,choose c where s.student_no=c.student_no group by s.student_no,s.student_name;

having关键字

作用:在分组得到的结果添加条件进行筛选

select table_schema,count(*) cnt from information_schema.tables

group by table_schema having cnt>50;

select distinct… from t1 (left/right) join t2 on t1.xx=t2.xx where 分组前条件1 and 分组前条件2

having 分组后条件3 order by 排序字段 limit

语法:select from where group by having order by

执行: from where select group by having order by

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值