博客系统:个人博客系统(Spring Boot、Spring MVC、MyBatis)_拾.柒.的博客-CSDN博客
目录
设计思路
分析
- 当用户选择好定时发布时间,点击“定时发布”按钮之后,触发 ajax 请求,请求中的数据包括文章标题、文章正文内容、定时发布的时间;
- 后端接收到数据以后,先对数据进行非空校验,然后创建一个线程,实现一个类似于自旋锁的操作,即每隔 2s 进行一次自旋询问操作,也就是说,每 2s 询问一下当前时间是否大于等于用户所选的定时发布时间,若满足大于等于条件,就将文章发布,若小于所定发布时间,就通过 wait(2000) 让线程等待 2s.
具体实现
前端操作
该功能涉及 blog_add.html 博客发布页面
a. 引入发送 ajax 请求的依赖
<script src="js/jquery.min.js"></script>
b. 约定前后端的交互接口
url:"/art/timeadd"
type:"POST"
data:title,content,postTime
后端返回 code = 200 并且 data = 1,提示定时发布成功,跳转至个人博客列表页,即 myblog_list.html ;返回结果不满足条件,弹框提示“定时发布失败,请稍后重试!”
c. 前端代码
创建 input 控件,type 类型为 datetime-local(可以选择年、月、日、时、分)
【注意】datetime-local 的格式为:"yyyy-mm-ddThh:mm"。
此处给定时发布按钮添加点击事件 myTimeSub(),因为实现发布文章功能时已经创建了编译器及对其进行了相应设置,所以这里作为扩展功能直接在原来基础上添加相应代码即可,代码如下:
<!-- 标题编辑区 -->
<div class="title">
<input type="text" id="title" placeholder="输入文章标题">
<input type="datetime-local" id="pubdate">
<button onclick="myTimeSub()" id="pubdate-button">定时发布</button>
<button onclick="mysub()" id="send-button">发布文章</button>
</div>
//定时发布
function myTimeSub() {
var postTime = jQuery("#pubdate");
//非空校验
if (postTime.val() == "") {
alert("请选择定时发布时间!");
return;
}
if(confirm("是否确认发布!")) {
jQuery.ajax({
type: "POST",
url: "/art/timeadd",
data: {
"title": jQuery('#title').val(),
"content": editor.getValue(),
"postTime": postTime.val()
},
success: function (result) {
if (result != null && result.code == 200 && result.data == 1) {
alert("定时发布成功!");
location.href = "myblog_list.html";
} else {
alert("定时发布失败,请稍后重试");
}
}
});
}
}
后端操作--该功能实现涉及到数据库表字段的修改
首先,创建一个公共类 common.ArticleInfoUtils,后续用来检验是否超时,达到发布时间
public class ArticleInfoUtils {
/**
* 定时发布
* 用来检验是否超时
* @param startTime 起始时间(yyyy-MM-dd HH:mm)
* @param endTime 定时发布时间(yyyy-mm-ddThh:mm)
* @return
*/
public static boolean checkOvertime(String startTime, String endTime) {
String[] st = startTime.split(" ");
String[] et = endTime.split("T");
//yyyy-mm-dd
String[] symd = st[0].split("-");
String[] eymd = et[0].split("-");
//hh:mm
String[] shm = st[1].split(":");
String[] ehm = et[1].split(":");
//进行时间比较(一次按年月日进行比较,只要大于定时发布时间就返回 true,反之返回 false)
if(Integer.parseInt(symd[0]) > Integer.parseInt(eymd[0])) return true;
else if(Integer.parseInt(symd[0]) < Integer.parseInt(eymd[0])) return false;
if(Integer.parseInt(symd[1]) > Integer.parseInt(eymd[1])) return true;
else if(Integer.parseInt(symd[1]) < Integer.parseInt(eymd[1])) return false;
if(Integer.parseInt(symd[2]) > Integer.parseInt(eymd[2])) return true;
else if(Integer.parseInt(symd[2]) < Integer.parseInt(eymd[2])) return false;
if(Integer.parseInt(shm[0]) > Integer.parseInt(ehm[0])) return true;
else if(Integer.parseInt(shm[0]) < Integer.parseInt(ehm[0]))return false;
if(Integer.parseInt(shm[1]) >= Integer.parseInt(ehm[1])) return true;
else return false;
}
a. 实现 mapper.ArticleMapper(此处和发布文章使用的是同一个,因为无论是定时发布文章还是即时发布文章,对于数据库而言都是添加一篇文章的操作,主要的不同,在咱们的 controller 层)
int add(Articleinfo articleinfo);
b. 对应的 xml 实现
<insert id="add">
insert into articleinfo(title,content,uid)
values(#{title},#{content},#{uid})
</insert>
c. 实现 service.ArticleService( service 层代码)
public int add(Articleinfo articleinfo) {
return articleMapper.add(articleinfo);
}
d. 实现 controller.ArticleController( controller 层)
【注意】
这里不是使用咱们单纯的 ArticleInfo 对象了,而是在这个的基础上加了定时发布时间 postTime 这一字段的,所以咱们创建一个 ArticleInfoVO 实体类,使其继承自 ArticleInfo 实体类
@Data
public class ArticleinfoVO extends Articleinfo {
private String postTime;
}
controller 层代码如下:
private Object lock = new Object();
@RequestMapping("/timeadd")
public AjaxResult timeAdd(HttpServletRequest request, ArticleinfoVO articleInfoVO) {
//非空校验
if(articleInfoVO == null || !StringUtils.hasLength(articleInfoVO.getTitle()) ||
!StringUtils.hasLength(articleInfoVO.getContent())) {
return AjaxResult.fail(-1, "参数错误!");
}
Userinfo userinfo = UserSessionUtils.getUser(request);
if(userinfo == null || !StringUtils.hasLength(userinfo.getUsername()) ||
!StringUtils.hasLength(userinfo.getPassword())) {
return AjaxResult.fail(-2, "参数错误");
}
//设置定时发布,启动一个线程,每两秒询问一次是否到达过期时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Thread queryTime = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
while(true) {
if(ArticleInfoUtils.checkOvertime(sdf.format(System.currentTimeMillis()),
articleInfoVO.getPostTime())) {
//到达过期时间
Articleinfo articleinfo = new Articleinfo();
articleinfo.setTitle(articleInfoVO.getTitle());
articleinfo.setContent(articleInfoVO.getContent());
articleinfo.setUid(userinfo.getId());
//添加文章
articleService.add(articleinfo);
break;
}
try {
System.out.println("休眠2s");
lock.wait(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
queryTime.start();
//发布博客
return AjaxResult.success(1);
}
到这里,定时发布文章功能就实现咯,下次见~