1. 过滤敏感词

  • 前缀树
    • 名称:Trie、字典树、查找树
    • 特点:查找效率高,消耗内存大
    • 应用:字符串检索、词频统计、字符串排序等
    • 性质:
      • 根节点不包含字符,除根节点外每一个节点都只包含一个字符;
      • 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
      • 每个节点的所有子节点包含的字符都不相同。

image.png

  • 敏感词过滤器
    • 定义前缀树SensitiveFilter中treeNode
      • 是否为敏感词最后一位的标识,boolean
      • 存放子节点,map,key为当前节点的值,value为当前节点的子节点
    • 根据敏感词,初始化前缀树,@PostConstruct注解
      • 按照敏感词个数循环添加
        • 从第i个敏感词的开始遍历到结尾
        • 到子节点中查找是否有重复的字符
        • 没有,创建节点添加到map中,添加后或者是有的状态,指针指向当前节点继续
    • 编写过滤敏感词的方法
      • 判断是否是特殊字符,如果是且指针1指向根节点,指针2向下走,添加指针3指向的字符到结果,如果不是根节点(说明特殊字符在疑似敏感字符里面),指针2不动,指针3无论是否根节点都往下走
      • 如果不是特殊字符
        • 判断当前指针3指向的字符没有找到,说明不是敏感词,添加指针2的字符到结果,指针2走一步,指针3指向指针2,指针1复位到根节点
        • 判断当前指针3指向的字符为敏感词结尾,将指针2到指针3的文字替代后添加到结果,指针2移动到当前指针3的后一位,指针3指向指针2,指针1复位到根节点
        • 判断当前指针3指向的字符为疑似敏感词,则将指针3向下走,继续比较
      • 可能存在指针3到达末尾时,指针2还没有到末尾,添加指针2到末尾的字符到结果

image.png

2. 发布帖子

  • DiscussPostController类addDiscussPost方法
  • AJAX
    • Asynchronous JavaScript and XML
    • 异步的JavaScript与XML,不是一门新技术,只是一个新的术语。
    • 使用AJAX,网页能够将增量更新呈现在页面上,而不需要刷新整个页面。
    • 虽然X代表XML,但目前JSON的使用比XML更加普遍。
    • https://developer.mozilla.org/zh-CN/docs/Web/Guide/AJAX
  • 示例
    • 使用jQuery发送AJAX请求。
  • 实践

    • 采用AJAX请求,实现发布帖子的功能。
    • 接受请求携带的参数,创建DiscussPost类
    • 需要将DiscussPost类的title和content进行标签过滤和敏感词过滤
    • 存入到MySQL数据库中

      3. 帖子详情

  • DiscussPostMapper

  • DiscussPostService
  • DiscussPostController类getDiscussPost方法,点赞都是通过redis进行存储
    • 需要封装帖子,帖子的作者,帖子收到的赞和当前用户对帖子的点赞状态
    • 以及当前帖子的评论
      • 评论中需要封装评论和发布评论的作者,当前评论收到的赞和当前用户对当前评论的点赞状态
      • 封装当前评论的回复
        • 也需要封装当前回复和发布回复的作者,同时还需要回复对象的信息,当前回复收到的赞和当前用户对该回复的点赞状态
    • 以及当前帖子收到的总的回复数量
  • index.html
    • 在帖子标题上增加访问详情页面的链接
  • discuss-detail.html

    • 处理静态资源的访问路径
    • 复用index.html的header区域
    • 显示标题、作者、发布时间、帖子正文等内容

      4. 事务管理

      回顾
  • 什么是事务

    • 事务是由N步数据库操作序列组成的逻辑执行单元,这系列操作要么全执行,要么全放弃执行。
  • 事务的特性(ACID)
    • 原子性(Atomicity):事务是应用中不可再分的最小执行体。
    • 一致性(Consistency):事务执行的结果,须使数据从一个一致性状态,变为另一个一致性状态。
    • 隔离性(Isolation):各个事务的执行互不干扰,任何事务的内部操作对其他的事务都是隔离的。
    • 持久性(Durability):事务一旦提交,对数据所做的任何改变都要记录到永久存储器中。

事务的隔离性

  • 常见的并发异常(都是在间隔很短的时间发生的)
    • 第一类丢失更新、第二类丢失更新。
    • 脏读、不可重复读、幻读。
  • 常见的隔离级别
    • Read Uncommitted:读取未提交的数据。
    • Read Committed:读取已提交的数据。
    • Repeatable Read:可重复读。
    • Serializable:串行化。

第一类丢失更新:某一个事务的回滚,导致另外一个事务已更新的数据丢失了。
image.png
第二类丢失更新:某一个事务的提交,导致另外一个事务已更新的数据丢失了。
image.png
脏读:某一个事务,读取了另外一个事务未提交的数据。
image.png
不可重复读:某一个事务,对同一个数据前后读取的结果不一致。
image.png
幻读:某一个事务,对同一个表前后查询到的行数不一致。
image.png
事务隔离级别
03 Spring Boot实践,开发社区核心功能 - 图8
实现机制

  • 悲观锁(数据库):提前加锁
    • 共享锁(S锁) 事务A对某数据加了共享锁后,其他事务只能对该数据加共享锁,但不能加排他锁。其他事务能读,不能改
    • 排他锁(X锁) 事务A对某数据加了排他锁后,其他事务对该数据既不能加共享锁,也不能加排他锁。其他事务不能读也不能改
  • 乐观锁(自定义)
    • 版本号、时间戳等
    • 在更新数据前,检查版本号是否发生变化。若变化则取消本次更新,否则就更新数据(版本号+1)。

Spring事务管理

  • 声明式事务
    • 通过XML配置,声明某方法的事务特征。
    • 通过注解,声明某方法的事务特征。
      • 隔离级别:五种(默认+四种)
      • 常用传播机制:
        • REQUIRED:支持当前事务(外部事务),如果不存在则创建新事务
        • REQUIRED_NEW:创建一个新事务,并且暂定当前事务(外部事务)
        • NESTED:如果当前存在事务(外部事务),则嵌套在该事务中执行(独立的提交和回滚),否则就会和REQUIRED一样
  • 编程式事务

    • 通过 TransactionTemplate 管理事务,并通过它执行数据库的操作。

      5. 显示评论

  • 数据层

    • 根据实体查询一页评论数据。
    • 根据实体查询评论的数量。
  • 业务层
    • 处理查询评论的业务。
    • 处理查询评论数量的业务。
  • 表现层DiscussPostController

    • 显示帖子详情数据时,同时显示该帖子所有的评论数据。

      6. 添加评论

  • 数据层

    • 增加评论数据。
    • 修改帖子的评论数量。
  • 业务层CommentService
    • 处理添加评论的业务:先增加评论(标签过滤、敏感词过滤)、如果是帖子就更新帖子的评论数量。
    • 两次DML操作,需要添加事务管理
  • 表现层CommentController

    • 处理添加评论数据的请求。
    • 设置添加评论的表单。

      7. 私信列表

  • 私信列表MessageController中getLetterList方法

    • 查询当前用户的会话列表,每个会话只显示一条最新的私信。
    • 支持分页显示。
  • 私信详情MessageController中getLetterDetail方法

    • 查询某个会话所包含的私信。
    • 支持分页显示。
    • 设置已读
      • 访问私信详情时,将显示的私信设置为已读状态。

        8. 发送私信

  • 发送私信(可以在回话列表和详情列表进行)MessageController中sendLetter方法

    • 采用异步的方式发送私信。
    • 发送成功后刷新私信列表。
      • 生成ConversationId,小号在前,大号在后
      • 消息需要标签过滤和敏感词过滤
      • 存入MySQL数据库表中

        9. 统一处理异常

  • @ControllerAdvice 当前指定处理controller层

    • 用于修饰类,表示该类是Controller的全局配置类。
    • 在此类中,可以对Controller进行如下三种全局配置:异常处理方案、绑定数据方案、绑定参数方案。
  • 全局配置相关注解ExceptionAdvice类
  • @ExceptionHandler
    • 用于修饰方法,该方法会在Controller出现异常后被调用,用于处理捕获到的异常。
  • @ModelAttribute
    • 用于修饰方法,该方法会在Controller方法执行前被调用,用于为Model对象绑定参数。
  • @DataBinder

    • 用于修饰方法,该方法会在Controller方法执行前被调用,用于绑定参数的转换器。

      10. 统一记录日志

      需求
  • ServiceLogAspect 当前指定处理Service层

  • 帖子模块
  • 评论模块
  • 消息模块

AOP的概念

  • Aspect Oriented Programing,即面向方面(切面)编程。
  • AOP是一种编程思想,是对OOP的补充,可以进一步提高编程的效率。

03 Spring Boot实践,开发社区核心功能 - 图9
AOP的术语
03 Spring Boot实践,开发社区核心功能 - 图10
AOP的实现

  • AspectJ
    • AspectJ是语言级的实现,它扩展了Java语言,定义了AOP语法。
    • AspectJ在编译期织入代码,它有一个专门的编译器,用来生成遵守Java字节码规范的class文件。
  • Spring AOP
    • Spring AOP使用纯Java实现,它不需要专门的编译过程,也不需要特殊的类装载器。
    • Spring AOP在运行时通过代理的方式织入代码,只支持方法类型的连接点。
    • Spring支持对AspectJ的集成。

Spring AOP

  • JDK动态代理
    • Java提供的动态代理技术,可以在运行时创建接口的代理实例。
    • Spring AOP默认采用此种方式,在接口的代理实例中织入代码。
  • CGLib动态代理
    • 采用底层的字节码技术,在运行时创建子类代理实例。
    • 当目标对象不存在接口时,Spring AOP会采用此种方式,在子类实例中织入代码。

Advice
image.png