8.1 单元测试
测试用例:
要求:保证测试方法的独立性,测试方法A不能依赖于测试方法B
步骤:初始化数据、执行测试代码、验证测试结果、清理测试数据
常用注解:@BeforeClass(类初始化前执行一次,该方法与类有关必须是静态的)、@AfterClass(类销毁时执行一次,该方法与类有关必须是静态的)、@Before(调用任何测试方法前该注释修饰的方法执行)、@After(调用任何测试方法后该注释修饰的方法执行)
8.2 项目监控
导包Spring Boot Actuator
Spring Boot Actuator的介绍:
- Endpoints:监控应用的入口,Springboot内置了很多端点而且支持自定义端点
- 监控方式:http或jmx
- 使用http监控的访问路径 例如/actuator/health, health是端点的id
- 注意事项:按需配置暴露的端点,不用的端点不要配置否则影响性能且可能被窃取,同时要对所有端点进行权限控制
导包后默认启用两个端点health、info,其他端点要使用需要配置
#springboot actuator配置
#要暴露所有端点
management.endpoints.web.exposure.include=*
#排除caches端点和info端点
management.endpoints.web.exposure.exclude=caches,info
自定义端点:新建一个类在类上加上@Endpoint,在方法上加上请求类型的注解@ReadOperation
@Component
@Endpoint(id="dataBase")
public class DataBaseEndPoint {
@Autowired
DataSource dataSource;
@ReadOperation//该请求是get
public String check() {
try (Connection connection = dataSource.getConnection();) {
return PycommunityUtil.getJSONString(0,"连接数据库成功");
} catch (SQLException throwables) {
return PycommunityUtil.getJSONString(1,"连接数据库失败");
}
}
}
8.3 项目总结
为什么不用session?用什么取代session?
敏感词过滤前缀树算法?事务 AOP
redis技术
8.4 常见面试题
MySQL
存储引擎
存储引擎使用InnoDB,因为InnoDB支持事务,NDB也支持事务但是NDB是在集群环境中使用的,而MySQL通常不做集群,做了集群要考虑分布式的事务,很麻烦。
事务
事务的隔离级别要掌握
要实现隔离性需要加锁
锁
锁按范围分为
- 表级锁 开销小,加锁块,不会出现死锁。发生锁冲突的概率高,并发度低
- 行级锁 开销大,加锁慢,会出现死锁,发生锁冲突的概率低,并发度高
具体针对InnoDB其锁按类型分为 - 共享锁(S):行级,读取一行时加
- 排他锁(X):行级,更新一行时加
- 意向共享锁(IS):表级,表示准备加共享锁,加共享锁之前必须加意向共享锁
- 意向排他锁(IX):表级,表示准备加排他锁,加排他锁之前必须加意向排他锁
- 间隙锁(NK):行级,使用范围条件时,对范围内不存在的记录加锁,一是防止幻读,二是为满足恢复和复制的需要
事务A加了IS锁,则事务B不能加X锁
加锁: - 增加行级锁前,会自动给表加意向锁
- 执行DML语句时,自动加排他锁
- 执行DQL语句时,默认不加锁,需要自己加
死锁:在以下常见时,加入事务1和事务2的第一条语句同时执行完,事务1和事务2会自动分别给id为1和id为2的加排他锁,则两个事务再执行第二条语句时都会互相等待对方的锁释放,没有人让步就发生死锁。
死锁的解决方案: - 一般InnoDB会自动检测到,并使一个事务回滚,另一个事务继续
- 可以设置超时等待参数 innodb_lock_wait_timeout
但是一般死锁的写的逻辑有问题,应该避免,可通过以下方式:
- 不同业务并发访问多个表时,应约定以相同的顺序来访问这些表
- 以批量的方式处理数据时,应事先对数据排序,保证线程按固定的顺序来处理数据
- 在事务中,如果要更新记录,应直接申请足够级别的锁即排他锁
悲观锁(数据库天生是悲观锁,认为一定会出问题,要先加锁),更新数据频繁时使用
乐观锁(自定义,认为不会出问题),查询数据频繁时使用。有两种实现机制:
- 版本号机制
- CAS算法:该算法采用自旋操作,也叫自旋锁(当A线程对数据加锁,B线程不是阻塞等待而是不断循环查看A线程有没有释放锁)
索引
事务为了保证数据安全,索引是为了提高查询效率
B+Tree(InnoDB默认采用)
Redis
数据类型
过期策略
淘汰策略
缓存穿透
场景:查询不存在的数据,使得请求直达存储层,导致数据库负载过大,甚至宕机
缓存击穿
场景:一份热点数据,其访问量非常大,在其缓存失效的瞬间,大量请求直达存储层,导致服务崩溃
缓存雪崩
场景:由于某些原因,缓存层不能提供服务,导致所有请求直达存储层,造成宕机
分布式锁
场景:修改数据时通常要把数据读到内存中,在内存中修改后再存回去。在分布式应用中,可能多个进程同时执行上述操作,而读取和修改非原子操作,所以会产生冲突,增加分布式锁,可以解决该类问题。
原理:在多个进程都能访问到的地方,做一个标记,标识该数据的访问权限。
Spring
spring ioc
spring aop
AOP的术语
spring mvc
客户端发送请求,请求到达前端控制器,前端控制器先调用处理器映射器HandlerMapping查询handler,HandlerMapping可以根据请求路径找到能够处理该请求的controller,之后将能处理该请求的controller和对该请求拦截的interceptors封装为HandlerExecutionChain执行链返回给前端控制器,随后找到支持该类型handler的处理器适配器HandlerAdapter,HandlerAdapter先调用拦截器的prehandle方法,然后调用controller对应的方法,返回ModelAndView对象给前端控制器,然后调用posthandle方法,前端控制器调用视图解析器,视图解析器返回view视图,渲染视图后运行拦截器的aftercompletion方法,返回给客户端。