一、过滤敏感词
功能拆解:
敏感词过滤器:定义前缀树;根据敏感词,初始化前缀树;编写过滤敏感词的方法
具体实现:
首先,创建一个Trie节点类:
接着,创建一个敏感词过滤服务,在service里:
SensitiveWordFilterService
类首先在init
方法中初始化敏感词列表。然后,我们使用addSensitiveWord
方法将敏感词添加到Trie树中。最后,我们在filter
方法中过滤敏感词。当调用filter
方法时,它将遍历文本,并使用Trie树来检查文本中是否包含敏感词。如果发现敏感词,则将其替换为指定的字符(在这个例子中是*
)。最后,该方法将过滤后的文本返回。
前缀树:
二、发布帖子
功能拆解:
使用ajax,实现发布帖子功能
具体实现:
以下是使用Ajax来实现发布帖子功能的基本步骤:
-
创建一个HTML页面,其中包含一个表单,用户可以在表单中输入帖子的标题和内容。
-
通过JavaScript,监听表单的提交事件。当表单被提交时,阻止默认的表单提交行为。
-
获取表单中的数据(例如标题和内容),然后使用Ajax来异步发送数据到服务器。
-
服务器接收到数据后,处理数据(例如保存到数据库),然后返回一个响应。
-
JavaScript接收到服务器的响应后,根据响应的内容来更新页面(例如显示一个消息,告诉用户帖子是否发布成功)。
三、帖子详情
功能拆解:
点击帖子标题就显示帖子内容
具体实现:
DiscussPostMapper
DiscussPostService
DiscussPostController
index.html:在帖子标题上增加访问详情页面的链接
discuss- detail.html:
处理静态资源的访问路径
复用index.html的header区域
显示标题、作者、发布时间、帖子正文等内容
四、事务管理
事务(Transaction)是一个执行单元,包含一系列对数据库的读/写操作。这些操作要么全部执行成功,要么全部执行失败。事务是数据库管理系统中执行调度的基本单位,具有以下四个基本特性,通常简称为ACID特性:
-
原子性(Atomicity):事务中包含的所有操作是一个不可分割的工作单位,要么全部成功,要么全部失败。如果事务中的某个操作失败,那么整个事务将回滚到开始状态,所有已经完成的操作将被撤销。
-
一致性(Consistency):事务应确保数据库从一个一致的状态转换到另一个一致的状态。在事务开始之前和结束之后,数据库的完整性约束必须保持不变。例如,银行转账,无论是成功还是失败,转账前后的总金额应该保持一致。
-
隔离性(Isolation):在并发环境下,一个事务的执行不应该被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,其他事务在这个事务提交之前不能看到这个事务内的操作。
-
持久性(Durability):一旦事务提交成功,其中的所有操作就都会永久保存到数据库中。即使系统发生崩溃,事务执行的结果依然不会被丢失。
这四个特性保证了数据库事务是完整、一致、隔离和持久的操作,使得在并发和分布式的环境下,可以安全、有效地访问和修改数据。
事务隔离级别:
事务的隔离级别是一个概念,用于控制在一个事务中所做的操作对其他并发事务的可见性和影响。设置适当的隔离级别可以帮助防止数据不一致、数据冲突和其他并发问题。SQL标准定义了四个隔离级别,从低到高分别是:
-
读未提交(Read Uncommitted): 在这个级别,一个事务可以读取另一个事务未提交的数据。这是最低的隔离级别,允许脏读(读取到其他事务未提交的数据),但是它可以实现最高的并发性能。因为事务之间基本上没有隔离,所以不常使用。
-
读已提交(Read Committed): 在这个级别,一个事务只能读取另一个事务已经提交的数据。这可以防止脏读,但是仍然允许不可重复读(在一个事务内读取了多次数据,由于其他事务的修改导致数据在这个事务中前后读取不一致)和幻读(在事务中插入或删除了一些记录,导致读取的行数不一致)。
-
可重复读(Repeatable Read): 在这个级别,其他事务不能修改或插入当前事务已经读取的数据,直到当前事务完成。这解决了不可重复读的问题,但仍然允许幻读。
-
串行化(Serializable): 这是最高的隔离级别,它要求所有事务串行执行。这意味着在同一时间只能有一个事务在执行。虽然这可以防止所有并发问题(脏读、不可重复读和幻读),但它也会严重降低系统的并发性能。
每个隔离级别都有其适用场景和权衡。在选择适合的隔离级别时,需要在数据一致性和系统性能之间做出平衡。
悲观锁和乐观锁:
悲观锁(Pessimistic Locking)和乐观锁(Optimistic Locking)都是在数据库和软件开发中用来管理并发控制的两种常见策略。这两种锁的主要区别在于它们如何处理并发事务。
-
悲观锁(Pessimistic Locking):
- 基本思想:悲观锁的核心思想是在数据被访问前先加锁。这样可以确保在锁持有期间,没有其他事务可以修改被锁定的数据。
- 适用场景:当预期到发生冲突的概率很高时,适合使用悲观锁。
- 优点:数据更加安全,因为一旦数据被锁定,其他事务就不能修改它,从而可以避免数据不一致。
- 缺点:在高并发环境下,由于事务在等待锁的时候无法做其他事情,因此可能导致性能瓶颈。同时,可能导致死锁的发生。
-
乐观锁(Optimistic Locking):
- 基本思想:乐观锁的核心思想是先进行操作,然后在提交时检查是否发生了冲突。如果没有冲突,就提交操作;如果发生了冲突,就回滚操作。
- 适用场景:当预期到发生冲突的概率很低时,适合使用乐观锁。
- 优点:在高并发环境下,由于不需要加锁,因此可以提高性能。
- 缺点:如果发生了冲突,需要回滚操作,这可能导致更高的开销。同时,数据的一致性可能较低。
总之,悲观锁和乐观锁都有各自的优点和缺点。在实际应用中,根据具体场景和需求,选择适合的锁机制。
spring事务管理:
Spring事务管理是Spring框架提供的一个关于事务处理的功能,它可以帮助你在企业级应用中更轻松地管理数据事务。
Spring支持编程式事务管理和声明式事务管理两种方式。
-
编程式事务管理:
- 直接在业务代码中手动管理事务,通过
TransactionTemplate
或者PlatformTransactionManager
来实现。 - 更加灵活,可以在运行时决定事务边界。
- 但是代码侵入性强,不利于维护。
- 直接在业务代码中手动管理事务,通过
-
声明式事务管理:
- 声明式事务管理是Spring推荐的事务管理方式。
-
通过注解(如
@Transactional
)或XML配置,把事务管理代码从业务代码中分离出来。 - 避免了代码侵入性,更加模块化和易于维护。
五、显示评论
功能拆解:
数据层:
根据实体查询一页评论数据
根据实体查询评论的数量
业务层:
处理查询讨论的业务
处理查询评论数量的业务
表现层:
显示帖子详情数据时,同时显示该帖子所有的评论数据
六、添加评论
功能拆解:
数据层:
增加评论数据
修改帖子的评论数量
业务层:
处理增加讨论的业务
先增加评论,再更新帖子的评论数量
表现层:
处理增加评论数据的请求
设置添加评论的表单
七、私信列表
功能拆解:
私信列表:
查询当前用户的会话列表,每个会话只显示一条最新的私信;支持分页显示
私信详情:
查询某个会话所包含的私信;支持分页显示
具体实现:
八、发送私信
功能拆解:
发送私信:
采用异步的方式发送私信,发送成功后刷新私信列表
设置已读:
访问私信详情时,将显示的私信设置为已读状态。
具体实现:
九、统一处理异常
在Spring中,可以使用@ControllerAdvice
注解来定义一个全局的异常处理类。在该类中,可以使用@ExceptionHandler
注解来处理特定类型的异常。
十、统一记录日志
功能拆解:
帖子模块,评论模块,消息模块:对所有的方法记日志(这是一种系统需求)
aop的概念:
AOP (Aspect Oriented Programming),即面向切面编程,是一个编程范式,主要用于解决一些在不同模块和层次中都需要实现的共同功能,例如日志、事务、权限等。AOP可以在不修改源代码的情况下,为已有的程序添加新功能或者改变既有功能的行为。
在AOP中,主要有以下几个概念:
-
切面(Aspect):切面是一个类,通常包含多个通知。切面的主要作用是将通用逻辑从业务逻辑中抽离出来,实现横向的代码重用。(会被织入的代码)
-
连接点(JoinPoint):连接点是程序执行中的一个特定位置,比如某个方法被调用的时候或者异常被抛出的时候。(可以被织入代码的地方)
-
通知(Advice):通知是切面中的一个方法,表示在某个连接点上需要执行的具体代码。根据执行的时机,通知可以分为以下几种类型:
- 前置通知:在连接点之前执行的通知
- 后置通知:在连接点之后执行的通知
- 返回通知:在连接点正常返回之后执行的通知
- 异常通知:在连接点抛出异常后执行的通知
- 环绕通知:在连接点之前和之后都可以执行的通知
-
切点(Pointcut):切点是一个表达式,用来指定在哪些连接点上应用通知。通过切点,我们可以精确地控制通知的执行位置。
-
织入(Weaving):织入是将切面和目标程序结合起来,生成一个新的程序的过程。根据织入的时机,织入可以发生在编译时、加载时或运行时。
AOP的主要优点是可以实现关注点的分离,将业务逻辑和通用逻辑分开,降低模块之间的耦合度,提高代码的可重用性和可维护性。在Java中,Spring框架提供了强大的AOP支持,可以轻松实现AOP编程。
具体实现:
spring aop:jdk动态代理,cglib动态代理