博客系统(升级(Spring))(四)(完)基本功能(阅读,修改,添加,删除文章)(附带项目)

博客系统 (三)

  • 博客系统
  • 博客主页
    • 前端
    • 后端
    • 个人博客
      • 前端
      • 后端
        • 显示个人文章
        • 删除文章
    • 修改文章
      • 前端
      • 后端
        • 提取文章
        • 修改文章
      • 显示正文内容
        • 前端
        • 后端
        • 文章阅读量功能
  • 添加文章
    • 前端
    • 后端
  • 如何使用Redis
  • 项目地点:

博客系统

博客系统是干什么的?
CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博客系统,这是一个较为简单的博客系统,但是主要功能一个不缺,不过就是 UI 有些 low,我学习前端是为了写后端更加顺手。不至于前后端完全分离,但是有个问题设计的 web 页面不是很好看。

首先我将整体的业务流程展现
在这里插入图片描述
我们继博客系统(二)继续,编写,到了主页的业务逻辑了

接下来的流程是通过,网页端,后端统一数据结构交互的数据结构。

博客主页

前端

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>博客列表</title><link rel="stylesheet" href="css/list.css"><link rel="stylesheet" href="css/blog_list.css"><link rel="stylesheet" href="css/conmmon.css"></lin><script src="js/jquery.min.js"></script><style>.nav{position: fixed;top: 0;left: 0;right: 0;height: 50px;}.container{padding-top: 80px;height: auto;}.container-right{width: auto;}.blog-pagnation-wrapper{height: 40px;margin: 16px 0;text-align: center;}.blog-pagnation-item{display: inline-block;padding: 8px;border: 1px solid #d0d0d5;color: #333;}.blog-pagnation-item:hover{background: #4e4eeb;color: #fff;}.blog-pagnation-item.actvie{background: #4e4eeb;color: #fff;}</style><script src="js/urluitils.js"></script>
</head><body><!-- 导航栏 --><div class="nav"><img src="img/sleep.jpg" alt=""><span class="title">我的博客系统</span><!-- 用来占据中间位置 --><span class="spacer"></span><a href="blog_list.html">主页</a><a href="blog_add.html">写博客</a><a href="myblog_list.html">我的博客</a><a href="javascript:logout()">注销</a></div><!-- 版心 --><div class="container"><!-- 右侧内容详情 --><div class="container-right" style="width: 100%;"><div id="artListDiv"><!-- 每一篇博客包含标题, 摘要, 时间 --></div><div class="blog-pagnation-wrapper"><button class="blog-pagnation-item" onclick="doFirst()">首页</button> <button class="blog-pagnation-item" onclick="doBefore()">上一页</button>  <button class="blog-pagnation-item" onclick="doNext()">下一页</button><button class="blog-pagnation-item" onclick="doLast()">末页</button>&nbsp; &nbsp; &nbsp; &nbsp;当前在第<span id="pindex"></span>页共:<span id="psize"></span></div></div></div><script>var psize=2;var pindex=1;var totalpage=1;//总页//初始化数据function init(){//得到url中的分页参数psize=getParamValue("psize");if(psize==null){psize=2;}pindex=getParamValue("pindex");if(pindex==null){pindex=1;}jQuery("#pindex").html(pindex);//请求后端接口jQuery.ajax({url:"/article/getlistbypage",type:"get",data:{"pindex":pindex,"psize":psize},success:function(res){if(res.code==200&&res.data!=null){var createHtml="";if(res.data.list!=null&&res.data.list.length>0){//文章totalpage =res.data.list.szie;jQuery("#psize").html(totalpage);var artList=res.data.list;for(var i=0;i<artList.length;i++){var art=artList[i];createHtml+='<div class="blog">';createHtml+='<div class="title">'+art.title+'</div>';createHtml+='<div class="date">'+art.createtime+'</div>';createHtml+='<div class="desc">'+art.content+'</div>';createHtml+=' <a href="blog_content.html?aid='+art.id+'" class="detail">查看全文 &gt;&gt;</a>';createHtml+='</div>';}}else{createHtml+='<h3 style="margin-top:20px;margin-left:20px">暂无文章!</h3>';}jQuery("#artListDiv").html(createHtml);}else{alert("抱歉:查询失败"+res.msg);}}});}init();function doFirst(){//判断是否在首页if(pindex<=1){alert("已经在首页了,不需跳转");return false;}location.href="blog_list.html";}function doLast(){if(pindex>=totalpage){alert("已经在末页了,不需跳转");return false;}location.href="blog_list.html?pindex="+(parseInt(totalpage));}function doBefore(){if(pindex<=1){alert("已经在首页了,不需跳转");return false;}location.href="blog_list.html?pindex="+(parseInt(pindex-1));}function doNext(){if(pindex>=totalpage){alert("已经在末页了,不需跳转");return false;}location.href="blog_list.html?pindex="+(parseInt(pindex+1));}</script>
</body>
</html>

后端

首先在主页中需要注意的是,我在这里添加了分页功能,如何解决分页问题,诺是将整个数据库里的文章全部读取到内存里,对于内存的消耗极大,所以这里我用sql语言中的 limt 语言进行分页读取(不知道的可以看我Mysql的文章)

通过mapper接口调用数据库

@Mapper
public interface ArticleMapper {@Select("select * from articleinfo order by id desc limit #{psize} offset #{offset}")List<Articleinfo> getListByPage(@Param("pszie") int pszie,@Param("offset") int offset);
}

通过service层调用mapper接口

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public List<Articleinfo> getListByPage (int psize,int offset){return articleMapper.getListByPage(psize, offset);} 
}

通过Controller层调用service层方法

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@Resourceprivate ThreadPoolTaskExecutor taskExecutor;public ResultAjax getListByPage(Integer pindex,Integer psize) throws ExecutionException, InterruptedException {if (pindex==null||pindex<1){pindex=1;}if (psize==null||psize<1){psize=1;}Integer finalPsize=psize;int offset=psize*(pindex-1);FutureTask<List<Articleinfo>> listFutureTask=new FutureTask<>(()->{return articleService.getListByPage(finalPsize,offset);});taskExecutor.submit(listFutureTask);FutureTask<Integer> sizeTask=new FutureTask<>(()->{int count= articleService.getCount(); double sizeTemp=((count*1.0)/(finalPsize*1.0));return (int)Math.ceil(sizeTemp);});taskExecutor.submit(sizeTask);List<Articleinfo> articleinfos=listFutureTask.get();int size=sizeTask.get();HashMap<String ,Object> map=new HashMap<>();map.put("list",articleinfos);map.put("szie",size);return ResultAjax.success(map);}
}

解释:

  1. 我在页面中每页所展示两个文章。而 limit finalPsize offset offset 我定位为 finalPsize 为第 几 行,offset 显示几个数据(具体原则在我的myslq 文章中有体现)(LIMIT [位置偏移量,] 行数)
  2. 使用多线程可以避开,有读者写数据,有读者读数据的情况。并且可以以最快速度反应的客户端
  3. 这个线程池Spring提供的,线程池,可以不需要去设置参数。
  4. 第一个线程池用来查找页面每页的内容,第二个线程池用来查找文章的总数。

个人博客

前端

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>博客列表</title><link rel="stylesheet" href="css/conmmon.css"><link rel="stylesheet" href="css/blog_list.css"><script src="js/jquery.min.js"></script><script src="js/logout.js"></script>
</head><body><!-- 导航栏 --><div class="nav"><img src="img/sleep.jpg" alt=""><span class="title">我的博客系统</span><!-- 用来占据中间位置 --><span class="spacer"></span><a href="blog_list.html">主页</a><a href="blog_add.html">写博客</a><a href="myblog_list.html">我的博客</a><a href="javascript:logout()">注销</a></div><!-- 版心 --><div class="container"><!-- 左侧个人信息 --><div class="container-left"><div class="card"><img src="img/sleep.jpg" class="avtar" alt=""><h3 id="username"></h3><a href="http:www.github.com">github 地址</a><div class="counter"><span>文章</span></div><div class="counter"><span id="artcount"></span></div></div></div><!-- 右侧内容详情 --><div id="artListDiv" class="container-right" ></div></div><script>function init(){jQuery.ajax({url:"/article/mylist",type:"get",data:{},success:function(res){if(res.code==200){var creatHtml="";var arrList=res.data.artList;if(res.code==200&&res.data!=null){var user=res.data.user;var size=res.data.size;var art=res.data.artList;if(user!=null){if(user.photo!=""){jQuery("#photo").att("src",user.photo);}jQuery("#username").html(user.username);jQuery("#artcount").html(size);}else{alert("抱歉查询失败"+res.msg);}}if(arrList!=null&&arrList.length>0){                    for( var i=0;i<arrList.length;i++){var art =arrList[i];creatHtml+='<div class="blog">';creatHtml+='<div class="title">'+art.title+'</div>';creatHtml+='<div class="date">'+art.createtime+'</div>';creatHtml+='<div class="desc">'+ art.content+' </div>';creatHtml+='  <a href="blog_content.html?aid='+art.id+'" class="detail">查看全文 &gt;&gt;</a>&nbsp;&nbsp;';creatHtml+='<a href="blog_edit.html?aid='+art.id+'" class="detail">修改 &gt;&gt;</a>&nbsp;&nbsp;';creatHtml+='<a οnclick="del('+art.id+')" class="detail">删除 &gt;&gt;</a>';creatHtml+=' </div>';}}else{creatHtml+='<h3 style="margin-top:20px;margin-left:20px">暂无文章,请先添加<a href="blog_add.html">添加</a> </h3>';}jQuery("#artListDiv").html(creatHtml);}else{alert("抱歉,操作失败"+res.msg);}}});}init();function del(aid){//1.参数校验if(aid=""||aid<=0){alert("参数错误!");return false;}jQuery.ajax({url:"/art/del",type:"post",data:{"aid":aid},success:function(res){if(res.code==200&& res.data==1){alert("恭喜:删除成功");location.href=location.href;}else{alert("删除失败"+res.msg);}}});}</script>
</body></html>

后端

显示个人文章

调用mapper层控制数据库

@Mapper
public interface ArticleMapper {@Select("select * from articleinfo where uid=#{uid}")List<Articleinfo> getUidByArticle(@Param("uid") int uid);
}

调用service层调用mapper接口

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public List<Articleinfo> getUidByArticle(int uid){return articleMapper.getUidByArticle(uid);}
}

调用Controller 层调用service层

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@Resourceprivate ThreadPoolTaskExecutor taskExecutor;@Resourceprivate UserinfoVO userinfoVO;@RequestMapping("/mylist")public ResultAjax getUidByArticle(HttpServletRequest request){Userinfo userinfo= SessionUtis.getUser(request);if (userinfo==null){return ResultAjax.fail(-1,"请先登录");}List<Articleinfo> list =articleService.getUidByArticle(userinfo.getUid());int size=articleService.getArtCountById(userinfo.getUid());if (list!=null&&list.size()>0){list.stream().forEach(articleinfo -> {if (articleinfo.getContent().length()>120){articleinfo.setContent(articleinfo.getContent().substring(0,120));}});}HashMap<String ,Object> map=new HashMap<>();map.put("artList",list);map.put("user",userinfo);map.put("size",size);return ResultAjax.success(map);}
}

删除文章

调用mapper层控制数据库

@Mapper
public interface ArticleMapper {@Delete("delete from articleinfo where aid=#{aid} and uid=#{uid}")int delArt(@Param("aid")int aid,@Param("uid") int uid);
}

调用service层调用mapper接口

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;}

Controller层调用service
这个代码太多了我只展示主要代码

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@Resourceprivate ThreadPoolTaskExecutor taskExecutor;@RequestMapping("/del")public ResultAjax delArt(Integer aid,HttpServletRequest request){if (aid==null||aid<=0){return ResultAjax.fail(-1,"请先登录");}Userinfo userinfo=SessionUtis.getUser(request);int result= articleService.delArt(aid,userinfo.getUid());return ResultAjax.success(result);}}

修改文章

前端

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>博客编辑</title><!-- 引入自己写的样式 --><link rel="stylesheet" href="css/conmmon.css"><link rel="stylesheet" href="css/blog_edit.css"><!-- 引入 editor.md 的依赖 --><link rel="stylesheet" href="editor.md/css/editormd.min.css" /><script src="js/jquery.min.js"></script><script src="js/urluitils.js"></script><script src="editor.md/editormd.js"></script>
</head><body><!-- 导航栏 --><div class="nav"><img src="img/sleep.jpg" alt=""><span class="title">我的博客系统</span><!-- 用来占据中间位置 --><span class="spacer"></span><a href="blog_list.html">主页</a><a href="javascript:logout()">注销</a></div><!-- 编辑框容器 --><div class="blog-edit-container"><!-- 标题编辑区 --><div class="title"><input type="text" placeholder="在这里写下文章标题" id="title"><button onclick="doUpdate()">修改文章</button></div><!-- 创建编辑器标签 --><div id="editorDiv"><textarea id="editor-markdown" style="display:none;"></textarea></div></div><script>var editor;var aid=getParamValue("aid");function initEdit(md){// 编辑器设置editor = editormd("editorDiv", {// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. width: "100%",// 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度height: "calc(100% - 50px)",// 编辑器中的初始内容markdown: md,// 指定 editor.md 依赖的插件路径path: "editor.md/lib/",saveHTMLToTextarea: true // });}initEdit("# 在这里写下一篇博客"); // 初始化编译器的值// 提交function doUpdate(){var title=jQuery("#title");if(title.val()==""){alert("输入标题");title.focus();return false;}if(editor.getValue()==""){alert("请先输入正文");return false;}jQuery.ajax({url:"/article/update",type:"post",data:{"aid":aid,"title":title.val(),"content":editor.getValue()},success:function(res){if(res.code==200&&res.data==1){alert("恭喜,修改成功");location.href="myblog_list.html";}else if(res.code==-2){alert("未登录")location.href="login.html";}else{alert("抱歉,修改失败!"+res.msg);}}});}//初始化页面function init(){//校验aidif(aid==null||aid<0){alert("非法参数");return false;}//查询文章详情jQuery.ajax({url:"/article/update_init",type:"get",data:{"aid":aid},success: function(res){if(res.code==200&&res.data!=null&&res.data.id>0){jQuery("#title").val(res.data.title);initEdit(res.data.content);}else if(res.code==-2){alert("未登录")location.href="login.html";}else{alert("抱歉查询失败"+res.msg);}}});//将文章内容展示到页面}init();</script>
</body></html>

后端

提取文章

调用mapper层控制数据库

@Mapper
public interface ArticleMapper {@Select("select * from articleinfo where aid=#{aid} and uid=#{uid}")Articleinfo getArtByaidAnduid(@Param("aid")int aid,@Param("uid") int uid);
}

调用service层调用mapper接口

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public Articleinfo getArtByaidAnduid(int aid,int uid){return articleMapper.getArtByaidAnduid(aid,uid);}
}

Controller层调用service

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@Resourceprivate ThreadPoolTaskExecutor taskExecutor;@Resourceprivate UserinfoVO userinfoVO;@RequestMapping("/update_init")public ResultAjax updataInti(Integer aid,HttpServletRequest request){if (aid<=0||aid==null){return ResultAjax.fail(-1,"参数有误");}Userinfo userinfo=SessionUtis.getUser(request);if (userinfo==null){return ResultAjax.fail(-2,"请先登录");}Articleinfo articleinfo=articleService.getArtByaidAnduid(aid,userinfo.getUid());return ResultAjax.success(articleinfo);}}

修改文章

调用mapper层控制数据库

@Mapper
public interface ArticleMapper {@Update("Update articleinfo set title=#{title},content=#{content} where aid=#{aid} and uid=#{uid}")int setArt(Articleinfo articleinfo);
}

调用service层调用mapper接口

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public int setArt(Articleinfo articleinfo){return articleMapper.setArt(articleinfo);}
}

Controller层调用service

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@Resourceprivate ThreadPoolTaskExecutor taskExecutor;@Resourceprivate UserinfoVO userinfoVO;@RequestMapping("/update")public ResultAjax setArt(Articleinfo articleinfo,HttpServletRequest request){if (articleinfo==null||!StringUtils.hasLength(articleinfo.getContent())||!StringUtils.hasLength(articleinfo.getTitle())){return ResultAjax.fail(-1,"参数非法");}Userinfo userinfo=SessionUtis.getUser(request);if (userinfo==null){return ResultAjax.fail(-2,"请先登录");}articleinfo.setUid(userinfo.getUid());int result=articleService.setArt(articleinfo);return ResultAjax.success(result);}
}

显示正文内容

前端

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>博客正文</title><link rel="stylesheet" href="css/conmmon.css"><link rel="stylesheet" href="css/blog_content.css"><link rel="stylesheet" href="editor.md/css/editormd.preview.min.css" /><script src="js/jquery.min.js"></script><script src="editor.md/editormd.js"></script><script src="editor.md/lib/marked.min.js"></script><script src="editor.md/lib/prettify.min.js"></script><script src="js/urluitils.js"></script>
</head><body><!-- 导航栏 --><div class="nav"><img src="img/sleep.jpg" alt=""><span class="title">我的博客系统</span><!-- 用来占据中间位置 --><span class="spacer"></span><a href="blog_list.html">主页</a><a href="blog_edit.html">写博客</a><a href="myblog_list.html">我的博客</a><a href="login.html">登陆</a><a href="javascript:logout()">注销</a></div><!-- 版心 --><div class="container"><!-- 左侧个人信息 --><div class="container-left"><div class="card"><img src="img/sleep.jpg" class="avtar" id="photo"><h3 id="username"></h3><a href="http:www.github.com">github 地址</a><div class="counter"><span>文章</span></div><div class="counter"><span id="artcount"></span></div></div></div><!-- 右侧内容详情 --><div class="container-right"><div class="blog-content"><!-- 博客标题 --><h3 id="title"></h3><!-- 博客时间 --><div class="date" >发布时间: <span id="createtime"></span>|               阅读量: <span id="rcount"></span></div><!-- 博客正文 --><div id="editorDiv"></div></div></div></div><script type="text/javascript">var aid=getParamValue("aid");var editormd;function initEdit(md){editormd = editormd.markdownToHTML("editorDiv", {markdown : md, });}//初始化页面function init(){if(aid==null||aid<=0){alert("参数有误");return false;}jQuery.ajax({url:"/article/detail",type:"get",data:{"aid":aid},success:function(res){if(res.code==200&&res.data!=null){var user=res.data.user;var art=res.data.art;if(user!=null){if(user.photo!=""){jQuery("#photo").att("src",user.photo);}jQuery("#username").html(user.username);jQuery("#artcount").html(user.artCoout);}else{alert("抱歉查询失败"+res.msg);}if(art!=null){jQuery("#title").html(art.title);jQuery("#createtime").html(art.createtime);jQuery("#rcount").html(art.rcount);initEdit(art.content);}else{alert("抱歉查询失败"+res.msg);}}else{alert("抱歉查询失败"+res.msg);}}});}init();function incrementRCount(){if (aid==null||aid<=0) {return false;}jQuery.ajax({url:"/article/increment_rcount",type:"post",data:{"aid":aid},success:function(res){}})}incrementRCount();</script> 
</body></html>

后端

调用mapper层控制数据库
UserMapper

@Mapper
public interface UserMapper {@Select("select * from userinfo where uid=#{uid}")UserinfoVO getUserById(@Param("uid")int uid);
}

ArticleMapper

@Mapper
public interface ArticleMapper {@Update("Update articleinfo set title=#{title},content=#{content} where aid=#{aid} and uid=#{uid}")int setArt(Articleinfo articleinfo);@Select("select * from articleinfo where aid=#{aid}")Articleinfo readDetail(@Param("aid")int aid);}

调用service层调用mapper接口
UserServie

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public UserinfoVO getUserByUid(int uid){return userMapper.getUserById(uid);}
}

ArticleService

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public Articleinfo readDetail(int aid){return articleMapper.readDetail(aid);}
}

Controller层调用service

ArticleController

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@Resourceprivate ThreadPoolTaskExecutor taskExecutor;@Resourceprivate UserService userService;@Resourceprivate UserinfoVO userinfoVO;@RequestMapping("/detail")public ResultAjax readDetail(Integer aid) throws ExecutionException, InterruptedException {if (aid<=0||aid==null){return ResultAjax.fail(-1,"非法参数");}Articleinfo articleinfo=articleService.readDetail(aid);if (articleinfo==null){return ResultAjax.fail(-1,"非法参数");}FutureTask<UserinfoVO> userTask=new FutureTask<>(()->{return  userService.getUserByUid(articleinfo.getUid());});taskExecutor.submit(userTask);FutureTask<Integer> artCountTask=new FutureTask<>(()->{return articleService.getArtCountById(articleinfo.getUid());});taskExecutor.submit(artCountTask);UserinfoVO userinfoVO=userTask.get();int artCount=artCountTask.get();userinfoVO.setArtCount(artCount);HashMap<String,Object> map=new HashMap<>();map.put("user",userinfoVO);map.put("art",articleinfo);return ResultAjax.success(map);}
}

文章阅读量功能

调用mapper层控制数据库

@Mapper
public interface ArticleMapper {@Update("upate articleinfo set readcount=readcount+1 where aid=#{aid}")int readArtCount(@Param("aid")int aid);}

调用service层调用mapper接口

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public int readArtCount(int aid){return articleMapper.readArtCount(aid);}
}

Controller层调用service

@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;@Resourceprivate ThreadPoolTaskExecutor taskExecutor;@Resourceprivate UserService userService;@Resourceprivate UserinfoVO userinfoVO;@RequestMapping("/increment_rcount")public ResultAjax readArtCount(Integer aid){if (aid==null||aid<=0){return ResultAjax.fail(-1,"参数有误");}int result = articleService.readArtCount(aid);return ResultAjax.success(result);}
}

添加文章

前端

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>博客编辑</title><!-- 引入自己写的样式 --><link rel="stylesheet" href="css/conmmon.css"><link rel="stylesheet" href="css/blog_edit.css"><!-- 引入 editor.md 的依赖 --><link rel="stylesheet" href="editor.md/css/editormd.min.css" /><script src="js/jquery.min.js"></script><script src="editor.md/editormd.js"></script>
</head><body><!-- 导航栏 --><div class="nav"><img src="img/sleep.jpg" alt=""><span class="title">我的博客系统</span><!-- 用来占据中间位置 --><span class="spacer"></span><a href="blog_list.html">主页</a><a href="myblog_list.html">我的博客</a><a href="javascript:logout()">注销</a></div><!-- 编辑框容器 --><div class="blog-edit-container"><!-- 标题编辑区 --><div class="title" ><input type="text" placeholder="在这里写下文章标题" id="title"><button onclick="mysub()"  >发布文章</button></div><!-- 创建编辑器标签 --><div id="editor"><textarea id="editor-markdown" style="display:none;"></textarea></div></div><script>var editor;function initEdit(md){// 编辑器设置editor = editormd("editor", {// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. width: "100%",// 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度height: "calc(100% - 50px)",// 编辑器中的初始内容markdown: md,// 指定 editor.md 依赖的插件路径path: "editor.md/lib/",saveHTMLToTextarea: true // });}initEdit("# 在这里写下一篇博客"); // 初始化编译器的值// 提交function mysub(){//非空校验var title=jQuery("#title");if(title.val()==""){alert("输入标题");title.focus();return false;}if(editor.getValue()==""){alert("请先输入正文");return false;}//将用户提交的数据传递给后端jQuery.ajax({url:"/article/add",type:"post",data:{"title":title.val(),"content":editor.getValue()},success:function(res){if(res.code==200&&res.data==1){if(confirm("恭喜:添加成功,是否继续添加文章")){Location.href=Location.href;}else{location.href="myblog_list.html";}}else{alert("抱歉:操作失败"+res.msg); }}});//将返回的数据展现给用户}</script>
</body></html>

后端

mapper

    @Insert("insert into articleinfo(title,content,uid) values(#{title},#{content},#{uid})")int add(Articleinfo articleinfo);

Service

    public int add(Articleinfo articleinfo) {return articleMapper.add(articleinfo);}

Controller

	 @RequestMapping("/add")public ResultAjax add(Articleinfo articleinfo,HttpServletRequest request){if (articleinfo==null||!StringUtils.hasLength(articleinfo.getTitle())||!StringUtils.hasLength(articleinfo.getContent())){return ResultAjax.fail(-1,"非法参数");}Userinfo userinfo=SessionUtis.getUser(request);if (userinfo==null){return ResultAjax.fail(-2,"请先登录");}articleinfo.setUid(userinfo.getUid());int result=articleService.add(articleinfo);return ResultAjax.success(result);}

补充一点:

如何使用Redis

在这里插入图片描述
具体详情可以看我的Redis哪一章文章链接

你会发现启动的并没有成功。原因我这里留了一个坑,关于拦截器的。

@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginIntercpet()).addPathPatterns("/**").excludePathPatterns("/css/*").excludePathPatterns("/js/*").excludePathPatterns("/css").excludePathPatterns("/img/*").excludePathPatterns("/reg.html").excludePathPatterns("/blog_list.html").excludePathPatterns("/article/detail").excludePathPatterns("/article/getlistbypage").excludePathPatterns("/user/reg").excludePathPatterns("/user/login").excludePathPatterns("/editor.md/*").excludePathPatterns("/blog_content.html").excludePathPatterns("/login.html");}
}

第二个启动这里要添加mapper映射否则会失败
在这里插入图片描述

@SpringBootApplication
@MapperScan("com.example.myblog.mapper")
public class MyblogApplication {public static void main(String[] args) {SpringApplication.run(MyblogApplication.class, args);}}

项目地点:

项目的Gitee链接(实际调试完毕的项目)

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

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

相关文章

数字化转型对企业有哪些优势?

数字化转型为企业提供了众多优势&#xff0c;帮助他们在日益数字化的世界中保持竞争力、敏捷性和响应能力。以下是一些主要优势&#xff1a; 1.提高效率和生产力&#xff1a; 重复性任务和流程的自动化可以减少人为错误&#xff0c;并使员工能够专注于更具战略性的任务。简化…

Apache Linki 1.3.1+DataSphereStudio+正常启动+微服务+端口号

我使用的是一键部署容器化版本&#xff0c;官方文章 默认会启动6个 Linkis 微服务&#xff0c;其中下图linkis-cg-engineconn服务为运行任务才会启动,一共七个 LINKIS-CG-ENGINECONN:38681 LINKIS-CG-ENGINECONNMANAGER:9102 引擎管理服务 LINKIS-CG-ENTRANCE:9104 计算治理入…

Vue开发小注意点

改bug 更改了配置项啥的&#xff0c;保存刷新发现没变&#xff0c;那就重启项目&#xff01;&#xff01;&#xff01;&#xff01; binding.value 和 e.target.value binding.value Day5 指令的值 e.target.value Day4 表单组件封装 binding.value 和 e.target.valu…

plt函数显示图片 在图片上画边界框 边界框坐标转换

一.读取图片并显示图片 %matplotlib inline import torch from d2l import torch as d2l读取图片 image_path ../data/images/cat_dog_new.jpg # 创建画板 figure d2l.set_figsize() image d2l.plt.imread(image_path) d2l.plt.imshow(image);二.给出一个(x左上角,y左上角,…

Flask 使用 JWT(三)flask-jwt-extended

如果想要在 flask 中使用 JWT ,推荐使用 flask-jwt-extended 插件。 使用 pip 安装这个扩展插件的最简单方法是: pip install flask-jwt-extended基本使用 在接下来的案例中,我们看一下基本使用。我们可以使用 create_access_token() 函数用来生成实际的 JWT token。@jwt_r…

K8S之使用yaml格式定义pod

mysql-pod.yaml # overView: # 1. web服务与db打包放在同一个pod中&#xff0c;本地通过localhost来访问&#xff0c;并附带存活性/可用性检测 # 2. 补充重启策略/镜像拉去策略 # 3. 对容器资源进行限制apiVersion: apps/v1 kind: Pod metadata:name: pub-oanamespace: hunte…

__declspec(novtable) 在C++

__declspec(novtable) 在C中接口中广泛应用. 不容易看到它是因为在很多地方它都被定义成为了宏. 比如说ATL活动模板库中的ATL_NO_VTABLE, 其实就是__declspec(novtable). __declspec(novtable) 就是让类不要有虚函数表以及对虚函数表的初始化代码, 这样可以节省运行时间和空间.…

服务注册与服务发现

服务注册与服务发现 Eureka的架构 Eureka客户端&#xff1a;使用了EnableEurekaClient注解的应用服务&#xff0c;如订单服务等&#xff0c;甚至Eureka本身也是一个客户端 Eureka服务端&#xff1a;使用了EnableEurekaServer注解的应用服务&#xff0c;该服务提供了注册表以及…

使用Git把项目上传到Gitee的详细步骤

1.到Git官网下载并安装 2.到Gitee官网进行注册&#xff0c;然后在Gitee中新建一个远程仓库 3.设置远程仓库的参数 4.返回Gitee查看仓库是否生成成功 5.新建一个文件夹作为你的本地仓库 6.将新建好的文件夹初始化成本地仓库 第一步&#xff1a;右键点击刚创建的本地仓库&#…

小程序实现一个 倒计时组件

小程序实现一个 倒计时组件 需求背景 要做一个倒计时&#xff0c;可能是天级别&#xff0c;也可能是日级别&#xff0c;时级别&#xff0c;而且每个有效订单都要用&#xff0c;就做成组件了 效果图 需求分析 需要一个未来的时间戳&#xff0c;或者在服务度直接下发一个未来…

NeuroFlash:AI文章写作与生成工具

【产品介绍 ​ 】 名称 NeuroFlash 上线时间 2015 具体描述 Neuroflash是一款基于人工智能的文本和图像生成器&#xff0c;可以帮助用户快速创建高质量的内容。Neuroflash拥有超过100种短文和长文的文本类型&#xff0c;涵盖了各种营销场景和需求。只需要输入简单的指示&#…

【Excel函数】Trim函数删除前后多余的空格

Excel 中的 TRIM 函数用于删除文本字符串两端多余的空格&#xff0c;只保留字符串内部的空格。这对于清理和规范化文本数据非常有用。 在使用Excel中使用TRIM可以删除内容前面和后面的空格字符&#xff0c;Trim的语法规则如下&#xff1a; A2trim(Text) text&#xff1a;要进…

最新ChatGPT网站源码+支持GPT4.0+支持Midjourney绘画+支持国内全AI模型

一、智能创作系统 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&…

Debian12系统下LAMP环境中Nubuilder4.5的安装

一、环境搭建 按照官方的说法&#xff0c;Apache2和Nginx都可以的&#xff0c;实际上&#xff0c;你最好直接按照 Mariadb\Apache2\Php8.2 这个顺序&#xff0c;搭建LAMP环境较好。不然各种调试&#xff0c;还不一定能够成功。 相关搭建方法&#xff0c;属于一般操作&#xf…

java类的命名规范

Java类的命名规范是一种编码规范&#xff0c;用于指导开发人员在命名Java类时遵循一致性和可读性的原则。以下是Java类的命名规范的主要要点&#xff1a; 类名应该使用大驼峰命名法&#xff08;UpperCamelCase&#xff09;&#xff1a; 类名的每个单词首字母都应该大写&#xf…

js中如何判断一个变量是否为数字类型?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐使用Number.isNaN()方法⭐使用正则表达式⭐使用isNaN()函数⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个…

LeetCode:1929.数组串联

1929. 数组串联 来源:力扣(LeetCode) 链接: https://leetcode.cn/problems/concatenation-of-array/description/ 给你一个长度为 n 的整数数组 nums 。请你构建一个长度为 2n 的答案数组 ans ,数组下标 从 0 开始计数 ,对于所有 0 < = i < n 0 <= i < n …

MD5 算法流程

先通过下面的命令对 md5算法有个感性的认识&#xff1a; $ md5sum /tmp/1.txt 1dc792fcaf345a07b10248a387cc2718 /tmp/1.txt$ md5sum // 从键盘输入&#xff0c;ctrl-d 结束输入 hello, world! 910c8bc73110b0cd1bc5d2bcae782511 -从上面可以看到&#xff0c;一个文件或一…

MySQL(1) 索引结构

1、索引结构 索引概念&#xff1a;是帮助mysql高效获取数据的排好序的数据结构 2、MySQL为什么用BTree 为什么不用二叉树&#xff0c;单边增长 为什么不用红黑树&#xff0c;树的高度不受控制 为什么不用B-Tree,为了节省空间 为什么不用Hash表&#xff0c;Hash不支持范围查询 …

C++ - map 的 例题

前言 本博客在 一下文章关于 map 和 set 讲解之下&#xff0c;对 map 当中的 operator[] &#xff08;&#xff09;函数的功能运用&#xff0c;感受 map 功能强大。 349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 给定两个数组 nums1 和 nums2 &#xff0c;返回…