杂项02
nacos单点启动
默认集群方式启动,指定参数单点启动
startup.cmd -m standalone
技术专题
亮点: 拦截器, 自定义注解, AOP, 分页查询, 单点登录, starter类(项目虽小,功能俱全)
- 配置两个拦截器, 第一个全部拦截用于刷新token;第二个部分拦截用于拦截未登录用户拦截器
- AOP + 自定义注解 + 日志记录
- 统一异常处理 + 常量定义 + 使用自定义异常自定义结果类,链式调用优雅 + 自定义工具类
- 分页查询
- starter类
- JWT + Redis
token令牌的登录方式,访问认证速度快,session共享,安全性
Redis做了令牌和用户信息的对应管理,进一步增加了安全性,登录用户做了缓存,过期时间踢掉线 - threadLocal使用了保存用户信息,请求的线程之内可以随时获取登录用户,做了线程隔离
- 使用完threadLocal之后做了value删除,防止内存泄漏
- 线程池,面试7个核心参数(对当前主业务流程 无影响的操作,放入线程池执行), 登录时,记录日志,不能因为日志功能影响登录主业务流程应该放入线程池, 多线程技术
- 权限系统 + 单点登录
- 使用ThreadLocal保存用户信息,拦截完成之后删除value值
- session存储敏感信息问题, 转成UserDTO对象, 同时可以节省内存占用
自定义starter
它允许您将一组相关的功能、配置和依赖项封装到一个可重用的模块中,以便在多个项目中共享和使用。
AOP
AOP理解
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
AOP是一种编程范式,旨在将横切关注点(cross-cutting concerns)从应用程序的主要逻辑中分离出来,以提高代码的可维护性和可重用性。
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理;
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,

切面
@Aspect
切入点
@Pointcut定义要拦截哪些类的哪些方法;
切入点的匹配规则:
通知
定义了拦截之后方法要做什么;
前置通知@Before
- 声明前置通知, 并将通知应用到指定的切入点上
- 目标类的方法执行前, 执行该通知
返回通知@AfterReturning
- 声明返回通知, 并将通知应用到指定的切入点上
- 目标类的方法在无异常执行后, 执行该通知
最终通知@After
- 声明最终通知, 并将通知应用到指定的切入点上
- 目标类的方法在执行后, 执行该通知(有异常和无异常最终都会执行)
异常通知@AfterThrowing
- 声明异常通知, 并将通知应用到指定的切入点上
- 目标类的方法在执行异常时, 执行该通知
环绕通知@Around
- 声明环绕通知, 并将通知应用到指定的切入点上
- 目标类的方法执行前后, 都可通过环绕通知定义相应的处理
- 需要通过显示调用的方法, 否则无法访问指定方法
SpringCache
常用注解
只支持String, 支持单表,不支持多表; 多表只能用RedisTemplate
-
@CacheConfig:
@CacheConfig(cacheNames = {“user”})
类级别的注解, 统一该类的所有缓存都是“user::”为前缀
-
@Cacheable
方法级注解, 用于将方法的结果redis缓存起来,
例如如果select方法被调用,先从缓存中读取数据,如果没有找到数据,再执行方法体进行sql查询,最后把返回值添加到缓存中,且是同步操作
缓存中有直接用,不用执行方法体了 -
@CacheEvict
方法级注解, 用于删除缓存
先执行方法体,再根据参数执行删除缓存
@CacheEvict(value = "myCache", key = "#id")用于清除名为 "myCache" 的缓存中键为id的缓存条目。 -
@CachePut
方法级注解, 用于更新缓存, 不会先查redis, 直接执行方法体, 再更新缓存
- springCache的注解是将方法的返回值进行缓存, 所以有时候会缓存一些不必要的数据
- 缓存是缓存在spring容器存放在服务器的, 占用服务器内存, 会给服务器造成过大压力,
- 那么我们可以配置将缓存在redis中, 在yml文件中配置指定redis, 然后可以写一个配置类配置一些不同方法的过期时间, 重写为json序列化器等
- 缓存的值默认是序列化的(io流的序列化), 所以返回的结果类需要实现序列化Serializable,有时候会忘记(重写为json之后不需要)
Redisson分布式
setnx
集群模式或分布式系统, 加锁还是会出现并发问题, 需要使用分布式锁
因为每个服务都是一个单独的JVM维护一个锁监视器
消息中间件篇
4.1消息队列
4.2RabbitMQ
死信交换机和延迟队列
消息堆积
- 增加更多的消费者,提高消费速度
- 开启线程池加快消息处理速度
- 扩大队列容积
高可用
镜像集群
- 镜像队列结构是一主多从,所有操作都是主节点完成,然后同步给镜像节点
- 主节点宕机后,镜像节点会替代成新的主节点
仲裁队列
- 如果有丢失数据采用仲裁队列解决,与镜像队列一样都是主从模式,支持主从同步,主从同步基于Raft协议强一致,只需要在声明队列的时候指定即可
4.3Kafka
如何保证消费的顺序性
一个topic的数据可能存储在不同的分区中,每个分区都有一个按照顺序的存储的偏移量,如果消费者关联了多个分区不能保证顺序性;
- 发送消息时指定分区号
- 发送消息时按照相同的业务设置相同的key
数据清理机制
Kafka存储结构
- Kafka中的topic的数据存储在分区上,分区如果文件过大会分段存储segment
- 每个分段都在磁盘上以索引和日志文件的形式存储
- 分段能够减少单个文件内容的大小,查找数据方便,方便Kafka进行日志清理
日志清理策略
- 根据消息的保留时间,当消息超过指定时间就会触发清理,默认168小时(7天)
- 根据topic存储的数据大小,当topic所占的日志文件大小大于一定的阈值,则开始删除最久的消息(默认关闭)
高可用
- 集群
- 复制机制
高性能
- 消息分区—不受单台服务器的限制,可以不受限的处理更多的数据
- 顺序读写—磁盘顺序读写,提升读写效率
- 页缓存—把磁盘中的数据缓存到内存中,直接对内存访问
- 零拷贝—减少上下文切换及数据拷贝

浙公网安备 33010602011771号