学习笔记:基于SpringBoot的牛客网社区项目实现(六)之发表帖子 + 评论 + 私信

news2024/9/27 5:52:46

一、过滤敏感词

二、发布帖子

 业务流程:

        1、先创建帖子的实体DiscussPost,属性有帖子id,user_id,title,content,type,status,create_time,comment_count,score,常规的生成set,get方法以及toString()方法。

         2、在dao层创建帖子的接口,加上Mapper注解给容器管理类,声明一些对数据库进行操作的方法,以及在resource文件夹下的mapper文件中建立相应的mybatis的xml映射文件,文件的格式可在mybatis官网复制。

List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit);
// @Param注解用于给参数取别名,
// 如果只有一个参数,并且在<if>里使用,则必须加别名.
int selectDiscussPostRows(@Param("userId") int userId);
int insertDiscussPost(DiscussPost discussPost);
DiscussPost selectDiscussPostById(int userId);
int updateCommentCount(int id, int commentCount);

        3、在Service层写处理业务相关代码,如新增一个帖子,先判断帖子是否不为空,然后进行转义HTML标记以及过滤敏感词,最后调用mapper层的插入帖子方法。

public int addDiscussPost(DiscussPost post) {
    if(post == null) {
        throw new IllegalArgumentException("参数不能为空!");
    }
    //转义HTML标记
    post.setTitle(HtmlUtils.htmlEscape(post.getTitle()));
    post.setContent(HtmlUtils.htmlEscape(post.getContent()));
    //过滤敏感词
    post.setTitle(sensitiveFilter.filter(post.getTitle()));
    post.setContent(sensitiveFilter.filter(post.getContent()));
    return discussPostMapper.insertDiscussPost(post);
}

         4、在Controller层处理浏览器的请求,在类前加上注解@Controller,@RequestMapping("/discuss")说明这个类下的访问路径都是在/discuss路径下的。

判断当前登录用户不为空,然后新建一个帖子对象,将浏览器传来的数据赋值给post对象,再调用Service层的新增帖子方法,将浏览器新建的帖子新增进数据库,最后返回json格式的数据,0代表成功状态,发布成功。

@RequestMapping(path = "/add", method = RequestMethod.POST)
@ResponseBody//给浏览器返回json格式数据
public String addDiscussPost(String title, String content) {
    User user = hostHolder.getUser();
    if (user == null) {
        return CommunityUtil.getJSONString(403, "你还没有登录");
    }
    DiscussPost post = new DiscussPost();
    post.setUserId(user.getId());
    post.setTitle(title);
    post.setContent(content);
    post.setCreateTime(new Date());
    discussPostService.addDiscussPost(post);
    return CommunityUtil.getJSONString(0,"发布成功");
}

        5、前端使用AJAX异步发送请求

$(function(){
   $("#publishBtn").click(publish);
});

function publish() {
   $("#publishModal").modal("hide");//隐藏发布帖子的输入框

   // 获取标题和内容
   var title = $("#recipient-name").val();
   var content = $("#message-text").val();
   // 发送异步请求(POST)
   $.post(
      CONTEXT_PATH + "/discuss/add",
      {"title":title,"content":content},
      function(data) {
         data = $.parseJSON(data);
         // 在提示框中显示返回消息
         $("#hintBody").text(data.msg);
         // 显示提示框
         $("#hintModal").modal("show");
         // 2秒后,自动隐藏提示框
         setTimeout(function(){
            $("#hintModal").modal("hide");
            // 刷新页面
            if(data.code == 0) {
               window.location.reload();
            }
         }, 2000);
      }
   );
}

三、帖子详情 

 业务流程:

        1、在DiscussPostMapper中新增根据id查找帖子的方法,并在相应的mybatis文件中新增对数据库的方法。

        2、在DiscussPostService中新增根据id查找帖子的方法,业务比较简单,只是调用mapper中对应查找的方法,注意返回类型是DiscussPost类型。

        3、在DiscussPostController中获取浏览器地址栏中帖子的id,然后根据id查找数据库中对应的帖子,以及当前登录的用户信息,通过Model返回给前端页面。

@RequestMapping(path = "/detail/{discussPostId}", method = RequestMethod.GET)
public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model) {
    //帖子
    DiscussPost post = discussPostService.findDiscussPostById(discussPostId);
    model.addAttribute("post", post);
    //作者
    User user = userService.findUserById(post.getUserId());
    model.addAttribute("user",user);

    return "/site/discuss-detail";
}

 四、显示评论

数据库comment表的设计 :id(评论id),user_id,entity_type(1代表是对帖子的评论,2代表是回复别人的评论),entity_id,target_id,content,status,create_time

业务流程如上图所示,数据层,业务层,表现层。

@Mapper
public interface CommentMapper {

    List<Comment> selectCommentsByEntity(int entityType, int entityId, int offset, int limit);

    int selectCountByEntity(int entityType, int entityId);

    int insertComment(Comment comment);
}
@Service
public class CommentService implements CommunityConstant {

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private SensitiveFilter sensitiveFilter;

    @Autowired
    private DiscussPostService discussPostService;

    public List<Comment> findCommentsByEntity(int entityType, int entityId, int offset, int limit) {
        return commentMapper.selectCommentsByEntity(entityType, entityId, offset, limit);
    }

    public int findCommentCount(int entityType, int entityId) {
        return commentMapper.selectCountByEntity(entityType, entityId);
    }

    public Comment findCommentsById(int id) {
        return commentMapper.findCommentsById(id);
    }

    //添加评论和更新帖子评论数量需要同时进行,放在一个事务之中
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public int addComment(Comment comment) {
        if (comment == null) {
            throw new IllegalArgumentException("参数不能为空!");
        }

        // 添加评论
        comment.setContent(HtmlUtils.htmlEscape(comment.getContent()));
        comment.setContent(sensitiveFilter.filter(comment.getContent()));
        int row = commentMapper.insertComment(comment);

        // 更新帖子评论数量
        if (comment.getEntityType() == ENTITY_TYPE_POST) {
            int count = commentMapper.selectCountByEntity(comment.getEntityType(), comment.getEntityId());
            discussPostService.updateCommentCount(comment.getEntityId(), count);
        }

        return row;
    }
}

 五、显示私信

/**
 * 每一个会话加入私信数量,未读数量,自己发送私信的target
 * 总的未读消息数量
 */
@RequestMapping(path = "/letter/list", method = RequestMethod.GET)
    public String getLetterList(Model model, Page page) {

        User user = hostHolder.getUser();
        //分页信息
        page.setLimit(5);
        page.setPath("/letter/list");
        page.setRows(messageService.findConversationCount(user.getId()));

        List<Message> conversationList = messageService.findConversations(user.getId(), page.getOffset(), page.getLimit());
        List<Map<String, Object>> conversations = new ArrayList<>();
        if (conversationList != null) {
            for (Message message : conversationList) {
                Map<String, Object> map = new HashMap<>();
                map.put("conversation", message);
                map.put("letterCount", messageService.findLetterCount(message.getConversationId()));
                map.put("unreadCount", messageService.findLetterUnreadCount(user.getId(), message.getConversationId()));
                int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId();
                map.put("target", userService.findUserById(targetId));

                conversations.add(map);
            }
        }
        model.addAttribute("conversations", conversations);

        // 查询未读消息总数
        int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null);
        model.addAttribute("letterUnreadCount", letterUnreadCount);

        return "/site/letter";
    }

 六、发送私信

 

@RequestMapping(path = "/letter/send", method = RequestMethod.POST)
    @ResponseBody
    public String sendLetter(String toName, String content) {
        User target = userService.findUserByName(toName);
        if (target == null) {
            return CommunityUtil.getJSONString(1, "目标用户不存在!");
        }
        Message message = new Message();
        message.setFromId(hostHolder.getUser().getId());
        message.setToId(target.getId());
        if (message.getFromId() < message.getToId()) {
            message.setConversationId(message.getFromId() + "_" + message.getToId());
        }else {
            message.setConversationId(message.getToId() + "_" + message.getFromId());
        }
        message.setContent(content);
        message.setCreateTime(new Date());
        messageService.addMessage(message);

        return CommunityUtil.getJSONString(0);
    }

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python入门知识】NumPy 数组搜索,案例+理论讲解

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 搜索数组 可以在数组中搜索&#xff08;检索&#xff09;某个值&#xff0c;然后返回获得匹配的索引。 要搜索数组&#xff0c;请使用 where() 方法。 实例 查找值为 4 的索引&#xff1a; import numpy as nparr np.…

[ tool ] Xpath选择器和selenium工具基本使用

XPath xpath介绍 是一门在XML文档中查找信息的语言 html文档准备 doc <html><head><base hrefhttp://example.com/ /><title>Example website</title></head><body><div idimages><a hrefimage1.html aabb>Name: My…

车载激光雷达原理+双激光雷达方案+纯激光雷达感知3Dbonding box

集度汽车透露了首款汽车机器人概念车车头部位的设计细节&#xff0c;车前灯和车前盖处激光雷达的设计清晰可见。至此&#xff0c;集度汽车的车前盖、前向双激光雷达自动驾驶技术方案首次曝光。 集度汽车官方也称&#xff0c;“双激光雷达”设计方案极具创新性&#xff0c;激光…

求中位数?

文章目录 如何求一个中位数&#xff1f;[295. 数据流的中位数](https://leetcode.cn/problems/find-median-from-data-stream/)常规思路&#xff1a;解决思路&#xff1a; 如何求一个中位数&#xff1f; 如果输入一个数组&#xff0c;让你求中位数&#xff0c;简单的解决方法就…

不合格机器人工程讲师如何坦然面对失败

能坦然面对的重要原因是我自己从一开始就知道注定要失败的&#xff0c;或者说失败率接近99.9%。 能够从失败中成长&#xff0c;不断挑战自我&#xff0c;收获更多更大的失败也是一种体验。 失败是客观事实&#xff0c;坦然是主观上的正能量的情绪。 用客观态度对待客观事实。 …

JavaScript class和继承的原理

&#xff08;对于不屈不挠的人来说&#xff0c;没有失败这回事。——俾斯麦&#xff09; class 相关链接 MDN链接 有关类的详细描述 关于构造函数&#xff0c;原型和原型链的说明 类的概述 类是用于创建对象的模板。他们用代码封装数据以处理该数据。JS 中的类建立在原型上…

4月跳槽进字节跳动了,面试真简单...

前言: 最近金三银四跳槽季&#xff0c;相信很多小伙伴都在面试找工作&#xff0c; 怎样才能拿到大厂的offer&#xff0c;没有掌握绝对的技术&#xff0c;那么就要不断的学习&#xff0c;没有绝对的天才&#xff0c;只有持续不断的付出。对于我们每一个平凡人来说&#xff0c;…

Detecting Kernel Memory Leaks in Specialized Modules with Ownership Reasoning

Detecting Kernel Memory Leaks in Specialized Modules with Ownership Reasoning 背景&#xff1a; 内存泄漏&#xff1a;A memory leak happens when an allocated memory region is not released even though it will never be used again.分配的内存未被正常释放。 内存…

Java高阶数据结构 图 图的表示与遍历

高阶数据结构&#xff01; 文章目录 Java高阶数据结构 & 图的概念 & 图的存储与遍历1. 图的基本概念1.1 图的属性1.2 无向图与有向图1.3 完全图1.4 简单路径和回路1.5 子图1.6 连通图 2. 图的存储&#xff08;理论&#xff09;2.1 ※邻接矩阵2.2 邻接链表3. 图的存储&a…

新唐NUC980使用记录(5.10.y内核):u-boot linux rootfs 编译与烧录测试(基于SD1位置SD卡)

文章目录 目的基础准备烧录环境开发编译环境SD卡分区 制作和设置编译工具链制作toolchain和rootfs拷贝rootfs内容到SD卡设置编译工具链 u-boot编译与测试下载、配置与编译烧录u-boot与环境变量 linux kernel编译与测试下载、配置与编译系统运行测试 总结设备树文件内容 目的 从…

【STM32】基础知识 第十一课 sys, delay usart 文件夹

【STM32】基础知识 第十一课 sys, delay & usart 文件夹 sys 文件介绍delay 文件夹函数简介SysTickSysTick 工作原理SysTick 寄存器介绍 delay_init() 函数delay_us() 函数usart 文件夹介绍printf 的使用常用输出控制符表常用转椅字符表 半主机模式简介 sys 文件介绍 函数…

浅谈Linux epoll机制

前言 概述 epoll是一种当文件描述符的内核缓冲区非空的时候&#xff0c;发出可读信号进行通知&#xff0c;当写缓冲区不满的时候&#xff0c;发出可写信号通知的机制&#xff1b; 关键函数 int epoll_create(int size);创建 eventpoll 对象&#xff0c;并将 eventpoll 对象…

Python+Yolov5墙体桥梁裂缝识别

程序示例精选 PythonYolov5墙体桥梁裂缝识别 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonYolov5墙体桥梁裂缝识别>>编写代码&#xff0c;代码整洁&#xff0c;规则&am…

【安装Nginx】

Linux上安装Nginx 文章目录 Linux上安装NginxUbuntuCentOS查看已安装的软件 Ubuntu 在 Ubuntu 上安装 Nginx 非常简单。只需按照以下步骤操作&#xff1a; 打开终端&#xff0c;更新软件包索引&#xff1a; sudo apt update安装 Nginx&#xff1a; sudo apt install nginx安…

2023世界超高清视频产业发展大会博冠8K明星展品介绍

2023世界超高清视频产业发展大会博冠8K明星展品介绍&#xff1a; 一、博冠8K全画幅摄像机B1 这是一款面向广电应用的机型&#xff0c;可适配外场ENG制作轻量化需求&#xff0c;应用于8K单边机位、新闻、专题的拍摄工作&#xff0c;也可应用于体育转播、文艺节目等特殊机位及各…

使用react脚手架初始化项目

1.使用react脚手架初始化项目 1.初始化命令&#xff0c;&#xff08;create-react-app脚手架的名称&#xff0c;my-app项目名称&#xff09; npx create-react-app my-app2.初始化完成之后可以看到Happy hacking&#xff01; 3.启动项目&#xff0c;进去根目录cd my-app &am…

这才是 玩转Github 的正确姿势

这才是 玩转Github 的正确姿势 GitHub各位应该都很熟悉了&#xff0c;全球最大的开源社区&#xff0c;也是全球最大的同性交友网站~~&#xff0c;但是大部分同学使用GitHub应该就是通过别人的开源链接&#xff0c;点进去下载对应的项目&#xff0c;而真正使用Github来查找开源…

RF学习-RF基本概念

射频(RF)指的是无线波的频率在3KHZ~300GHZ&#xff1b; RF系统通常包括以下模块&#xff1a; 本振(LO)放大器(Amplifier)混频器(Mixer)滤波器(Filter)天线(Antenna) RF接收机有如下三种类型&#xff1a; 超外差式接收机(Super heterodyne structure)零中频接收机(Homodyne…

GAN与DCGAN

GAN&#xff1a;生成对抗网络&#xff0c;首先是一个生成模型&#xff0c;区别与之前的辨别模型&#xff0c;对抗体现在生成器与辨别器之间的对抗。 生成器输入的是噪音&#xff0c;通过多层的MLP可以产生图片&#xff0c;将产生的图片和真实图片输入到辨别器&#xff0c;辨别器…

AI绘画5大免费工具

AI现在最火爆的两个方向一个是以ChatGPT为主导的文本生成工具&#xff0c;还有一个就是以Midjourne为主导的文本生成图片工具。 Midjourne 现在基本是都是需要收费的&#xff0c;但确实Midjourne的效果是顶尖的&#xff0c;如果我们只是想试一下 文本生图的过程&#xff0c;这里…