1. 过滤敏感词
- 前缀树
- 名称:Trie、字典树、查找树
- 特点:查找效率高,消耗内存大
- 应用:字符串检索、词频统计、字符串排序等
- 性质:
- 根节点不包含字符,除根节点外每一个节点都只包含一个字符;
- 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
- 每个节点的所有子节点包含的字符都不相同。
- 敏感词过滤器
- 定义前缀树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到末尾的字符到结果
- 定义前缀树SensitiveFilter中treeNode
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请求。
实践
DiscussPostMapper
- DiscussPostService
- DiscussPostController类getDiscussPost方法,点赞都是通过redis进行存储
- 需要封装帖子,帖子的作者,帖子收到的赞和当前用户对帖子的点赞状态
- 以及当前帖子的评论
- 评论中需要封装评论和发布评论的作者,当前评论收到的赞和当前用户对当前评论的点赞状态
- 封装当前评论的回复
- 也需要封装当前回复和发布回复的作者,同时还需要回复对象的信息,当前回复收到的赞和当前用户对该回复的点赞状态
- 以及当前帖子收到的总的回复数量
- index.html
- 在帖子标题上增加访问详情页面的链接
discuss-detail.html
什么是事务
- 事务是由N步数据库操作序列组成的逻辑执行单元,这系列操作要么全执行,要么全放弃执行。
- 事务的特性(ACID)
- 原子性(Atomicity):事务是应用中不可再分的最小执行体。
- 一致性(Consistency):事务执行的结果,须使数据从一个一致性状态,变为另一个一致性状态。
- 隔离性(Isolation):各个事务的执行互不干扰,任何事务的内部操作对其他的事务都是隔离的。
- 持久性(Durability):事务一旦提交,对数据所做的任何改变都要记录到永久存储器中。
事务的隔离性
- 常见的并发异常(都是在间隔很短的时间发生的)
- 第一类丢失更新、第二类丢失更新。
- 脏读、不可重复读、幻读。
- 常见的隔离级别
- Read Uncommitted:读取未提交的数据。
- Read Committed:读取已提交的数据。
- Repeatable Read:可重复读。
- Serializable:串行化。
第一类丢失更新:某一个事务的回滚,导致另外一个事务已更新的数据丢失了。
第二类丢失更新:某一个事务的提交,导致另外一个事务已更新的数据丢失了。
脏读:某一个事务,读取了另外一个事务未提交的数据。
不可重复读:某一个事务,对同一个数据前后读取的结果不一致。
幻读:某一个事务,对同一个表前后查询到的行数不一致。
事务隔离级别:
实现机制
- 悲观锁(数据库):提前加锁
- 共享锁(S锁) 事务A对某数据加了共享锁后,其他事务只能对该数据加共享锁,但不能加排他锁。其他事务能读,不能改
- 排他锁(X锁) 事务A对某数据加了排他锁后,其他事务对该数据既不能加共享锁,也不能加排他锁。其他事务不能读也不能改
- 乐观锁(自定义)
- 版本号、时间戳等
- 在更新数据前,检查版本号是否发生变化。若变化则取消本次更新,否则就更新数据(版本号+1)。
Spring事务管理
- 声明式事务
- 通过XML配置,声明某方法的事务特征。
- 通过注解,声明某方法的事务特征。
- 隔离级别:五种(默认+四种)
- 常用传播机制:
- REQUIRED:支持当前事务(外部事务),如果不存在则创建新事务
- REQUIRED_NEW:创建一个新事务,并且暂定当前事务(外部事务)
- NESTED:如果当前存在事务(外部事务),则嵌套在该事务中执行(独立的提交和回滚),否则就会和REQUIRED一样
编程式事务
数据层
- 根据实体查询一页评论数据。
- 根据实体查询评论的数量。
- 业务层
- 处理查询评论的业务。
- 处理查询评论数量的业务。
表现层DiscussPostController
数据层
- 增加评论数据。
- 修改帖子的评论数量。
- 业务层CommentService
- 处理添加评论的业务:先增加评论(标签过滤、敏感词过滤)、如果是帖子就更新帖子的评论数量。
- 两次DML操作,需要添加事务管理
表现层CommentController
私信列表MessageController中getLetterList方法
- 查询当前用户的会话列表,每个会话只显示一条最新的私信。
- 支持分页显示。
私信详情MessageController中getLetterDetail方法
发送私信(可以在回话列表和详情列表进行)MessageController中sendLetter方法
@ControllerAdvice 当前指定处理controller层
- 用于修饰类,表示该类是Controller的全局配置类。
- 在此类中,可以对Controller进行如下三种全局配置:异常处理方案、绑定数据方案、绑定参数方案。
- 全局配置相关注解ExceptionAdvice类
- @ExceptionHandler
- 用于修饰方法,该方法会在Controller出现异常后被调用,用于处理捕获到的异常。
- @ModelAttribute
- 用于修饰方法,该方法会在Controller方法执行前被调用,用于为Model对象绑定参数。
@DataBinder
ServiceLogAspect 当前指定处理Service层
- 帖子模块
- 评论模块
- 消息模块
AOP的概念:
- Aspect Oriented Programing,即面向方面(切面)编程。
- AOP是一种编程思想,是对OOP的补充,可以进一步提高编程的效率。
- 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