设计思路
分析
当用户选择好定时发布时间以后,点击定时发布按钮之后,向后端发起 ajax 请求,请求中的数据有:“文章标题、文章正文内容、定时发布时间”,后端接收到数据以后,首先对客户端传入数据进行非空校验,然后起一个线程,实现一个类似自旋锁的操作:“每过 2s 就进行一次自旋询问操作”,通俗来讲就是每过 2s 询问一下当前时间是否大于定时发布时间,若大于,就将文章发布,若不大于就使用 wait(2000) 让线程等待 2s 。
这样就可以实现文章定时发布功能喽~
前后端交互接口
请求
POST /art/timeadd
Content-Type: application/json
{
"title": jQuery('#title').val(), //获取标题
"content": editor.getValue(), //获取正文
"postTime": postTime.val() //获取定时发布时间
}
响应
Ps:采用同一返回数据格式处理(“code:状态码,msg:信息,data:数据”)
HTTP1.1 200 OK
Content-Type: application/json
{
code: 200, //状态码
msg: "", //信息
data: 1 //数据
}
代码实现和详细注释
数据库设计
文章表设计如下:
create table articleinfo(
id int primary key auto_increment,
title varchar(100) not null,
content text not null,
createtime timestamp default current_timestamp,
updatetime timestamp default '1970-01-01 10:00:00',
uid int not null,
rcount int not null default 1,
`state` int default 1,
)
前后端交互
客户端开发
创建 input 控件,type 类型为 datetime-local (可以选择年、月、日、时、分)
Ps:这里要注意 datetime-local 的格式为:"yyyy-mm-ddThh:mm"
创建 button 控件,点击触发 js 代码。
<input type="datetime-local" id="pubdate">
<button onclick="myTimeSub()" id="pubdate-button">定时发布</button>
js 代码实现如下:
//定时发布
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.assign("/myblog_list.html");
} else {
alert("定时发布失败,请稍后重试");
}
}
});
}
}
服务器开发
按照刚刚讲到的分析思路和前后端交互接口不难实现~
Ps:定时发布时间的格式为:"yyyy-mm-ddThh:mm"
Controller 层代码如下;
@RequestMapping("/timeadd")
public AjaxResult timeAdd(HttpServletRequest request, ArticleInfoVO articleInfoVO) {
//非空校验
if(articleInfoVO == null || !StringUtils.hasLength(articleInfoVO.getTitle()) ||
!StringUtils.hasLength(articleInfoVO.getContent())) {
return AjaxResult.fail(403, "参数错误!");
}
UserInfo userInfo = UserSessionUtils.getUser(request);
if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
!StringUtils.hasLength(userInfo.getPassword())) {
return AjaxResult.fail(403, "参数错误");
}
//设置定时发布,启动一个线程,每两秒询问一次是否到达过期时间
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);
}
定时发布时间检测:
/**
* 定时发布
* 用来检验是否超时
* @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;
}