仿牛客网项目第三章:开发社区核心功能(详细步骤和思路)

2023-11-14

1. 过滤敏感词

1)可以使用JDK自带的replace方法替换敏感词,但在实际应用中敏感词比较多、字符串可能比较长(发布的一篇文章)这种情况下用replace去替换性能就比较差
2)使用前缀树来实现过滤敏感词的算法。但前缀树方法也有一些局限性,不能实现对停顿词重复词的检查,考虑到此可以优化为DFA算法过滤敏感词

1.1 目的

在发帖子的过程中,可能会有人发布一些敏感词信息,在提交到系统中需要先进行一次过滤,故需要开发过滤敏感词功能

1.2 实现方法

通过前缀树,然后书写过滤敏感词方法,能够实现敏感词的过滤功能。

1.3 前缀树

  1. 名称:Trie,字典树,查找树
  2. 特点:查找效率高,消耗内存大(以空间换时间)
  3. 应用:字符串检索,词频统计和字符串排序

1.4 敏感词过滤步骤(为发帖子做准备)

  1. 定义前缀树
    1)敏感词文件:在resource中添加文件sensitive-words.txt
    2)添加工具类sensitivefilter:(核心搞懂前缀树和过滤功能实现说明
    (1):新建前缀树:TrieNode(),私有
    (2):初始化前缀树:init() ,私有。用@PostConstruct标注,说明只是在类加载的时候运行一次。
    (3):将一个敏感词添加到前缀树中,addKeyword(String keyword),私有
    (4):根据前缀树,对输入的字符串进行过滤,filter(String text),公有,需要考虑符号穿插。
    (5):判断输入字符串是否为符号(符号课采取跳过原则,例如“★开★票★★”,还是能够被检测出来)
  2. 进行测试敏感词过滤效果
    1)新建一个敏感词的测试类SensitiveTests,然后进行测试文本过滤效果
    2)调用公有的铭感次过滤函数sensitiveFilter.filter(text),实现功能

2. 发布帖子

2.1 AJAX介绍

  1. Astnchronous JavaScript and XML
  2. 异步的JavaScipt与XML,不是一门新技术,只是一个新的术语
  3. 使用AJAX,网页能够将增量更新呈现在页面上面,而不需要刷新整个页面
  4. 虽然X代表XML,但是现在使用JSON比XML更加广泛。

2.2 AJAX使用实例

  1. 导包:导入包fastjson(用于)
  2. Util层:在CommunityUtil类中实现获取JSON字符串的三个构造方法:getJSONString()
    1) 直接在CommunityUtil类中测试获取json字符串的方法,
  3. Dao层(把接收到的信息传入数据库):
    1)在DiscussPostMapper中增加插入数据的方法insertDiscussPost。
    2)在mapper文件中增加insert方法的实现。
  4. Service层:在DiscussPostService中增加调用的实现findDiscussPosts。
  5. Controller层:增加DiscussPostController类,添加add访问请求,并修改index.js。
    1)在add方法中,返回json信息而不是文本,故需要添加注解@ResponseBody
    2)add的作用是添加帖子的功能,返回的是json信息,被前端读取后,能够在前端自己完成刷新功能,而不是整体刷新。
    3)修改index.js使得前端能够完成一定的功能。(减轻服务器的压力,负载均衡)
    4)修改index.html中弹出框提示框的内容

3. 帖子详情

3.1 实现功能

通过点击帖子栏中帖子的标题,能够获取用户帖子的详情

3.2 实现过程

  1. Dao层:在DiscussPostMapper中添加根据帖子id查询到帖子对象功能的sql方法申明,并在mapper.xml书写sql语句。
  2. Service层:在DiscussPostService中添加根据帖子id查询到帖子对象功能方法(直接调用)
  3. Controller层:根据用户id获取帖子对象用户对象,传入model中方便在页面进行调用,然后页面跳转至详情页。
  4. index.html:修改点击帖子标题,跳转到详情页面的连接
  5. discuss-detail.html
    1)处理静态资源的访问路径
    2)复用index.html的heade区域
    3)根据得到帖子的对象,在页面显示标题,作者,发布时间和帖子正文内容

4. 事务管理

4.1 事务介绍

事务是由N步数据库操作序列组成的逻辑执行单元,这系列操作要么全执行,要么全放弃执行

4.2 事务四大特性

  1. 原子性(Atomicity):事务是应用中不可再分的最小执行体。
  2. 一致性(Consistency):事务执行的结果,须使数据从一个一致性状态,变为另一个一致性状态。
  3. 隔离性(Isolation):各个事务的执行互不干扰,任何事务的内部操作对其他的事务都是隔离的。
  4. 持久性(Durability):事务一旦提交,对数据所做的任何改变都要记录到永久存储器

4.3 事务的隔离性

  1. 并发异常
    读取未提交都不能解决
    1)第一类丢失更新:一个查询回滚,一个查询更新,前者慢一点,会导致后者的更新丢失
    2)脏读:一个事务读取另一个事务未提交的数据(读取已提交能够解决
    3)第二类丢失更新:两个都进行查询更新,会使得前者更新值丢失
    4)不可重复度:一个事务进行数据更新,另一个事务进行多次访问出现不一致。(可重复读能够解决
    5)幻读:对数据的添加和删除,使得另一个事务在多次查询的时候感觉出现了幻觉(类似不可重复读,不过前者是数据更新,后者是数据修改或者删除)(序列化能够解决

4.4 事务的实现机制

  1. 悲观锁(数据库自带)
    1)共享锁(S锁):事务A对某数据加上共享锁后,其他事务只能对数据加共享锁,不能加排他锁
    2)排它锁(X锁):事务A对某数据加上排他锁后,其他事务既不能给数据加上排他锁,也不能加上共享锁。
  2. 乐观锁(自定义)
    1)版本号,时间戳等
    2)版本号工作原理:在更新数据之前,检查版本号是否发生变化,若变化则取消本次更新,否则就更新内容,且版本号+1。

4.4 事务的管理(Spring Boot)

  1. 申明式事务(XML+注解+方法)(更常用,编写简单
    1)通过XML配置,申明某方法的事务特征
    2)通过注解,申明某方法的事务特征
  2. 编程式事务(TransactionTemplate+方法内部)
    1)通过TransactionTemplate管理事务
    2)并通过她执行数据库的操作
  3. 两者区别
    1)更简单:申明式事务只能申明方法的整体,不能对局部代码进行事务管理;但是事务管理非常方便,只需要添加注解
    2)更精细:编程式事务形成一个TransactionTemplate对象,把需要管理的代码可以局部圈起来。
  4. 管理事务的两个参数
    1)隔离级别:在上述已经说明了(一般用可重复度)
    2)关联方式:REQUIRED;REQUIRES_NEW;NESTED
    (1)REQUIRED:支持当前事务(外部事务),如果不存在则创建新事务.
    (2)REQUIRES_NEW创建一个新事务,并且暂停当前事务(外部事务).
    (3)NESTED:如果当前存在事务(外部事务),则嵌套在该事务中执行(独立的提交和回滚),否则就会REQUIRED一样.
  5. 两种管理事务方式例子
    1)在AlphaService里面书写两种事务管理方式事例。
    2)申明式事务:在方法上加上注解:@Transactional,里面有两个参数
    3)新增用户,新增帖子,然后加上一个会报错的语句
    4)如果有事务管理,会因为存在报错,而进行回滚,其他语句也不会执行。
    5)新建一个测试类DiscusspostTests,执行两种方法,查看数据库的改变。数据库就没变。

5. 显示评论

  1. 评论表对象:存在非常多种类型的评论,用参数entity_type进行区分。
  2. 实体类:定义评论entity:一实体一表,添加评论表。
  3. Dao层:创建CommentMapper
    1)根据评论类型和帖子id,查询一页评论的数据(需进行翻页展示):
    (1):根据四个参数,从帖子数据库中获取所需帖子:
    selectCommentsByEntity(int entityType, int entityId, int offset, int limit)
    2)根据实体查询评论的数量:
    (1):根据评论类型和帖子id,获取评论的数量:
    selectCountByEntity(int entityType, int entityId)
    3)新建comment-mapper.xml,对Dao层进行实现
  4. 业务层Service:创建CommentService
    1)处理查询评论的业务:直接调用Dao方法
    2)处理查询评论数量的业务,直接调用Dao方法
  5. 实现层Controller:这一层与帖子详情功能共享,在同一个页面
    1)根获取不同类型评论对象:评论对象回复对象(评论的评论,回复对象还有两种),传值给model。(思路简单,步骤繁琐了点)
  6. .xtml
  1. 有两类评论,评论和回复两种类型,需要分别进行展示。通过循环操作。
  2. 在帖子详情里面,复用首页分页的功能

6. 添加评论(事务管理)

  1. Dao层:
    (1)增加评论数据:在comment里书写:insertComment(Comment comment);
    (2)修改帖子的评论数量:在discussPost里书写:updateCommentCount
    (3)对应书写mapper.xml的文件
  2. Service层:
    1)处理添加评论的功能:
    2)先增加评论,再更新帖子的评论数量(事务操作,两者连在一起):在DiscussPostService先书写更新帖子数量,然后再CommentService里面书写帖子个数。
  3. Controller层:
    1)处理添加评论数据的请求:书写方法:addComment
  4. html层:
  1. 设置添加评论的表单(有两个地方需要放入表单)

7. 私信列表+私信详情

7.0 功能说明

  1. 私信列表:通过私信列表,能够查询到最近有谁给你发了消息,显示最新的一条消息(类似首页帖子)
  2. 私信详情:点击消息,能够直到消息的详情,把所有交流的内容都放出来。
  3. 两者都支持分页展示功能

7.1 私信列表+私信详情

  1. 查询当前用户的会话列表和私信详情列表
    1)Entity实体类:创建Message实体类
    private int id;                    //自动生成的id
    private int fromId;                //发送者id
    private int toId;                  //接收者id
    private String conversationId;     //会话id(第几次会话了)
    private String content;           //会话内容
    private int status;                //状态(0未读,1已读,2删除)
    private Date createTime;           //交流时间

2)Dao层:创建MessageMapper
书写五个查询方法
(1)私信列表:查询当前用户的会话列表,针对每个对话只返回最新一条的私信(sql注意)
(2)私信列表:查询当前用户的会话数量
(3)私信详情:查询某个会话所包含的私信列表
(4)私信详情:查询某个会话所包含的私信数量
(5)私信列表:查询未读私信的数量
3)Dao层:创建对应的。xml文件书写sql语句
4)Service层:创建MessageService:直接调用对应Dao方法(比较简单,核心逻辑放到表现层);在UserService中添加方法:根据用户的名字查找用户对象。
5)Controller层:创建MessageController
(1)私信列表请求:分页信息,私信列表信息,私信数量,发送私信对象,未读私信数量,把以上几个数据都查找出来,然后通过写入Model中,传递给前端页面。
(2)私信详情请求:分页信息,私信详情列表,私信详情发送对象,设置已读(把在私信详情列表中出现过的数据)
(3)私信发送请求:发送私信,从前端得到的消息,使用异步方式,故需要注解 @ResponseBody。功能交给前端处理。
(4):小方法一:根据消息的conversationId,结合当前用户判断收信人是谁
(5):小方法二:根据消息,返回消息发送人的id。(用于设置消息的未读转为已读)
6)修改html
(1)修改index.html文件:点击消息,能够跳转页面。
(2)修改letter.html文件:因为是异步的方式,所以还需要修改letter.js文件,设置响应方式。
(3)修改letter_detail.html文件

8. 发送私信

8.1 发送私信+设置已读

  1. 采用异步的方式发送私信
    1)Dao层:添加MessageMapper
    (1)添加方法:新增消息
    (2)添加方法:修改消息状态。出现在显示名单里的标记为已读状态。
    2)**Dao层:**添加Message.xml书写对应sql文件
    3)**Service层:**直接调用Dao的查询方法
    4)Controller层:添加add请求,采用异步通信方法,返回json格式,在前端的message.js中进行逻辑控制。
    5)修改对应的.html文件。

9. 统一处理异常

9.1 处理异常的四种方式

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

9.2 统一处理异常步骤:

  1. 在template目录下新建一级文件
    (1)把最容易出错的两个.xml文件存入:404(请求资源不存在)和500(服务端发生错误)
  2. 在Controller中新建文件夹advice,然后新建ExceptionAdvice
    (1)记录发生错误处的日志信息,并且逐行写下原因是什么
    (2)根据发生错误处请求的方式,分为同步请求和异步请求,分别返回错误页面和错误消息json。
  3. 一旦系统中发送了错误,那么就会自动运行这个方法,进行统一异常的处理机制,非常方便,这就是框架的强大之处。

10. 统一记录日志

10.1 需求

比如一些请求执行的过程中,需要对其进行日志记录,但是一个个在求情中添加不是很方便,故使用功能切面编程技术去实现。

  1. 在Controller运行的时候,可以通过拦截器进行日志记录
  2. 在发生异常的时候,可以通过统一异常管理进行处理
  3. 在业务运行的时候,Service,需要通过AOP进行统一的管理。

10.2 AOP概念和术语

详情见我以前写的文章记录。

10.3 AOP的实现

1. AspectJ
(1)语言级的实现,拓展了java语言,定义了AOP语法(一种新的语言)
(2)在编译器植入代码,有一个专门的编译器,用来生成遵守Java字节码规范的class文件。
2. Spring AOP
(1)纯java实现,不需要专门的编译过程,不需要特殊的类装载器
(2)在运行时通过代理的方式植入代码,只支持方法类型的连接点
(3)支持对 AspectJ的集成
3. 两者区别:
(1):功能:AspectJ功能更强大,但是需要额外语言和编译期;Spring AOP使用更方便,但是有一定局限性,比如只支持方法类型的连接点。
(2):植入代码的时期:AspectJ为编译期,Spring AOP为运行期。

10.4 动态代理的种类(Spring AOP)

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

10.5 项目实现

  1. 在一级目录下面新建文件夹aspect,存放切片文件
  2. 在上述文件夹下新建文件ServiceLogAspect
  3. 文件主要啷个部分:
    1)申明该切片作用的对象,即运行哪些业务需要service。
    2)申请业务那一部分添加切片,@Before,@After,@Round,@AfterReturning,@AfterThrowing,并书写需要额外实现的功能。
    3)特点:使用起来非常方便,只需要新建一个文件就好,不需要额外修改其他的原始文件。

文章参考:
1. 从零开始—仿牛客网讨论社区项目(二)
5. 关于介绍AJAX的文章

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

仿牛客网项目第三章:开发社区核心功能(详细步骤和思路) 的相关文章

随机推荐

  • 03 面向对象(多态,接口)

    如果要求程序员必须在某个类中特定的方法中实现一个特定的功能 应该如何实现 使用抽象方法或者使用接口 interface 抽象方法只能单继承 不能多继承 子类必须使用里面的抽象方法 接口可以多继承 实现类必须重写里面的方法 接口的作用 接口是
  • MOS管泄漏电流简要分析

    待机状态下 晶体管的漏电分析 一个理想的MOS晶体管不应该有任何电流流入衬底或者阱中 当晶体管关闭的时候D S之间不应该存在任何的电流 但是 现实中MOS却存在各种不同的漏电流 漏电流一方面严重减小了低功耗设备的电池使用寿命 另一方面在某些
  • 《深度学习》读书笔记:第3章 概率与信息论

    目录 第3章 概率与信息论 3 1 为什么要使用概率 3 2 随机变量 3 3 概率分布 3 3 1 离散型变量和概率质量函数 3 3 2 连续型变量和概率密度函数 3 4 边缘概率 3 5 条件概率 3 6 条件概率的链式法则 3 7 独
  • 九、网络IO原理-创建ServerSocket的过程

    示例 创建ServerSocker过程 创建ServerSocket并注册端口号8090 ServerSocket server new ServerSocket 8090 while true 循环 final Socket socket
  • [Tools: tiny-cuda-nn] Linux安装

    official repo https github com NVlabs tiny cuda nn 该包可以显著提高NeRF训练速度 是Instant NGP Threestudio和NeRFstudio等框架中 必须使用的 1 命令行安
  • iOS开发之Runtime运行时机制

    摘要 Objective C是基于C加入了面向对象特性和消息转发机制的动态语言 除编译器之外 还需用Runtime系统来动态创建类和对象 进行消息发送和转发 作者通过分析Apple开源的Runtime代码来深入理解OC的Runtime机制
  • js实现模仿广告弹出并关闭弹窗

    css部分
  • 字符串转换整数 (atoi)

    字符串转换整数 atoi 请你来实现一个myAtoi string s 函数 使其能将字符串转换成一个 32 位有符号整数 类似 C C 中的 atoi 函数 函数myAtoi string s 的算法如下 读入字符串并丢弃无用的前导空格
  • linux系统忘记记密码怎么办

    linux 此次操作系统为 CentOS Linux release 7 5 1804 Core 1 重启linux 进入系统的GRUB菜单界面 按下小写字母e进入编辑界面 进入如下画面 2 按下方向键 找到以字符串Linux16开头的行
  • 物联网改造体育产业,这些常见球类都成了数据终端

    从智能手机 衣服 汽车到冰箱 物联网意味着几乎任何物件都可以连接到网络 通过物件里含有的传感器之间的通信和同步 我们获得了大量的数据 这些数据经过分析和处理 产生了大数据智能 现在 物联网 大数据智能不仅仅是一种时尚 一个流行语 更将彻底改
  • pppoe 拨号过程

    PPPoE 拔号过程 发现阶段解析 文档编号 834 浏览 14295 评分 73 最后更新于 2011 02 11 PPPoE拔号的发现阶段 Discovery PPPoE的发现阶段一共分为 4步 分别是 PADI PPPoE Activ
  • 什么是图神经网络

    2019年可以说是图神经网络元年 01 什么是图神经网络 1 图和属性图 要了解图神经网络 首先要了解图 图是由节点和边组成的 如下图所示 一般图中的节点表示实体对象 比如一个用户 一件商品 一辆车 一张银行卡等都可以作为节点 边代表事件或
  • 服务器windows操作系统安装,服务器windows操作系统的安装.doc

    服务器windows操作系统的安装 Windows 2K3 2K8系统的安装 注 在这两个操作系统的安装中尤其要注意RAID卡驱动的加载 Windows server 2003标准版的安装 一 准备工作 Windows 2003标准版的安装
  • Unity之三:配置向导

    文章目录 一 C标准 编译器 微控制器 二 选项 2 1 整数类型 2 1 1 UNITY EXCLUDE STDINT H 2 1 2 UNITY EXCLUDE LIMITS H 2 1 3 UNITY INT WIDTH 2 1 4
  • 项目重构之起始

    百层之台始于累土 合抱之木生于毫末 转眼间来到公司已历三个寒暑 愈加光亮鬓角 隆起的肚腩 无不彰显着开发功力日渐深厚 公司的产品也从H5商城成长为了一款app 步入了他的青年阶段 也许是青春期的原因 也许是成长路上各种功能迭代导致 总而言之
  • Keil5(MDK5)在调试(debug)过程中遇到的问题

    参考原子哥教程 使用开发板 STM32F103RC Keil5 MDK5 在调试 debug 过程中崩溃 IDE已停止运行 http blog csdn net qq 33259138 article details 70224581 现象
  • Py的ipykernel:Python库介绍、安装及使用攻略

    Py的ipykernel Python库介绍 安装及使用攻略 ipykernel是一个用于在Jupyter Notebook中运行Python代码的包 它可以将Python代码转化为可以在IPython内核上运行的格式 下面我们将详细介绍如
  • C/C++中如何获取数组的长度?

    C C 中没有提供 直接获取数组长度的函数 对于存放字符串的字符数组提供了一个strlen函数获取长度 那么对于其他类型的数组如何获取他们的长度呢 其中一种方法是使 用sizeof array sizeof array 0 在C语言中习惯上
  • ctfhub技能树部分wp(潦草笔记)

    备份文件下载 vim缓存 在使用vim时会创建临时缓存文件 关闭vim时缓存文件则会被删除 当vim异常退出后 因为未处理缓存文件 导致可以通过缓存文件恢复原始文件内容 隐藏文件index php swp前加 以 index php 为例
  • 仿牛客网项目第三章:开发社区核心功能(详细步骤和思路)

    目录 1 过滤敏感词 1 1 目的 1 2 实现方法 1 3 前缀树 1 4 敏感词过滤步骤 为发帖子做准备 2 发布帖子 2 1 AJAX介绍 2 2 AJAX使用实例 3 帖子详情 3 1 实现功能 3 2 实现过程 4 事务管理 4