基于 Spring Boot 博客系统开发(六)

基于 Spring Boot 博客系统开发(六)

本系统是简易的个人博客系统开发,为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。🌿🌿🌿
基于 Spring Boot 博客系统开发(五)👈👈

文章详情页实现

在Controller类中,编写处理HTTP请求的方法来获取文章详情并返回视图。
HomeController.java

	@RequestMapping("/article/{id}")
    public String article(@PathVariable Long id,Model model){
        Article article = articleService.getById(id);
        if(article == null){
            return "error/404";
        }
        model.addAttribute("article",article);
        return "client/article";
    }

修改视图中代码。article.html

<title th:text="${article.title}">函数式接口</title>
    <article class="main-content post-page">
        <div class="post-header">
            <h1 class="post-title" itemprop="name headline" th:text="${article.title}">函数式接口</h1>
            <div class="post-data">
                <time datetime="2018-12-01" itemprop="datePublished"  >发布于 [[${article.created}]]</time>
            </div>
        </div>
        <br />
        <div id="post-content" class="post-content content" th:utext="${@textUtils.md2Html(article.content)}"></div>
    </article>

渲染后效果
在这里插入图片描述

文章评论实现

评论用户登录渲染

用户评论前需要进行登录

<span th:if="${@loginUtils.isLogin()}" class="response">
     Hello,<a data-no-instant="" th:text="${@loginUtils.getLoginUser().username}">admin</a>
     如果你想 <a href="/logout">注销</a> ?
</span>
<span th:unless="${@loginUtils.isLogin()}" class="response">
        用户想要评论,请先<a href="/login" title="登录" target="_blank" data-no-instant="">登录</a>!
</span>

LoginUtils.java

@Component
public class LoginUtils {

    @Autowired
    public HttpServletRequest request;

    public boolean isLogin(){
        Object loginUser = request.getSession().getAttribute("loginUser");
        return loginUser!=null;
    }

    public User getLoginUser(){
        Object loginUser = request.getSession().getAttribute("loginUser");
        if(loginUser instanceof User){
            return (User)loginUser;
        }
        return null;
    }
}

用户登录前渲染效果:
在这里插入图片描述
用户登录后渲染效果:
在这里插入图片描述

评论列表渲染

创建CommentController.java,查询指定文章ID的评论列表并分页,以JSON格式返回。
这里注意要写@ResponseBody

@Controller
@RequestMapping("/comment")
public class CommentController {

    @Autowired
    private ICommentService commentService;

    @RequestMapping("/list")
    @ResponseBody
    public PageInfo<Comment> list(Long articleId,@RequestParam(defaultValue = "1") Integer pageNum){
        PageHelper.startPage(pageNum,3);
        QueryWrapper<Comment> query = new QueryWrapper<>();
        query.eq("article_id",articleId);
        List<Comment> list = commentService.list(query);
        PageInfo<Comment> page = new PageInfo<>(list);
        return page;
    }
}

前端代码,需要引入JQ。由于之前有统一引入到公共JS里了,所以这里不需要引入。
引入JQ

<script src="/assets/js/jquery.min.js"></script>

HTML中添加文章ID

 <form id="comment-form" class="comment-form" role="form" >
       <input type="hidden" name="articleId" id="aid" th:value="${article.id}">
       <textarea name="content" id="textarea" class="form-control" placeholder="以上信息可以为空,评论不能为空哦!" required="required" minlength="5" maxlength="2000"></textarea>
       <button type="button" class="submit" id="misubmit">提交</button>
</form>

编写渲染评论列表的JS脚本。这里没有使用模板技术,采用原生文本拼接。

 <script type="text/javascript">
        function loadComment(pageNum){
            $.ajax({
                type: 'get',
                url: '/comment/list',
                data: {articleId:$("#aid").val(),pageNum:pageNum},
                async: true,
                dataType: 'json',
                success: function (result) {
                    console.log(result)
                    let templates = '';
                    $.each(result.list,function (i,o){
                        // 渲染模板
                       templates += '<li id="li-comment-15" class="comment-body comment-parent comment-odd">\n' +
                            '                                <div id="comment-15">\n' +
                            '                                    <div class="comment-view" οnclick="">\n' +
                            '                                        <div class="comment-header">\n' +
                            '                                            <!--设置人物头像和名称-->\n' +
                            '                                            <img class="avatar" src="/assets/img/avatars.jpg" height="50">\n' +
                            '                                            <a class="comment-author" rel="external nofollow">'+o.author+'</a>\n' +
                            '                                        </div>\n' +
                            '                                        <!-- 评论内容 -->\n' +
                            '                                        <div class="comment-content">\n' +
                            '                                            <span class="comment-author-at"></span>\n' +
                            '                                            <p></p><p>'+o.content+'</p>\n' +
                            '    <p></p>\n' +
                            '                                        </div>\n' +
                            '                                        <!-- 评论日期 -->\n' +
                            '                                        <div class="comment-meta">\n' +
                            '                                            <time class="comment-time">'+o.created+'</time>\n' +
                            '\n' +
                            '                                        </div>\n' +
                            '                                    </div>\n' +
                            '                                </div>\n' +
                            '                            </li>';
                    })
                    $(".comment-list").html(templates);

                    let pageText = '';
                    $.each(result.navigatepageNums,function (i,o){
                        pageText +=
                            '<li class="'+(o==result.pageNum?'current':'')+'">' +
                            '<a>'+o+'</a>' +
                            '</li>';
                    });
                    $(".page-navigator").html(pageText);
                    $(".page-navigator a").click(function (){
                        let pageNum = $(this).text();
                        loadComment(parseInt(pageNum));
                    });
                }
            });
        }
        loadComment(1);
    </script>

渲染效果:
在这里插入图片描述

评论提交实现

后端 CommentController 添加评论方法

@Controller
@RequestMapping("/comment")
@Slf4j
public class CommentController {

    @Autowired
    private ICommentService commentService;

    @RequestMapping("/list")
    @ResponseBody
    public PageInfo<Comment> list(Long articleId,@RequestParam(defaultValue = "1") Integer pageNum){
        PageHelper.startPage(pageNum,3);
        QueryWrapper<Comment> query = new QueryWrapper<>();
        query.eq("article_id",articleId);
        List<Comment> list = commentService.list(query);
        PageInfo<Comment> page = new PageInfo<>(list);
        return page;
    }

    @Autowired
    private LoginUtils loginUtils;

    @PostMapping("/add")
    @ResponseBody
    public AjaxResult add(Comment comment, HttpServletRequest request){
        comment.setCreated(new Date()); //实体created 属性修改成Date类型
        comment.setIp(request.getRemoteAddr());
        User loginUser = loginUtils.getLoginUser();
        if(loginUser == null){
            return new AjaxResult(-1,"请先登录");
        }
        comment.setAuthor(loginUser.getUsername());
        try {
            commentService.save(comment);
            return AjaxResult.success();
        }catch (Exception e){
            log.error(e.getMessage());
        }
       return  AjaxResult.error();
    }

}

创建AjaxResult 用于返回异步状态结果
AjaxResult.java

@Data
public class AjaxResult {

    private int code = 0;
    private String msg ="操作成功" ;
    private Object data;

    public AjaxResult() {
    }

    public AjaxResult(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public AjaxResult(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public static AjaxResult success(){
        return new AjaxResult();
    }
    public static AjaxResult error(){
        return new AjaxResult(-1,"未知错误");
    }
}

前端提交的HTML

  <div>
        <form id="comment-form" class="comment-form" role="form"  >
             <input type="hidden" name="articleId" id="aid" th:value="${article.id}">
             <textarea name="content" id="textarea" class="form-control" placeholder="以上信息可以为空,评论不能为空哦!" required="required" minlength="5" maxlength="2000"></textarea>
             <button type="button" class="submit" id="misubmit">提交</button>
        </form>
  </div>

提交评论的JS脚本

 $("#misubmit").click(function (){

                $.ajax({
                    type: 'post',
                    url: '/comment/add',
                    data: {articleId:$("#aid").val(),content:$("#textarea").val()},
                    async: false,
                    dataType: 'json',
                    success: function (result) {
                        if(result.code == 0){
                            alert("评论成功");
                            window.location.reload();
                        }else{
                            alert(result.msg)
                        }
                    }
                });
            });
成功提交评论效果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

适合打工人的赚钱软件有哪些?盘点5个实用的赚钱软件(真实靠谱)

在这个互联网时代&#xff0c;手机不仅仅是我们的通讯工具&#xff0c;更是我们赚钱的小助手。今天&#xff0c;就让我带你一探究竟&#xff0c;揭秘那些真实靠谱的赚钱软件&#xff0c;让你在家也能轻松赚钱&#xff01; 一、抖音极速版&#xff1a;刷视频也能赚钱 抖音极速版…

Flutter笔记:Widgets Easier组件库(11)- 使用提示吐丝

Flutter笔记 Widgets Easier组件库&#xff08;11&#xff09;使用提示吐丝 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this …

【前端学习——网络相关】浏览器同源策略和跨域

浏览器的同源策略 为什么要有&#xff1f; 帮助阻隔恶意文档&#xff0c;减少可能被攻击的媒介。&#xff08;就是为了安全&#xff09; 如果非同源&#xff0c;共有三种行为受到限制 &#xff08;1&#xff09; Cookie、LocalStorage 和 IndexDB 无法读取。 &#xff08;2…

央视影音 视频下载 2

浏览器猫抓插件&#xff0c;拿到视频地址&#xff0c;这个地址的播放不正常&#xff0c;花屏。https://dh5.cntv.qcloudcdn.com/asp/h5e/hls/2000/0303000a/3/default/6edd15a0ebb3467993bec51a95be0e22/2000.m3u8 改一下地址&#xff0c;把代码中的h5e去掉。网址改为https://…

解决MySQL进行group by 字段返回大量异常结果

目录 问题 原因 解决方案 问题 看这条sql CH2O这个字段的取值只有1&#xff0c;2&#xff0c;3&#xff0c;正常进行group by 分类累加统计返回结果应该是这样&#xff1a; [{"CH2O": 2.0,"insufficient_weight": 142,"Normal_Weight": 164…

锁相环原理解析

在计算机和嵌入式系统中&#xff0c;常常要用锁相环来倍频&#xff0c;那么&#xff0c;锁相环是如何倍频的&#xff0c;其原理又是什么呢&#xff1f; 目录 1. 锁相环基本概念与构成1.1 鉴相器1.2 低通滤波器1.3 压控振荡器 2. 锁相环如何实现倍频3. 锁相环也会失效&#xff…

基于springboot+vue+Mysql的租房网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

[C++核心编程-01]----C++内存四区详细解析

前言 当程序运行时&#xff0c;操作系统会为程序分配一块内存空间&#xff0c;这块内存空间被划分为不同的区域&#xff0c;每个区域有其独特的作用和管理方式。四个区域分别为&#xff1a;堆、栈、全局/静态存储区和常量存储区。每个区域都有不同的作用和特点&#xf…

夏目友人帐所有妖怪名单

夏目友人帐妖怪名单 夏目友人帐 第一季 2008.07.07第1话&#xff1a;猫和友人帐 / 猫と友人帐 菱垣 狞影 斑第2话&#xff1a;露神之祠 / 露神の祠 露神 濯第3话&#xff1a;八原的怪人 / 八ツ原の怪人 一只目 牛头&#xff08;中级妖怪&#xff09;第4话&#xff1a;时雨与少女…

PHP源码_众筹商城

众筹商城源码 众筹商品平台 商城加共识元富之路 网上商城众筹 前端是编译后的&#xff0c;后端PHP&#xff0c;带商城 运行截图 源码贡献 https://githubs.xyz/boot?app39 部分数据库表 CREATE TABLE ti_shopro_store (id int(11) NOT NULL AUTO_INCREMENT COMMENT ID,nam…

英语复习之英语形近词总结(二)

接着总结形近词 单词释义例句 impress 英 /ɪmˈpres/ 美 /ɪmˈpres/ vt.盖印&#xff1b;强征&#xff1b;传送&#xff1b;给予某人深刻印象 vi.给人印象。印象&#xff0c;印记&#xff1b;特征&#xff0c;痕迹 1.It didnt impress me as a good place to live. 那地方…

基于openEuler22.03 LTS环境的docker容器基础

一、说明 本文配置环境为VMware虚拟机或华为云服务器&#xff08;4核CPU&#xff0c;8 GB内存&#xff0c;40GB磁盘&#xff09;&#xff0c;OS为openEuler 22.03 LTS &#xff0c;Linux服务器要求能联网。 二、安装docker 2.1 安装docker软件包 [rootnode01 ~]# dnf -y in…

电机控制系列模块解析(15)—— 母线小电容

一、薄膜电容 在家电产品和工业变频器中&#xff0c;使用容值更小但耐压更高的薄膜电容来代替传统的电解电容作为逆变器母线电容&#xff0c;这种技术趋势已经得到了广泛应用和产品化。以下是关于这一替换技术的一些关键考量和优势&#xff1a; 长期稳定性与可靠性&#xff1a…

3-qt综合实例-贪吃蛇的游戏程序

引言&#xff1a; 如题&#xff0c;本次实践课程主要讲解贪吃蛇游戏程序。 qt贪吃蛇项目内容&#xff1a; 一、功能需求 二、界面设计 各组件使用&#xff1a; 对象名 类 说明 Widget QWidge 主窗体 btnRank QPushButton 排行榜-按钮 groupBox QGroupBox 难…

牛客NC383 主持人调度(一)【简单 排序 Java/Go/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/e160b104354649b69600803184094adb 思路 直接看代码&#xff0c;不难Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返…

CMakeLists.txt语法规则:控制编译的变量

一. 简介 前面一篇文章学习了 CMakeLists.txt语法中的 部分常量变量&#xff0c;具体学习提供信息的变量。 本文继续学习 CMakeLists.txt语法中&#xff1a;控制编译的变量。 二. CMakeLists.txt语法规则&#xff1a;控制编译的变量 这些变量可以控制编译过程&#xff0c;…

[C语言]指针进阶详解

指针是C语言的精髓所以内容可能会比较多&#xff0c;需要我们认真学习 目录 1、字符指针 2、指针数组 3、数组指针 3.1数组指针的定义 3.2&数组名vs数组名 3.3数组指针的使用 4、数组传参和指针传参 4.1一维数组传参 4.2二维数组传参 4.3一级指针传参 4.4二级指…

【Docker学习】docker run的端口映射-p和-P选项

docker run的端口映射选项分为-p&#xff08;小写&#xff0c;全称--publish&#xff09;&#xff0c;-P&#xff08;大写&#xff0c;全称--publish-all&#xff09;&#xff0c;之前认为只有改变容器发布给宿主机的默认端口号才会进行-p的设置&#xff0c;而不改变默认端口号…

现代信号处理8_递归的最小二乘(CSDN_20240505)

递归的最小二乘大约出现在50年前。递归&#xff0c;就是在已经算出的结果的基础下&#xff0c;当新的数据到来时&#xff0c;不需要再对数据进行一次完整的运算&#xff0c;而是在已有结果的基础上做一些简单的调整&#xff0c;就能得到新的结果。使用递归的好处&#xff1a; …

面试中算法(使用栈实现队列)

使用栈来模拟一个队列&#xff0c;要求实现队列的两个基本操作:入队、出队。 栈的特点&#xff1a;先入后出&#xff0c;出入元素都是在同一端&#xff08;栈顶&#xff09;。 队列的特点&#xff1a;先入先出&#xff0c;出入元素是在两端&#xff08;队头和队尾)。 分析&…