15. 实现业务功能--帖子操作

1. 集成编译器

editor.md 支持 MarkDown 语法编辑,在需要用户输⼊内容的页面按以下代码嵌入编辑器

1.1 编写 HTML

<!-- 引⼊编辑器的CSS -->
<link rel="stylesheet" href="./dist/editor.md/css/editormd.min.css">
<!-- 引⼊编辑器JS -->
<script src="./dist/editor.md/editormd.min.js"></script>
<script src="./dist/editor.md/lib/marked.min.js"></script>
<script src="./dist/editor.md/lib/prettify.min.js"></script>
<script src="./dist/libs/tinymce/tinymce.min.js" defer></script>
<!-- 需要初始化编辑器的DIV -->
<div id="edit-article"><!-- textarea也是⼀个表单控件,当在editor.md中编辑好的内容会关联这个⽂本域上 --><textarea id="article_post_content" style="display: none;"></textarea>
</div>

1.2 编写 JS

var editor = editormd("edit-article", {width: "100%",height: "100%",// theme : "dark",// previewTheme : "dark",// editorTheme : "pastel-on-dark",codeFold: true,//syncScrolling : false,saveHTMLToTextarea: true, // 保存 HTML 到 TextareasearchReplace: true,watch : true, // 关闭实时预览htmlDecode: "style,script,iframe|on*", // 开启 HTML 标签解析,为了安
全性,默认不开启 // toolbar : false, //关闭⼯具栏// previewCodeHighlight : false, // 关闭预览 HTML 的代码块⾼亮,默认开启emoji: true,taskList: true,tocm: true, // Using [TOCM]tex: true, // 开启科学公式TeX语⾔⽀持,默认关闭// flowChart: true, // 开启流程图⽀持,默认关闭// sequenceDiagram: true, // 开启时序/序列图⽀持,默认关闭,placeholder: '开始创作...', // 占位符path: "./dist/editor.md/lib/"
});

2. 发布帖子

2.1 实现逻辑

1. 用户点击发布新帖按钮,进入发贴页面

2. 选择版块,填入标题、正文后提交服务器

 

3. 服务器校验信息,并写入数据库

4. 更新用户发帖数与版块贴子数

5. 返回结果 

要对帖子表、用户表、板块表同时进行操作,就需要通过事务进行管理。 

2.2 参数要求

参数名描述类型默认值条件
boardId版块 Idlong必须
title文章标题String必须
content帖子内容String必须

作者 Id 需要从 Session 中获取(即当前的登录用户)。

2.3 在 UserExtMapper.xml 中编写 SQL 语句

<!-- 更新用户的发帖数 --><update id="updateArticleCount" parameterType="java.lang.Long">update t_user set articleCount = articleCount + 1,updateTime = now() where id = #{id,jdbcType=BIGINT}</update>

2.4 创建 Service 接口

在 IUserService 定义方法:
    /*** 贴子数增加1* @param id* @return*/void addOneArticleCountById(Long id);
在 IBoardService 定义方法:
    /*** 贴子数增加1* @param id* @return*/void addOneArticleCountById(Long id);

在 IArticleService 定义方法:

使用事务管理,加入 @Transactional 注解

 

    /*** 发布帖⼦* @param article 帖⼦信息*/// 事务管理@Transactionalvoid create(Article article);

在这个方法中,需要对三个表进行更新操作,因此需要通过事务进行管理。如果在执行过程中抛出异常,那么事务将会被自动回滚。

2.5 实现 Service 接口

在 IBoradService.java 中实现以下方法:

 @Overridepublic void addOneArticleCountById(Long id) {// 非空检验if(id == null || id <= 0){// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 查询现有的用户信息User user = selectById(id);// 校验用户是否存在if (user == null) {// 打印日志log.info(ResultCode.FAILED_USER_NOT_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}// 构造要更新的对象User updateUser = new User(); updateUser.setId(user.getId()); // 用户IdupdateUser.setArticleCount(user.getArticleCount() + 1); //帖子数量+1updateUser.setUpdateTime(new Date());// 更新时间// 调用 DAOint row = userMapper.updateByPrimaryKeySelective(updateUser);if(row != 1){// 打印日志log.warn(ResultCode.ERROR_SERVICES.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));}}

在 BoardServiceImpl.java 中实现以下方法:

@Overridepublic void addOneArticleCountById(Long id) {// 非空检验if(id == null || id <= 0){// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 查询板块信息Board board = selectById(id);// 检验版块是否存在if(board == null){// 打印日志log.warn(ResultCode.FAILED_BOARD_NOT_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_BOARD_NOT_EXISTS));}// 构造要更新的对象Board updateBoard = new Board();updateBoard.setId(board.getId()); // 版块IdupdateBoard.setArticleCount(board.getArticleCount() + 1); //帖子数量updateBoard.setUpdateTime(new Date());// 更新时间// 调用 DAOint row = boardMapper.updateByPrimaryKeySelective(updateBoard);}

2.6 测试

在以上的实现方法写好后,编写测试代码:

在 UserServiceImplTest.java 文件中:

@Test@Transactionalvoid addOneArticleCountById() {userService.addOneArticleCountById(1l);System.out.println("更新成功");userService.addOneArticleCountById(2l);System.out.println("更新成功");}

在 BoardServiceImplTest.java 中:

    @Testvoid addOneArticleCountById() {boradService.addOneArticleCountById(1l);System.out.println("更新成功");boradService.addOneArticleCountById(2l);System.out.println("更新成功");boradService.addOneArticleCountById(55l);System.out.println("更新成功");}

加了事务的注解后,测试的结果不在持久化到数据库,当测试通过后,写入的数据会被回滚。 

    @Testvoid create() {Article article = new Article();article.setBoardId(1l);article.setUserId(1l);article.setTitle("单元测试标题");article.setContent("单元测试内容");// 调用servicearticleService.create(article);System.out.println("写入成功");}

 测试成功:

2.7 实现 Controller

@ApiOperation("发布帖子")@PostMapping("/create")public AppResult create(HttpServletRequest request,@ApiParam("版块Id") @RequestParam("boardId") @NonNull Long boardId,@ApiParam("帖子标题") @RequestParam("title") @NonNull String title,@ApiParam("帖子正文") @RequestParam("content") @NonNull String content){// 获取用户信息HttpSession session = request.getSession(false);User user =(User)session.getAttribute(AppConfig.SESSION_USER_KEY);// 校验用户状态if(user.getState() == 1){// 用户已禁言,返回提示return AppResult.failed(ResultCode.FAILED_USER_BANNED);}// 构造帖子对象Article article = new Article();article.setUserId(user.getId()); // 当前登录用户就是作者article.setBoardId(boardId); // 版块Idarticle.setTitle(title); // 帖子标题article.setContent(content); // 帖子正文// 调用 ServicearticleService.create(article);// 返回结果return AppResult.success("贴子发布成功");}

2.8 实现前端界面

// 构造帖子对象let postData = {boardId : boardIdEl.val(),title : titleEl.val(),content : contentEl.val()};// 提交, 成功后调用changeNavActive($('#nav_board_index'));回到首页并加载帖子列表// contentType: 'application/x-www-form-urlencoded'$.ajax({type : 'post',url : 'article/create',contentType : 'application/x-www-form-urlencoded',data : postData,// 成功回调success: function(respData){if(respData.code == 0){// 成功后跳转到首页changeNavActive($('#nav_board_index'));}else{// 失败$.toast({heading : '警告',text : respData.message,icon : 'Warning'}); }},// 失败回调error: function(){$.toast({heading : '错误',text : '出错了,请联系管理员',icon : 'error'});}

3. 帖子详情

3.1 实现逻辑

1. 用户点击帖子,将帖子 Id 做为参数向服务器发送请求
2. 服务器查询帖子信息
3. 帖子访问次数加1
4. 返回查询结果

那么此时的操作有一个查询,一个更新需要用事务进行管理吗?

答:只对一条记录进行更新时,不需要事务。

在帖子详情中,必须包含帖子的全部信息。

3.2 创建扩展 Mapper.xml

在 ArticleExtMapper.xml 中添加SQL:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.ArticleMapper"><!--  定义表关系的结果集映射  --><resultMap id="AllInfoResultMap" type="com.example.demo.model.Article" extends="ResultMapWithBLOBs"><!--    关联User对象  --><association property="user" resultMap="com.example.demo.dao.UserMapper.BaseResultMap" columnPrefix="u_"/><!--    关联Board对象  --><association property="board" resultMap="com.example.demo.dao.BoardMapper.BaseResultMap" columnPrefix="b_"/></resultMap><!--  查询所有的帖子集合  --><select id="selectAll" resultMap="AllInfoResultMap">selectu.id as u_id,u.nickname as u_nickname,u.gender as u_gender,u.avatarUrl as u_avatarUrl,a.id,a.boardId,a.userId,a.title,a.visitCount,a.replyCount,a.likeCount,a.state,a.deleteState,a.createTime,a.updateTimefrom t_article as a ,t_user as uwhere a.userId = u.idand a.deleteState = 0order by a.createTime desc</select><!--  查询所有的帖子集合  --><select id="selectByBoardId" resultMap="AllInfoResultMap">selectu.id as u_id,u.nickname as u_nickname,u.gender as u_gender,u.avatarUrl as u_avatarUrl,a.id,a.boardId,a.userId,a.title,a.visitCount,a.replyCount,a.likeCount,a.state,a.deleteState,a.createTime,a.updateTimefrom t_article as a ,t_user as uwhere a.userId = u.idand a.deleteState = 0and a.boardId = #{boardId,jdbcType=BIGINT}order by a.createTime desc</select><!--  根据帖子Id 查询帖子详情  --><select id="selectById" resultMap="AllInfoResultMap" parameterType="java.lang.Long">selectu.id as u_id,u.nickname as u_nickname,u.gender as u_gender,u.avatarUrl as u_avatarUrl,b.id as b_id,b.name as b_name,a.id,a.boardId,a.userId,a.title,a.visitCount,a.replyCount,a.likeCount,a.state,a.deleteState,a.createTime,a.updateTimefrom t_article as a ,t_user as u,t_board bwhere a.userId = u.idand a.boardId = b.idand a.id = #{id,jdbcType=BIGINT}and a.deleteState = 0</select>
</mapper>

3.3 修改 DAO

在 dao 包下的 ArticleMapper 中添加方法声明:
    /*** 根据帖子Id 查询帖子详情* @param id* @return*/Article selectById(@Param("id") Long id);

3.4 创建 Service 接口

在 IArticleService 定义方法:
    /*** 根据帖子Id 查询帖子详情* @param id* @return*/Article selectById(Long id);

3.5 实现 Service 接口

在 ArticleServiceImpl 中实现方法:
 @Overridepublic Article selectById(Long id) {// 非空检验if(id == null || id <= 0){// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 调用 DAOArticle article = articleMapper.selectById(id);// 返回结果return article;}

3.6 测试

@Testvoid selectById() throws JsonProcessingException {Article article = articleService.selectById(1l);System.out.println(objectMapper.writeValueAsString(article));article = articleService.selectById(8l);System.out.println(objectMapper.writeValueAsString(article));article = articleService.selectById(100l);System.out.println(objectMapper.writeValueAsString(article));}

测试结果:

3.7 实现 Controller

在 ArticleController 中提供对外的API接口:
@ApiOperation("根据Id查询帖⼦详情")@GetMapping("/getById")public AppResult<Article> getDetails(@ApiParam("帖⼦Id")@RequestParam("id") @NonNull Long id) {// 调⽤Service层获取帖⼦详情Article article = articleService.selectById(id);// 校验if (article == null) {return AppResult.failed("帖子不存在");}// 返回成功信息return AppResult.success(article);}

 

3.8 实现前端界面

$.ajax({type : 'get',url : '/article/getById?id=' + currentArticle.id,// 成功回调success: function(respData){if(respData.code == 0){// 把查询到的数据设置到页面上initArticleDetails(respData.data);}else{// 失败$.toast({heading : '警告',text : respData.message,icon : 'Warning'}); }},// 失败回调error: function(){$.toast({heading : '错误',text : '出错了,请联系管理员',icon : 'error'});}});

 

 

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

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

相关文章

Linux服务器中创建SVN项目详细步骤

一、Linux服务器中的SVN安装和搭建项目环境可以参考一下文章: 1、《阿里云服务器搭建》------搭建SVN服务 2、在一个服务器的svn上&#xff0c;设置一个端口号对应一个项目 3、如何解决Linuxsvn无法显示日志的问题 二、Linux服务器中的SVN项目如何添加项目的忽略文件&#xff1…

Rabbitmq的消息转换器

Spring会把你发送的消息序列化为字节发送给MQ&#xff0c;接收消息的时候&#xff0c;还会把字节反序列化为Java对象 ,只不过&#xff0c;默认情况下Spring采用的序列化方式是JDK序列化。众所周知&#xff0c;JDK序列化存在下列问题&#xff1a; 数据体积过大 有安全漏洞 可读…

nacos Error to process server push response

nacos2.0.3报错&#xff1a; Error to process server push response 解决办法&#xff1a; 排查项目当中有没有直接或间接依赖reflections&#xff1a; <dependency><groupId>org.reflections</groupId><artifactId>reflections</artifactId>…

华为配置聚合vlan(Super vlan--Sub vlan)

聚合vlan&#xff0c;Aggregation vlan&#xff0c;也称Super vlan&#xff0c;可以实现用Sub vlan二层隔离广播域&#xff0c;但又将这些Sub vlan聚合使用同一IP子网和网关的情况。 这样&#xff0c;多个Sub-VLAN共享一个网关地址&#xff0c;节约了子网号、子网定向广播地址、…

部署问题集合(二十一)从零开始搭建一台NAS服务器(Linux虚拟机)

前言 因工作需要&#xff0c;需要从零通过虚拟机搭建一台NAS服务器&#xff0c;以此记录下来 步骤 1、创建虚拟机 通过VMWare创建一台新虚拟机&#xff0c;虚拟机内存和磁盘自定义&#xff0c;不过建议尽量大一点 2、服务器端配置 查看是否安装有NFS服务&#xff1a;rpm …

TensorFlow-slim包进行图像数据集分类---具体流程

TensorFlow中slim包的具体用法 1、训练脚本文件&#xff08;该文件包含数据下载打包、模型训练&#xff0c;模型评估流程&#xff09;3、模型训练1、数据集相关模块&#xff1a;2、设置网络模型模块3、数据预处理模块4、定义损失loss5、定义优化器模块 本次使用的TensorFlow版本…

open cv快速入门系列---数字图像基础

目录 一、数字图像基础 1.1 数字图像和图像单位 1.2 区分图片分辨率与屏幕分辨率 1.3 图像的灰度与灰度级 1.4 图像的深度 1.5 二值图像、灰度图像与彩色图像 1.6 通道数 二、数字图像处理 2.1 图像噪声及其消除 2.2 数字图像处理技术 2.2.1 图像变换 2.2.2 图像增强…

爬虫逆向实战(二十七)--某某招标投标网站招标公告

一、数据接口分析 主页地址&#xff1a;某网站 1、抓包 通过抓包可以发现数据接口是page 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现&#xff0c;请求参数是一整个密文 请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 通…

springboot集成es 插入和查询的简单使用

第一步&#xff1a;引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId><version>2.2.5.RELEASE</version></dependency>第二步&#xff1a;…

TypeScript的变量声明的各种方式

TypeScript是一种静态类型的JavaScript超集&#xff0c;它为JavaScript代码提供了类型检查和更好的代码组织结构。在TypeScript中&#xff0c;变量声明是非常重要的&#xff0c;因为它们定义了变量的类型和范围。本文将详细介绍TypeScript的变量声明&#xff0c;并通过代码案例…

Tomcat安装及基本使用

1. 什么是Web服务器 Web服务器是一种应用程序&#xff08;软件&#xff09;&#xff0c;它封装了对HTTP协议的操作&#xff0c;使得开发人员无需直接操作协议&#xff0c;从而简化了Web开发。其主要功能是提供网上信息浏览服务。 Web服务器安装在服务器端&#xff0c;我们可以…

C++ 异常

一、异常概念 异常是一种处理错误的方式&#xff0c;当一个函数发现自己无法处理的错误时就可以抛出异常&#xff0c;让函数的直接或间接 的调用者处理这个错误。 throw: 当问题出现时&#xff0c;程序会抛出一个异常。这是通过使用 throw 关键字来完成的。 catch: 在您想要…

L1-043 阅览室(Python实现) 测试点全过

题目 天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时&#xff0c;管理员输入书号并按下S键&#xff0c;程序开始计时&#xff1b;当读者还书时&#xff0c;管理员输入书号并按下E键&#xff0c;程序结束计时。书号为不超过1000的正整数。当管理员将0作为书号…

国际腾讯云账号云服务器网络访问丢包问题解决办法!!

本文主要介绍可能引起云服务器网络访问丢包问题的主要原因&#xff0c;及对应排查、解决方法。下面一起了解腾讯云国际云服务器网络访问丢包问题解决办法&#xff1a; 可能原因 引起云服务器网络访问丢包问题的可能原因如下&#xff1a; 1.触发限速导致 TCP 丢包 2.触发限速导致…

linux下vi或vim操作Found a swap file by the name的原因及解决方法--九五小庞

在linux下用vi或vim打开Test.java文件时 [rootlocalhost tmp]# vi Test.java出现了如下信息&#xff1a; E325: ATTENTION Found a swap file by the name ".Test.java.swp" owned by: root dated: Wed Dec 7 13:52:56 2011 file name: /var/tmp/Test.java modif…

Hystrix: Dashboard流监控

接上两张服务熔断 开始搭建Dashboard流监控 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…

华为复合vlan(mux vlan)

一、概念&#xff1a; Multiplex vlan&#xff1a;实现网络资源控制的的机制。 / Principle vlan&#xff1a;port 可以和mux vlan内所有接口进行通信&#xff0c;限制128个 < /Separate vlan&#xff1a;隔离型从vlan&#xff0c;只能和…

Git 简单介绍

Git 是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。 一、Git 安装 windows安装&#xff1a;进入网站 https://git-scm.com/ 安装&#xff0c;ubuntu配置&#xff1a;apt install git。当前于 Win 下已安装 Git 版本 2.40.1。 二、配置 设…

一台服务器上部署 Redis 伪集群

哈喽大家好&#xff0c;我是咸鱼 今天这篇文章介绍如何在一台服务器&#xff08;以 CentOS 7.9 为例&#xff09;上通过 redis-trib.rb 工具搭建 Redis cluster &#xff08;三主三从&#xff09; redis-trib.rb 是一个基于 Ruby 编写的脚本&#xff0c;其功能涵盖了创建、管…

flutter高德地图大头针

1、效果图 2、pub get #地图定位 amap_flutter_map: ^3.0.0 amap_flutter_location: ^3.0.0 3、上代码 import dart:async; import dart:io;import package:amap_flutter_location/amap_flutter_location.dart; import package:amap_flutter_location/amap_location_option…