27.<Spring博客系统③(实现用户退出登录接口+发布博客+删除/编辑博客)>

PS:关于打印日志

1.建议在关键节点打印日志。

①请求入口。

②结果响应

2.在可能发生错误的节点打印日志

3.日志不是越多越好。因为打日志也会消耗性能。

日志也可以配置去除重复日志。

一、用户退出功能

判断用户退出。我们只需要在前端将token删掉就可以了。 

由于用户退出功能在每一个页面都会用到。因此我们将这个前端代码写在

common.js中。

function logout(){localStorage.removeItem("user_token");location.href = "blog_login.html";
}

这样就写好了。

二、发布博客功能

2.1后端代码

Controller

    @RequestMapping("/add")public Boolean publishBlog(String title, String content, HttpServletRequest request){log.info("publish,接收参数:title{},content{}",title,content);//1.参数校验//2.获取当前登录用户if(!StringUtils.hasLength(title) ||!StringUtils.hasLength(content)){log.error("title or content为空");return false;}String user_token = request.getHeader(Constant.USER_TOKEN_HEADER);Integer userId = JWTUtils.getUserIdFromToken(user_token);if(userId == null || userId<1){log.error("用户未登录");return false;}BlogInfo blogInfo =new BlogInfo(title,content,userId);Integer result = blogService.publishBlog(blogInfo);if(result < 1){log.error("博客发布失败");return false;}return true;}

Service 

    public Integer publishBlog(BlogInfo blogInfo) {return blogMapper.interBlog(blogInfo);}

 Mapper

    @Insert("insert into blog (title, content, user_id) values (#{title},#{content},#{userId})")Integer interBlog(BlogInfo blogInfo);

测试成功

实现markdown编辑器

editor.md 简单介绍

用户发布博客用到的是一个Markdown编辑器。

editor.md 是一个开源的页面 markdown 编辑器组件.

官网: http://editor.md.ipandao.com/

代码: https://pandao.github.io/editor.md/

使用时引入对应依赖就可以了
"test-editor" 为 markdown编辑器所在的div的id名称path为 editor.md依赖所在的路径

2.2前端代码 

        function submit() {$.ajax({type: "post",url: "/blog/add",data:{title:$("#title").val(),content:$("#content").val(),},success:function(result){if(result.code == 200 && result.data == true){alert("发布成功");location.href = "/blog_list.html";}else{alert("发布失败,标题或正文不能为空!");}}});}

 

发布成功!!!!! 

测试成功!

###标题不能正常显示

但是发现,二级标题。一级标题在点击查看全文中还是##。我们如何处理呢 

将下面两部分代码

        <div class="right"><div class="content"><div class="title"></div><div class="date"></div><div class="detail"></div><div class="operating"> <button onclick="window.location.href='blog_update.html'">编辑</button><button onclick="deleteBlog()">删除</button></div></div>
                if(result.code == 200 && result.data!=null){$(".right .content .title").text(blog.title);$(".right .content .date").text(blog.createTime);$(".right .content .detail").text(blog.content); 

修改为下面内容就可以了

        <div class="right"><div class="content"><div class="title"></div><div class="date"></div><div class="detail" id="detail" style="background-color: transparent;"></div><div class="operating"> <button onclick="window.location.href='blog_update.html'">编辑</button><button onclick="deleteBlog()">删除</button></div></div>
            success:function(result){var blog = result.data;if(result.code == 200 && result.data!=null){$(".right .content .title").text(blog.title);$(".right .content .date").text(blog.createTime);/* $(".right .content .detail").text(blog.content); */editormd.markdownToHTML("detail", {markdown: blog.content,});

修改之后就会发现。我们再点击查看全文。里面的标题就不是##了 。

会正常显示了

这是博客列表显示的 

 这是查看全文显示的

除了查看详情。在博客列表中我们也发现还是存在####。

不但如此。我们还希望。在博客列表中只显示一部分博客。而不是将博客全部显示出来。这个又该怎么操作呢?

这个如何修改呢 

1.去掉特殊符号

2.对内容长度进行处理

①通过SQL截断

②通过Java截断

三、实现编译/删除博客(只能删除编辑自己的)

当登录用户和作者是一个人的时候。才应该有编辑和删除按钮。

首先,我们应该处理。在

1.什么时候显示这个操作按钮。

2.实现这个按钮。

3.1实现博客作者和登录用户一样的时候显示编译删除按钮

判断博客作者和登录用户是否一样

实现方式

解耦考虑1、2

1.提供接口,判断作者和登录用户是否一样

2.提供接口,返回登录用户

由于这个项目简单。我们用第三种方法实现。

3.获取博客详情时,顺带返回

首先在博客实体类中加上一个成员变量

    private Boolean isLoginUser;

接着在Controller中的/getBlogDetail路由方法中获取登录用户。

给它加上。

HttpServletRequest request

这个参数。

1.获取登录信息。

2.判断登录用户是否为作者。 

后端代码实现

    @RequestMapping("getBlogDetail")public BlogInfo queryBlogById(Integer blogId,HttpServletRequest request){log.info("publish,接收参数:blogId{}",blogId);BlogInfo blogInfo = blogService.queryBlogById(blogId);//1.获取登录用户信息//2.判断用户是否为作者String user_token = request.getHeader(Constant.USER_TOKEN_HEADER);Integer userId = JWTUtils.getUserIdFromToken(user_token);if(userId != null && userId == blogInfo.getUserId()){blogInfo.setIsLoginUser(true);}return blogInfo;}

前端代码实现

在获取博客详情的前端代码中添加如下代码 

                    //是否实现编辑/删除按钮if(blog.isLoginUser == true){var findHtml = "";findHtml += '<div class="operating">';findHtml += '<button onclick="window.location.href=\'blog_update.html'+location.search+'\'">编辑</button>';findHtml += '<button onclick="deleteBlog()">删除</button>';findHtml += '</div>';$(".content").append(findHtml);}

注意Boolean和boolean 

如果我们使用的是基本类型的boolean。那么它在

后端代码的写法上和

返回的参数上会与

包装类型Boolean有所区别。

 点击编辑显示原文

测试后发现功能已经实现。不过还有一个问题。点击编辑的时候

显示的是固定的内容而不是我们写过的内容。 

如何修改呢。我们可以写前端代码

(不正规写法)

将这个代码放在blog_update.html中就可以了

        function getBlogInfo() {$.ajax({type: "get",url: "/blog/getBlogDetail"+location.search,success:function(result){if(result.code ==200 && result.data != null){$("#title").val(result.data.title);$("#content").val(result.data.content);$("#title").val(result.data.title);}}});}

不过当我们刷新的时候,会发现又变回原样了。

 这是就是不正规写法会导致的一些错误。那么正规写法是什么样的呢?

正规写法

使用我们Markdown自带的插件的代码填写正文内容

        function getBlogInfo() {$.ajax({type: "get",url: "/blog/getBlogDetail"+location.search,success:function(result){if(result.code ==200 && result.data != null){$("#title").val(result.data.title);/* $("#content").val(result.data.content); */editormd("editor", {width  : "100%",height : "550px",path: "blog-editormd/lib/",onload : function(){this.watch();this.setMarkdown(result.data.content);} });}}});

这样就没有任何问题了 

3.2更新博客功能实现

后端

    /*** 编辑博客*/@RequestMapping("/update")public Boolean update(Integer blogId,String title,String content){log.info("updateBlog,接收到的参数title{},content{}",title,content);if(blogId == null || !StringUtils.hasLength(title) && StringUtils.hasLength(content)){log.error("Id/标题/内容为空或不合法");return false;}BlogInfo blogInfo = new BlogInfo();blogInfo.setId(blogId);blogInfo.setTitle(title);blogInfo.setContent(content);Integer result = blogService.updateBlog(blogInfo);if(result < 1){log.error("更新失败!");return false;}return true;}

前端

        function submit() {$.ajax({type: "post",url: "/blog/update",data: {title: $("#title").val(),content: $("#content").val(),blogId : $("#blogId").val()},success: function (result) {if (result.code == 200 && result.data == true) {alert("更新成功!")location.href = "blog_list.html";} }});}

测试:一下页面

更新成功

3.3删除博客功能实现

后端

    /*** 删除博客*/@RequestMapping("/delete")public Boolean delete(Integer blogId){log.info("删除博客,blogId:{}",blogId);BlogInfo blogInfo = new BlogInfo();blogInfo.setId(blogId);blogInfo.setDeleteFlag(1);Integer result = blogService.updateBlog(blogInfo);if(result < 1){log.error("删除失败!");return false;}return true;}

前端

        function deleteBlog() {if(confirm("确认删除?")){$.ajax({type:"get",url:"/blog/delete"+location.search,success:function(result){if(result.code == 200 && result.data == true){alert("删除成功!");location.href = "blog_list.html";}}});}}

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

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

相关文章

[前端面试]javascript

js数据类型 简单数据类型 null undefined string number boolean bigint 任意精度的大整数 symbol 创建唯一且不变的值&#xff0c;常用来表示对象属性的唯一标识 复杂数据类型 object&#xff0c;数组&#xff0c;函数,正则,日期等 区别 存储区别 简单数据类型因为其大小固定…

uniapp自动注册机制:easycom

传统 Vue 项目中&#xff0c;我们需要注册、导入组件之后才能使用组件。 uniapp 框架提供了一种组件自动注册机制&#xff0c;只要你在 components 文件夹下新建的组件满足 /components/组件名/组件名.vue 的命名规范&#xff0c;就能直接使用。 注意&#xff1a;组件的文件夹…

人工智能与SEO优化中的关键词策略解析

内容概要 在当今数字化快速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;与搜索引擎优化&#xff08;SEO&#xff09;的结合正变得愈发重要。关键词策略是SEO优化的一项基础工作&#xff0c;它直接影响到网站的可见性和流量。通过运用智能算法&#xff0c;企业能…

【异常解决】Linux shell报错:-bash: [: ==: 期待一元表达式 解决方法

博主介绍&#xff1a;✌全网粉丝21W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

卷径计算(基于卷径变化微分方程计算实时卷径)

这里本质是积分法计算实时卷径,PLC里如何实现数值积分器算法请参考下面文章链接: 博途PLC数值积分器(矩形积分和梯形积分法自由切换) 博途PLC数值积分器(矩形梯形积分自由切换)_博图 积分计算-CSDN博客文章浏览阅读505次。本文详细介绍了博途PLC的数值积分器功能,涵盖了矩…

【Mysql】Mysql的多表查询---多表联合查询(上)

1、介绍 多表查询就是同时查询两个或者两个以上的表&#xff0c;因为有的时候&#xff0c;用户在查看数据的时候&#xff0c;需要显示的数据来自多张表&#xff0c;多表查询有以下分类&#xff1a; &#xff08;1&#xff09;交叉连接查询&#xff08;产生笛卡尔积&#xff0…

Shell基础(4)

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

跨平台WPF框架Avalonia教程 十五

ListBox 列表框 列表框从元素源集合中显示多行元素&#xff0c;并允许选择单个或多个。 列表中的元素可以组合、绑定和模板化。 列表的高度会扩展以适应所有元素&#xff0c;除非特别设置&#xff08;使用高度属性&#xff09;&#xff0c;或由容器控件设置&#xff0c;例如…

有序数组的平方(leetcode 977)

一个数组&#xff0c;返回一个所有元素的平方之后依然是一个有序数组。&#xff08;数组中含负数&#xff09; 解法一&#xff1a;暴力解法 所有元素平方后再使用快速排序法重新排序&#xff0c;时间复杂度为O(nlogn)。 class Solution { public:vector<int> sortedSqu…

使用 Go 实现将任何网页转化为 PDF

在许多应用场景中&#xff0c;可能需要将网页内容转化为 PDF 格式&#xff0c;比如保存网页内容、生成报告、或者创建网站截图。使用 Go 编程语言&#xff0c;结合一些现有的库&#xff0c;可以非常方便地实现这一功能。本文将带你一步一步地介绍如何使用 Go 语言将任何网页转换…

ASP.NET 部署到IIS,访问其它服务器的共享文件 密码设定

asp.net 修改上面的 IIS需要在 配置文件 添加如下内容 》》》web.config <system.web><!--<identity impersonate"true"/>--><identity impersonate"true" userName"您的账号" password"您的密码" /><co…

基础IO2

文章目录 磁盘结构磁盘存储结构磁盘的逻辑结构引入文件系统理解文件系统inode 映射 data blocks文件名与inode的关系dentry树文件描述符与进程之间的关系 深刻理解软硬链接软链接硬链接 动静态库静态库1. 手动制作静态库2.调用静态库(1)安装到系统(2)自己指定查找路径(3)自己创…

计算机网络:运输层 —— TCP的流量控制

文章目录 TCP的流量控制TCP的流量控制方法滑动窗口机制持续计时器 TCP的流量控制 当 TCP 客户端持续发送大量数据时&#xff0c;应用程序可能正忙于其他任务&#xff0c;并不一定能够立刻取走数据&#xff0c;这会造成接收方接收缓存的溢出&#xff0c;导致数据丢失。 TCP 为应…

Flink_DataStreamAPI_执行环境

DataStreamAPI_执行环境 1创建执行环境1.1getExecutionEnvironment1.2createLocalEnvironment1.3createRemoteEnvironment 2执行模式&#xff08;Execution Mode&#xff09;3触发程序执行 Flink程序可以在各种上下文环境中运行&#xff1a;我们可以在本地JVM中执行程序&#x…

鸿蒙中如何实现图片拉伸效果

2024年10月22日&#xff0c;华为发布会上&#xff0c;推出鸿蒙5.0。现在加入恰逢时机&#xff0c;你&#xff0c;我皆是鸿蒙时代合伙人。无论为了学习技术&#xff0c;还是为了谋福利&#xff0c;在鸿蒙的浩瀚海洋中分到一杯羹。现在学习鸿蒙正当时。 一文了解鸿蒙中图片拉伸的…

Unity 2022 Nav Mesh 自动寻路入门

untiy 2022 window-PackageManager-AINavigation 安装 Install 2.创建一个空物体命名Nav&#xff0c;在其自身挂载 NavMeshSurface 然后点击bake 烘焙地形即可 3.创建palyer和怪物 怪物AI代码 using System.Collections; using System.Collections.Generic; using UnityEngi…

基于gradio+networkx库对图结构进行可视化展示

前言 在gradio框架下对蛋白质-蛋白质相互作用网络&#xff08;PPI网络&#xff09;进行可视化&#xff0c;并将其在网页前端进行展示。 方法 其实很简单 可以直接使用networkx画图后保存图片&#xff0c;然后使用Gradio框架的image组件进行展示即可。 但实际上gradio还配置…

MSTP知识点

多生成树协议 在 MSTP&#xff08;Multiple Spanning Tree Protocol&#xff09;中&#xff0c;根桥&#xff08;root&#xff09;、指定端口&#xff08;designated port&#xff09;、备用端口&#xff08;alternate port&#xff09;等角色都是确保网络中没有循环并且流量能…

为正在运行的 Docker 容器重启策略,以提高服务的可用性

为正在运行的 Docker 容器重启策略,以提高服务的可用性。 为正在运行的 Docker 容器添加 --restartalways –restartalways 是 Docker 中一个常用的参数&#xff0c;用来设置容器的重启策略。它的作用是确保容器在一定条件下能够自动重启&#xff0c;以提高服务的可用性。 方…

后台管理系统(开箱即用)

很久没有更新博客了&#xff0c;给大家带上一波福利吧,大佬勿扰 现在市面上流行的后台管理模板很多,若依,芋道等,可是这些框架对我们来说可能会有点重,所以我自己从0到1写了一个后台管理模板,你们使用时候可扩展性也会更高 项目主要功能: 成员管理&#xff0c;部门管理&#…