SpringBoot 阶段测试 1

SpringBoot 阶段测试 1

目录

1、使用JDK8新语法完成下列集合练习:

1.1 List中有1,2,3,4,5,6,7,8,9几个元素要求;

(1) 将奇、偶数分别汇聚成一个List

//初始化集合
List<Integer> numList = new ArrayList<>();
//批量添加数据
Collections.addAll(numList,1,2,3,4,5,6,7,8,9,10);
//或者
//List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

//方法一: 使用 forEach
List<Integer> oddList = new ArrayList<>();
List<Integer> evenList = new ArrayList<>();
numList.forEach(num-> {
    boolean temp = (num%2 == 1) ? oddList.add(num) : evenList.add(num);
});

log.info("numList:{}",numList); //numList:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
log.info("oddList:{}",oddList); //oddList:[1, 3, 5, 7, 9]
log.info("evenList:{}",evenList); //evenList:[2, 4, 6, 8, 10]

//方法二: 使用 filter 过滤 + collect 收集
List<Integer> oddList2 =  numList.stream().filter(num -> num%2==1).collect(Collectors.toList());
List<Integer> evenList2 = numList.stream().filter(num -> num%2==0).collect(Collectors.toList());

log.info("oddList2:{}",oddList2); //oddList2:[1, 3, 5, 7, 9]
log.info("evenList2:{}",evenList2); //evenList2:[2, 4, 6, 8, 10]

(2) 分别求出奇数和偶数的和

//奇数集合
//使用选出来的奇数求和
Optional<Integer> oddSum = oddList.stream().reduce((n, m) -> n + m);
log.info("使用选出来的奇数求和 oddSum:{}",oddSum.get());
//使用选出来的奇数求和 oddSum:25

//使用源集合 求和
oddSum = numList.stream().filter(num -> num % 2 == 1).reduce((n, m) -> n + m);
log.info("使用源集合 求和 oddSum:{}",oddSum.get());
//使用源集合 求和 oddSum:25

//偶数集合
//使用选出来的偶数 求奇数和
Optional<Integer> evenSum = evenList.stream().reduce((n, m) -> n + m);
log.info("使用选出来的偶数 求奇数和 evenSum:{}",evenSum.get());
//使用选出来的偶数 求奇数和 evenSum:30

//使用源集合 求偶数和
evenSum = numList.stream().filter(num->num%2 == 0).reduce((n,m)->n+m);
log.info("使用源集合 求偶数和 evenSum:{}",evenSum.get());
//使用源集合 求偶数和 evenSum:30

1.2 已知集合:[[1,3,5,7,5,3,11],[2,4,6,8,6,4,2],[5,8,7]]要求:

1.2.1 集合转换:["1","3","5","7","5",...,"5", "8","7"]。

List<List<Integer>> oldList = new ArrayList<>();
Collections.addAll(oldList,Arrays.asList(1,3,5,7,5,3,11),Arrays.asList(2,4,6,8,6,4,2),Arrays.asList(5,8,7));

List<String> newList = new ArrayList<>();
oldList.forEach(num->num.forEach(n->newList.add("\""+n+"\"")));
//或
//oldList.forEach(nums->nums.stream().map(n -> "\""+n+"\"").forEach(n->newList.add(n)));

log.info("oldList:{}",oldList); //oldList:[[1, 3, 5, 7, 5, 3, 11], [2, 4, 6, 8, 6, 4, 2], [5, 8, 7]]
log.info("newList:{}",newList); //newList:["1", "3", "5", "7", "5", "3", "11", "2", "4", "6", "8", "6", "4", "2", "5", "8", "7"]

2、springboot框架下的为什么有些依赖是不需要版本号的?

springboot框架下的为什么有些依赖是不需要版本号的:
	SpringBoot框架的版本仲裁中心,对一些依赖进行了版本可控制和冲突处理,版本控制中心没有的需要自定义依赖版本;

3、springboot核心注解是什么,深入介绍下这个注解。

@SpringBootConfiguration: springboot的配置
	@Configuration: spring配置类
		@Component: 说明也是一个spring的组件
@EnableAutoConfiguration: 自动配置
	@AutoConfigurationPackage: 自动配置包
		@Import({Registrar.class}): 导入自动配置包注册 导入著启动类同包及其子内中的所有组件
	@Import({AutoConfigurationImportSelector.class}): 导入自动配置导入选择器
		List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);//获取所有的配置
@ComponentScan(excludeFilters = {  : //按条件剔除一部分组件
	@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
	@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

4、pringboot为什么可以打包成可执行的jar,执行命令是什么?

Spring Boot 打包成Jar包运行的原理:https://blog.csdn.net/y5492853/article/details/123758851

4.1 MANIFEST.MF的主要内容:

xxx.jar/META-INFO/MANIFEST.MF

jar包启动类:
	Main-Class: org.springframework.boot.loader.JarLauncher
主启动类:
	Start-Class: com.kgc.scd.Edocmall96WebApplication

JarLauncher:
    根据 Start-Class
    通过反射拿到了项目的启动类的main方法
    从而启动本地项目

4.2 执行命令

执行命令:
	java -jar xxx.jar

可以添加参数:
    java -jar xxx.jar --server.port=8081
    java -jar -Dserver.port=8081 xxx.jar

5、Springboot的配置文件是哪个?你知道有哪些格式,这些格式的优先级是什么?配置过哪些内容?

5.1Springboot的配置文件

Springboot的配置文件是哪个:
	application

5.2 Springboot的配置文件格式,和优先级

Springboot的配置文件格式:
	application.properties,application.yml,
	bootstrap.properties,bootstrap.yml

优先级:
	bootstrap.properties>bootstrap.yml>application.properties>application.yml

    
配置文件路径优先级:
	项目根路径下的confing下 > 项目根路径下 > 项目类路径(resource)下的confing下 > 项目类路径下

5.3 配置过哪些内容

1、项目基本配置: 
	项目基本信息

2、数据库相关配置:
	mybatis
	mybatis-plus
	jpa
	逆向工程

3、组件相关:
	dubbo
	zookeeper
	eureka
	feign
	hytrix
	ribbon
	zuul
	config配置中心

4、一些官方接口线管:
	微信相关
	支付宝相关
	验证码相关
	短信相关

5、自定义配置:
	一些方便修改的统一配置

6、日志有哪些级别。springboot的默认日志框架是什么?项目中是如何使用的?

日志有哪些级别: trace < dubug < info < warn < error

springboot的默认日志框架是什么: Sl4j + logback

默认日志级别是: info

项目中是如何使用的: 
	实例化日志对象: Logger logger = LoggerFactory.getLogger(getClass());
	添加注解: @Sl4j

7、springboot中你知道有哪些方式可以用来读取配置文件?他们的区别是什么?

读取配置文件方式:
	批量读取: @ConfigurationProperties(prefix="xxx")
	单个读取: @Value("${xxx}")
		如果需要指定配置文件:@PropertySource(value="classpath:xxx.properties")
		
区别: 
	批量获取: 支持松散绑定,支持复杂类型绑定,支持数据格式校验

8、你觉得在哪些业务中可以使用定时任务,在springboot中如何实现定时任务?

哪些业务中可以使用定时任务: 
	订单审核、出库、订单超时自动取消与退款
	优惠卷生成、发放与过期
	物流信息推送与状态刷新
	数据积压监控、日志监控、服务可用性探测作业
	定时备份与更新数据
	金融系统每天的定时结算
	按月批量统计报表数据
	
什么业务下需要要定时任务: https://www.csdn.net/tags/MtjaEg3sNjEzMjUtYmxvZwO0O0OO0O0O.html

springboot中如何实现定时任务:
	方法上添加注解: 
		@Scheduled(fixedDelay=second)
		@Scheduled(fixRate=second)
		@Scheduled(cron="cronPartten")
    主动启动类上添加注解:
    	@EnableScheduling

9、你觉得在哪些业务中可以使用异步任务,在 springboot中如何实现异步任务?

哪些业务中可以使用异步任务:
	发送短信验证码
	购买成功或者抽奖成功短信通知
	卡卷或优惠卷发放
	发送微信红包
	微信消息通知
	订单流程处理
	定时批量处理(比如数据同步)
	工作流性质的异步任务(未完成异步任务补偿)

异步调用的经典业务场景: https://blog.csdn.net/fujuan08093206/article/details/79867367

springboot中如何实现异步任务: 
	方法上添加注解:
		@Async
		开启异步线程注解,如果是同一个类中的其他方法调用,添加此异步处理注解,异步是不生效的
	主启动类上添加注解: 
		@EnableAsync

10、redis有哪些数据类型?你常用哪些数据类型?

redis有哪些数据类型:
	string
	list
	set
	hash
	zset
	geospatial
	hyperloglog
	bitmaps

常用哪些数据类型:
	string
	hash
	zset: 比如 做浏览记录
	bitmaps: 比如 每日打卡(占用内存小)

11、如何在redis中保存一个java对象,又如何把redis中数据变为java对象?

如何在redis中保存一个java对象: 
	将对象转换为json字符串,存入redis中

如何把redis中数据变为java对象:
	从redis中获取对象json字符串,再转为对应的对象
	
注意: 需要自定义对象序列化方式

12、什么是序列化?为什么需要序列化,在哪些场景中需要序列化?

什么是序列化:
	把对象转换为字节序列的过程
	将对象的状态信息转换为可以存储或传输的形式的过程
什么是反序列化:
	把字节序列恢复为对象的过程


为什么需要序列化:
	序列化的原因是 想将对象转换成流,方便存储和在网络上传输。

在哪些场景中需要序列化:
	把内存中的对象状态保存到一个文件或者数据库中时候
	用套接字再网络上传送对象的时候
	通过RMI传输对象的时候(RMI是什么东西?):RMI总结来说就是远程调用对象,在一个jvm上调用另一个jvm的对象。
	通过RPC调用接口,获取对象的时候
	把对象存入redis中的时候

13、redis是单线程还是单进程的?

redis是单线程还是单进程:
	单线程:

redis 为什么快:
	为什么redis那么快?剖析redis快的原因:
	https://blog.csdn.net/qq3073959033/article/details/127415029
	https://blog.csdn.net/weixin_43001336/article/details/122773260
	
	1.纯内存KV操作
	2.单线程操作
	3.I/O 多路复用
	4.Reactor 设计模式
	
那么为什么Redis是单线程的:
https://blog.csdn.net/weixin_44395707/article/details/106192656
    原因如下:
    1. CPU不是瓶颈:Redis的所有操作都是基于内存的,而CPU不是Redis的瓶颈。在大多数情况下,Redis的瓶颈很可能是机器内存或网络带宽的大小。如果我们想要更高的性能,可以使用单线程Redis,我们可以使用集群(多个进程)解决方案。
    2. 并发性:并行性不是支持多个客户端的唯一策略。Redis使用epoll和事件循环来实现并发策略并节省大量时间而无需上下文切换。
    3. 易于实现:编写多线程程序可能会更加困难。我们需要为线程添加锁和同步机制。
    4. 易于部署:单线程应用程序可以部署在至少具有单个CPU内核的任何计算机上。

14、简述下redis 中 setnx命令的效果或作用?

redis 中 setnx命令的效果或作用:
	只有key不存在的情况下,设置key的值,如key存在,则什么也不做。
	设置成功返回1,失败返回0;

redis setnx java_Redis SETNX 命令:
	https://blog.csdn.net/weixin_39517289/article/details/114468562

15、介绍下你用redis做过的一些业务,以及为什么你用redis 做。

用redis做过的一些业务: 
	缓存
	数据共享分布式
	分布式锁
	全局ID
	计数器
	限流
	位统计
	购物车
	用户消息时间线timeline
	消息队列
	抽奖
	点赞
	签到
	打卡
	商品标签
	商品筛选
	用户关注
	推荐模型
	排行榜
	
Redis 16 个常见的使用场景:
	https://blog.csdn.net/gp_911014/article/details/124744869

16.事务隔离级别有哪些?MySQL的默认隔离级别是?

事务隔离级别有哪些:
	读未提交
	读已提交
	可重复读
	可串行化

MySQL的默认隔离级别是:
	可重复读
	
脏读、幻读和不可重复读:
https://blog.csdn.net/qq_41776884/article/details/81608777
	脏读: 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
	不可重复读: 是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
	幻读: 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.
	提醒:
	脏读: 
		一个事务读取到另外一个事务没有提交的修改数据
	不可重复读的重点是修改:
		同样的条件,你读取过的数据,再次读取出来发现值不一样了
	幻读的重点在于新增或者删除: 
		同样的条件,第 1 次和第 2 次读出来的记录数不一样
隔离级别 脏读 不可重复读 幻读
READ-UNCOMMITTED
READ-COMMITTED ×
REPEATABLE-READ × ×
SERIALIZABLE × × ×

17、为什么要使用统一返回类?

为什么要使用统一返回类:
	统一返回值类型是接口开发中的一种良好的开发习惯(企业级开发基本都有),统一接口返回值的目的是为了加快开发速率以及形成团队良好的代码规范

18、什么叫物理删除什么叫逻辑删除,分别适用于哪些场景?

物理删除:
	物理删除是真正物理地址上的删除,是将数据从数据库中移除的操作,也就是删除的一般意义。
	数据被物理删除后在数据库中就不在存在了,是无法(难以)被恢复的。
逻辑删除:
	逻辑删除不是真正意义上的删除,而是逻辑意义上的删除。通常的实现方式是在数据表中添加一个字段,比如deleted(是否删除,0未删除,1已删除)。
 	数据被逻辑删除后在数据库中依然是存在的,是可以(容易)被恢复的。
 	
适用于哪些场景:
	 物理删除的场景: 数据不再有实际的意义。
	 逻辑删除的场景: 数据的失效属于状态的改变,比如订单作废,用户禁用,员工离职,文稿废弃,优惠券作废,商品下架等。

小知识【1】逻辑删除和物理删除的区别:
	https://blog.csdn.net/qq_39288456/article/details/84786980

19、为什么要使用swagger?

为什么要使用swagger:
	随着sprnigboot、springcloud等微服务的流行,在微服务的设计下,小公司微服务小的几十,大公司大的几百上万的微服务。
	这么多的微服务必定产生了大量的接口调用。而接口的调用就必定要写接口文档。
	在微服务的盛行下,成千上万的接口文档编写,不可能靠人力来编写,故swagger就产生了,它采用自动化实现并解决了人力编写接口文档的问题;

Swagger 提供了一个全新的维护 API 文档的方式,有4大优点:
	1.自动生成文档:只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了文档的时效性。
	2.跨语言性,支持 40 多种语言。
	3.Swagger UI 呈现出来的是一份可交互式的 API 文档,我们可以直接在文档页面尝试 API 的调用,省去了准备复杂的调用参数的过程。
	4.还可以将文档规范导入相关的工具(例如 SoapUI), 这些工具将会为我们自动地创建自动化测试。

20、使用springboot框架相较于之前的spring或者springmvc框架有哪些优势?

springboot框架相较于之前的spring或者springmvc框架有哪些优势:
	Spring Boot实现了自动配置,降低了项目搭建的复杂度。
	独立运行的spring项目:
	内嵌Tomcat或Jetty等Servlet容器;
	无代码生成和xml配置
	准生产的应用监控
	提供starter 简化Maven 配置
	集成了常用的第三方库配置
	
Spring Boot优点:
1、Spring Boot实现了自动配置,降低了项目搭建的复杂度。:
	众所周知Spring框架需要进行大显的配置,Spring Boot引入自动配置的概念,让项目设置变得很容易。
自动配置 spring:Spring Boot 会根据在类路径中的jar包,类,为jar包里的类自动配置Bean,这样会极大减少我们要使用的配置。

2、独立运行的spring项目:
	Spring Boot可以以jar包形式直接运行,如java-jar xxxjar优点是:节省服务器资源

3、内嵌Tomcat或Jetty等Servlet容器;:
	Spring Boot 可以选择内嵌Tomcat,Jetty,这样我们无须以war包形式部署项目。

4、无代码生成和xml配置:
	Spring Boot大量使用spring4.x提供的注解新特性来实现无代码生成和xml 配置。spring4.x提倡使用Java配置和注解配置组合
Spring Boot不需要任何xml配置即可实现spring的所有配置。

5、准生产的应用监控:
	Spring Boot 提供基于http,sh,telnet对运行时的项目进行监控

6、提供starter 简化Maven 配置:
	在Spring Boot 项目中为我们提供了很多的spring-boot-starter-xxx的项目,我们导入指定的这些项目的坐标,就会自动导入和该模块相关的依赖包:

7、集成了常用的第三方库配置:
	集成了大星常用的第三方库配置(例如Jackson,JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用,大部分的Spring Boot应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。

21、回顾过滤器和拦截器的执行时机

​ 过滤器是在DispatcherServlet处理之前拦截,拦截器是在DispatcherServlet处理请求然后调用控制器方法(即我们自己写的处理请求的方法,用@RequestMapping标注)之前进行拦截。

22、Mybatis,Spring,SpringMVC 执行流程图

22.1Mybatis执行流程图

22.2 Spring执行流程图

22.SpringMVC执行流程图

23、MyBatis的mapper接口重载

一般不进行mapper接口重载因为MyBatis是通过 全类名+方法名的保存和寻找策略,可以用过实体传递参数,进行动态sql;如实在是有需要,方法重载后,xml里面的sql语句通过动态sql解决;

接口:

public interface AnimeMapper1 {

    //根据动漫编号查询动漫详情
    Anime selectAnime(@Param("id") Integer animeId);

    //测试mapper接口重载
    Anime selectAnime();

}

xml:

<select id="selectAnime" parameterType="int" resultType="com.kgc.mybatis.bean.Anime">
    select * from animes
    <where>
        <if test="id == null" >
            id = 654
        </if>
        <if test="id != null" >
            id = #{id}
        </if>
    </where>
</select>



posted @ 2022-10-30 17:19  化羽羽  阅读(130)  评论(0编辑  收藏  举报