Java14道高频面试题
面试题
1、JWT
①、JWT(全称:Json Web Token)
是一个开放标准(RFC 7519)
,它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。
②、JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户
③、JWT是由头部、负载和签名这三部分组成的,其中头部和负载都是明文,签名是经过加密处理的。头部是加密方式(HS256)
2、Session和Cookie区别
Session和Cookie都是客户端-服务端的一种存储机制,但是它们之间有一些重要的区别:
1、存储位置:Cookie数据存放在客户端,Session数据存储在服务端
2、数据共享:Cookie是不安全的,可以通过网络被共享,而Session更加安全,因为数据只在客户端和服务器之间共享。
3、数据大小限制:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。
4、数据有效期:Cookie过期时间由开发者设置,而Session数据在用户关闭浏览器后自动过期
5、数据传输:Cookie在每次请求时都需要手动添加到HTTP头中,而Session ID会自动添加到HTTP头中,因此Session更加高效
总之,Cookie更加灵活,但不够安全,适用于不需要太高安全性的场景;Session更加安全,适用于对安全性要求较高的场景。
3、route与router区别
1、router 主要负责页面跳转
2、route 获取当前页面的参数等信息
4、为什么要用token,token的优势
Token是一种用于验证用户身份及权限的机制,它是由服务器颁发给客户端的,用于验证客户端的身份及权限。Token的优势有:
1、增强安全性:Token机制使用了时间戳和签名算法,使得Token更加安全,可以有效防止CSRF攻击
2、简化客户端代码:Token机制允许客户端存储服务器颁发的Token,从而减少了客户端与服务器之间的交互,简化了客户端代码
3、灵活性:Token机制可以根据具体需求进行灵活配置,可以用于不同类型的请求和场景
4、易于实现:Token机制的实现相对简单,可以使用现有的框架和库来实现。
5、token拦截器,前后端如何验证
Token拦截器是一种用于验证用户身份和权限的机制,它通过在HTTP请求头中添加一个Token字段,服务器在处理请求时会检查Token的有效性。
具体实现流程如下:
1、当用户成功登录时,在服务器端生成一个Token,并将其返回给客户端
2、客户端在每次发送请求时,将Token添加到HTTP请求头中。
3、服务拦截器收到请求后,从HTTP请求头中获取Token。
4、服务器对Token进行验证,包括检查Token是否过期、是否被篡改等。
5、如果Token验证通过,则服务器继续处理请求;如果Token验证失败,则返回错误响应。
通过Token拦截器,可以实现前后端的联合验证,增强系统的安全性。前后端分别负责生成、验证和存储Token,以确保Token的安全性和有效性。
6、如何使用自定义注解和AOP实现万能分页
一、先自定义一个注解,然后这个注解上面有三个注解分别为:@Target、@Retention、@Documented
1、@Target({ElementType.METHOD})
在方法上面放注解
2、@Retention(RetentionPolicy.RUNTIME)
表示该注解在程序运行时仍然被保留并可以被读取。
3、@Documented
用于指示注解应该被包含在代码文档中
二、定义切面类 在类里定义切入点
二、AOP,在需要分页的方法上面打上自定义注解,然后使用切入点注解,在有自定义注解的方法运行之前,也就是在环绕通知里面(@around)完成分页配置。
7、reduce函数的概念和使用场景
1、reduce概念:reduce函数是用于对数据进行累加或聚合操作的函数。它接收一个函数作为参数,用于指定聚合的方式,然后将输入的迭代器作为参数传入,通过不断调用指定的聚合函数来将输入的元素进行累加或聚合操作,最后返回一个单独的值
2、使用场景:把扁平化数据转化为树形数据,(统计总数、计算总和、求最大值或最小值)
8、利用线程传递数据
1、ThreadLocal是一个类,它提供了一种将对象保存为线程变量的方法,相当于一个特殊的Map,它通过提供get()和set()方法来实现线程局部变量的功能。
2、ThreadLocalMap的作用:①、为每一个线程创建一个变量,这个变量可以随时获取,并且可以随时设置。
②、可以跨类跨方法传递变量
3、ThreadLocalMap的优点:①、安全性、可以方便的在多线程中传递数据。
②、可以在service层、controller层里面少些代码,减少代码量。
9、MyBatis拦截器
-
Executor 拦截器:对于 Executor 类中的四个基本操作(update、query、flushStatements、commit/rollback),执行前后都可以进行拦截。
-
ParameterHandler 拦截器:对查询参数进行处理的拦截器,可以在执行 SQL 语句前对参数进行处理,比如对参数进行加密等。
-
ResultHandler 拦截器:对查询结果集进行处理的拦截器,可以在获取结果集时对结果进行处理,比如将结果集转换为 Excel 文件等。
-
StatementHandler 拦截器:对 SQL 语句进行处理的拦截器,可以在执行 SQL 语句前对 SQL 进行处理,比如对 SQL 进行分页等。
10、内存泄漏和内存溢出
1、内存泄漏:指程序运行后,没有释放所占用的内存空间(程序中有引用没有释放,不能被GC回收),一次内存泄漏可能不会有很大的影响,但长时间的内存泄漏,堆积到一定程度就会产生内存溢出。
2、内存溢出:内存溢出(Memory Overflow)是指程序请求的内存超出了 JVM 可以提供的最大内存限制,从而导致内存无法分配而产生的错误。内存溢出通常由于应用使用的内存不断增长,超过了 JVM 配置的堆内存大小而导致。内存溢出会导致应用崩溃或者变得非常缓慢。
11、什么 SPI 和 Spring SPI
1、SPI(Service Provider Interface)是一种设计模式,翻译过来就是“服务提供接口”,再说简单一点就是提供某一个服务的接口, 提供给服务开发者或者服务生产商来进行实现。
2、Java SPI 是JDK内置的一种动态加载扩展点的实现。
3、这个机制在一般的业务代码中很少用到,但是在底层框架中却被大量使用,包括JDBC、Dubbo
、Spring框架、日志接口中都有用到,不同的是有的使用Java原生的实现,有的框架则自己实现了一套SPI机制.
4、Spring中的SPI相比于JDK原生的,它的功能更为强大,因为它可以替换的类型不仅仅局限于接口/抽象类,它可以是任何一个类,接口,注解;
5、正因为Spring SPI是支持替换注解类型的SPI,这个特性在Spring Boot中的自动装配有体现(EnableAutoConfiguration注解)
6、Spring的SPI文件是有规矩的,它需要放在工程的META-INF下,且文件名必须为spring.factories ,而文件的内容本质就是一个properties
12、SpringBoot如何自动装配
1、SpringBoot启动的时候加载主配置类,@EnableAutoConfiguration注解开启了自动配置功能。
2、@EnableAutoConfiguration注解里面有一个注解叫@Import,它使用反射的方式导入了AutoConfigurationImportSelector类
3、在AutoConfigurationImportSelector类中有一个getCandidateConfigurations(获取候选配置)方法,它里面调用了SpringFactoriesLoader类
4、在SpringFactoriesLoader里面配置了工厂资源位置,这个位置是固定的(META-INF/spring.factories)
spring.factories是KV结构
5、然后通过spring.factories里面的KV值来自动装配
13、如何实现Starter
1、要有被封装的类(MyResponseAdvice)
原因:因为我们这整个starter都是为它服务的。
2、写一个properties包,里面放各种属性配置类,在这些类上面有两个注解,分别是@ConfigurationProperties(配置注解)和@Data,其中@ConfigurationProperties是别人配置starter的前缀
3、写一个autoConfigution包,里面放的是自动配置类,这个类上面也有两个注解,分别为@ConditionalOnProperty(根据属性开启自动配置的开关)和@Import(导入的类),其中@ConditionalOnProperty这个注解根据属性开启自动配置的开关,而@Import是需要被封装的类
4、最后在resources包下创建 META-INF包 和 spring.factories文件,配置自动注入的key和value
14、ThreadLocal的优点
-
线程隔离:每个线程都有自己的独立变量副本,不受其他线程的影响,确保了线程安全性。
-
简单易用:使用ThreadLocal可以方便地将数据与线程关联起来,无需手动管理线程间的数据传递。
-
开箱即用,开销小:在多线程环境下,可以避免因访问共享变量而需要进行的上锁操作,降低了使用复杂性。
-
适用于各种场景:如对象跨层传递、事务操作、数据库连接等,能够打破层次间的约束,提高代码的可维护性和扩展性。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!