【JavaEE】進(jìn)階 · 個(gè)人博客系統(tǒng)(4)
【JavaEE】進(jìn)階 · 個(gè)人博客系統(tǒng)(4)
1. 增加博文
1.1 預(yù)期效果
用戶在網(wǎng)頁(yè)中編寫(xiě)標(biāo)題和正文,點(diǎn)擊提交,選擇
- 輸入摘要
- 取消,繼續(xù)編寫(xiě)文章
提交成功后,選擇
- 繼續(xù)寫(xiě)文章
- 返回“我的博客列表頁(yè)”
1.1 約定前后端交互接口
后端:
- /art/publish
- 將前端傳遞過(guò)來(lái)的數(shù)據(jù)保存到數(shù)據(jù)庫(kù)
- 返回受影響行數(shù)
前端:
- /art/publish
- 標(biāo)題,正文,摘要
- 當(dāng)前登錄用戶sessionid
1.2 后端代碼
- controller層
由于經(jīng)常需要對(duì)字符串進(jìn)行檢查,我封裝了一個(gè)方法:
- 為什么前端檢驗(yàn)完了,后端還檢驗(yàn)?zāi)兀?/strong>
- 千萬(wàn)別相信“前端”,因?yàn)檫@個(gè)“前端”,可能不是瀏覽器正常的流程,也可能是通過(guò)postman等方式發(fā)送的請(qǐng)求,這個(gè)就可以繞開(kāi)前端代碼的校驗(yàn)~
- 不用擔(dān)心,因?yàn)?/li>
public class APPUtils { /** * 字符串全部都有長(zhǎng)度才返回true * @param strings * @return */ public static boolean hasLength(String... strings) { for(String x : strings) { if(!StringUtils.hasLength(x)) { return false; } } return true; } }
修改:
@RequestMapping("/publish")
public CommonResult publish(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {
// 1. 獲取當(dāng)前用戶詳信息
UserInfo userInfo = SessionUtils.getUser(request);
articleInfo.setUid(userInfo.getId());
articleInfo.setPhoto(userInfo.getPhoto());
// 2. 校驗(yàn)參數(shù)
if(!APPUtils.hasLength(articleInfo.getContent(), articleInfo.getSummary(), articleInfo.getTitle())) {
return CommonResult.fail(-1, "非法參數(shù)!");
}
// 3. 提交到數(shù)據(jù)庫(kù)中
int rows = articleService.publish(articleInfo);
// 4. 返回
return CommonResult.success(rows);
}
- service層
@Autowired
private ArticleMapper articleMapper;
public int publish(ArticleInfo articleInfo) {
return articleMapper.insert(articleInfo);
}
- mapper層
@Insert("insert into articleinfo (title, content, summary, uid, photo) values (#{title}, #{content}, #{summary}, #{uid}, #{photo})")
int insert(ArticleInfo articleInfo);
-
攔截器配置
- 攔截,不排除此接口
1.3 前端代碼
function publish() {
var title = jQuery("#text");
var content = jQuery("#content");
// 1. 參數(shù)校驗(yàn)
if (title.val().trim() == "") {
alert("標(biāo)題不能為空!");
title.focus();
return false;
}
if (content.val().trim() == "") {
alert("正文不能為空!");
content.focus();
return false;
}
// 2. 輸入摘要
var summary = prompt("請(qǐng)輸入摘要:");
if(summary == "") {
return false;
}
// 3. 發(fā)送請(qǐng)求
jQuery.ajax({
url: "/art/publish",
method: "POST",
contentType: "application/json; charset=utf8",
data: JSON.stringify({
title: title.val().trim(),
content: content.val().trim(),
summary: summary.val().trim(),
}),
// 3. 處理響應(yīng)
success: function (body) {
if (body.code == 200 && body.data == 1) {
if(confirm("發(fā)布成功!請(qǐng)問(wèn)是否繼續(xù)創(chuàng)作?")) {
location.href = location.href;
}else {
location.href = "myblog_lists.html";
}
} else {
alert("發(fā)布失?。? + body.msg);
}
},
});
}
1.4 測(cè)試
為了避免寫(xiě)文章過(guò)程中session過(guò)去,我將session設(shè)置為永不過(guò)期:
2. 我的博客列表頁(yè)
2.1 期待效果
- 左側(cè)窗口顯示用戶信息
-
右側(cè)窗口顯示用戶創(chuàng)作的博文簡(jiǎn)介
- 標(biāo)題
- 時(shí)間以及閱讀量
- 摘要
- 查看正文,修改文章,刪除文章按鈕
-
右上角
- 點(diǎn)擊主頁(yè)跳轉(zhuǎn)到所有人的博客列表頁(yè)
- 點(diǎn)擊寫(xiě)博客跳轉(zhuǎn)到博客創(chuàng)作頁(yè)
- 點(diǎn)擊退出登錄,后端刪除登錄記錄,跳轉(zhuǎn)到登錄頁(yè)面
2.2 顯示用戶信息以及博客信息
2.2.1 約定前后端交互接口
后端:
- /article/get_mylist
- 通過(guò)當(dāng)前登錄用戶查詢博客
- 返回用戶信息以及博客信息的組合
前端:
- /article/get_mylist
- get
- 接受響應(yīng),投喂給頁(yè)面
2.2.2 后端代碼
- controller層
@RequestMapping("/get_mylist")
public CommonResult getMylist(HttpServletRequest request) {
// 1. 獲取當(dāng)前登錄用戶
UserInfo userInfo = SessionUtils.getUser(request);
// 2. 通過(guò)此用戶發(fā)布的所有文章
List<ArticleInfo> list = articleService.getListByUid(userInfo.getId());
// 3. 標(biāo)題 / 正文太長(zhǎng) 處理
ArticleUtils.substringList(list);
// 4. 返回給前端
Map<String, Object> map = new HashMap<>();
map.put("user", userInfo);
map.put("list", list);
return CommonResult.success(map);
}
// 文章工具類 public class ArticleUtils { //標(biāo)題截取長(zhǎng)度 private static final int _TITLE_LENGTH = 40; //摘要截取長(zhǎng)度 private static final int _SUMMARY_LENGTH = 160; public static void substringList(List<ArticleInfo> list) { if(list != null && list.size() != 0) { // 并發(fā)處理 list 集合 list.stream().parallel().forEach((art) -> { //標(biāo)題截取 if(art.getTitle().length() > _TITLE_LENGTH) { art.setTitle(art.getTitle().substring(0, _TITLE_LENGTH) + "..."); } //摘要截取 if(art.getSummary().length() > _SUMMARY_LENGTH) { art.setSummary(art.getSummary().substring(0, _SUMMARY_LENGTH) + "..."); } }); } } }
- service層
public List<ArticleInfo> getListByUid(int uid) {
return articleMapper.getListByUid(uid);
}
- mapper層
@Select("select * from articleinfo where uid = #{uid} order by id desc")
List<ArticleInfo> getListByUid(@Param("uid") int uid); //越晚發(fā)布排在越前
-
攔截器配置
- 不排除此接口
- 時(shí)間格式配置
可以接受數(shù)據(jù)庫(kù)時(shí)間的類型一般是:
- Date
- LocalDataTime
- TimeStamp
網(wǎng)絡(luò)資料
LocalDateTime和Date是Java中表示日期和時(shí)間的兩種不同的類,它們有一些區(qū)別和特點(diǎn)。
類型:LocalDateTime是Java 8引入的新類型,屬于Java 8日期時(shí)間API(java.time包)。而Date是舊版Java日期時(shí)間API(java.util包)中的類。
不可變性:LocalDateTime是不可變的類型,一旦創(chuàng)建后,其值是不可變的。而Date是可變的類型,可以通過(guò)方法修改其值。
線程安全性:LocalDateTime是線程安全的,多個(gè)線程可以同時(shí)訪問(wèn)和操作不同的LocalDateTime實(shí)例。而Date是非線程安全的,如果多個(gè)線程同時(shí)訪問(wèn)和修改同一個(gè)Date實(shí)例,可能會(huì)導(dǎo)致不可預(yù)期的結(jié)果。
時(shí)間精度:LocalDateTime提供了納秒級(jí)別的時(shí)間精度,可以表示更加精確的時(shí)間。而Date只能表示毫秒級(jí)別的時(shí)間精度。
時(shí)區(qū)處理:LocalDateTime默認(rèn)不包含時(shí)區(qū)信息,表示的是本地日期和時(shí)間。而Date則包含時(shí)區(qū)信息,它的實(shí)際值會(huì)受到系統(tǒng)默認(rèn)時(shí)區(qū)的影響。
而TimeStamp就是long類型的時(shí)間戳的包裝~
對(duì)于時(shí)間格式的控制:
-
json的構(gòu)造本身是通過(guò)getter去獲取的,所以可以重寫(xiě)getter來(lái)控制顯示效果
-
全局配置:
但是這只適合jdk8之前的Date類型
-
局部配置:
- 對(duì)于時(shí)間類型的屬性,是可以通過(guò)注解@JsonFormat來(lái)配置的:
2.2.3 前端代碼
左:
右:
jQuery.ajax({
type: "get",
url: "/art/get_mylist",
success: function (body) {
if (body.code == 200) {
// 1. 改變左側(cè)窗口
jQuery(".card img").attr("src", body.data.user.photo);
jQuery(".card h3").text(body.data.user.name);
if(body.data.user.git.trim() != "") {
jQuery(".card a").attr("href", body.data.user.git);
}
jQuery("#count").text(body.data.list.length);
// 2. 顯示文章,構(gòu)造博客html元素
for (var blog of body.data.list) {
console.log(body.title);
var art =
'<div class="blog"><div class="title">' + blog.title + "</div>";
art +=
'<div class="date">' +
blog.createtime +
" 閱讀量:" +
blog.rcount +
"</div>";
art += '<div class="content">' + blog.summary + "</div>";
art += '<div class="thing">';
art +=
'<a href="blog_detail.html?aid=' + blog.id + '">查看正文</a>';
art +=
'<a href="myblog_update.html?aid=' + blog.id + '">修改文章</a>';
art +=
'<div id="del" style="background-color: rgba(255, 0, 0, 0.6)" οnclick="del(' +
blog.id +
')">刪除文章</div>';
art += "</div></div>";
// 3. 追加到div.article
jQuery(".article").append(jQuery(art));
}
}
},
});
你也可以,以標(biāo)簽為單位去設(shè)置屬性以及嵌套,這有邏輯的構(gòu)建;而我這里是單純的拼接字符串,用jQuery(str),構(gòu)造html元素
2.2.4 測(cè)試
2.3 刪除文章
2.3.1 約定前后端交互接口
后端:
- /art/delete
- 根據(jù)當(dāng)前登錄用戶id,和刪除文章對(duì)應(yīng)的作者id,判斷是否有權(quán)限刪除,有才能刪除
- 返回受影響行數(shù)
前端:
- /art/delete
- post
- JSON:id(文章id)
- 如果受影響行數(shù)為1,刷新頁(yè)面
2.3.2 后端代碼
- controller層
@RequestMapping("/delete")
public CommonResult delete(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {
// 1. 獲取當(dāng)前登錄用戶的id
int uid = SessionUtils.getUser(request).getId();
// 2. 設(shè)置到文章對(duì)象里
articleInfo.setUid(uid);
// 3. 刪除
int rows = articleService.delete(articleInfo);
// 4. 返回
return CommonResult.success(rows);
}
- service層
public int delete(ArticleInfo articleInfo) {
return articleMapper.delete(articleInfo);
}
- mapper層
@Delete("delete from articleinfo where id = #{id} and uid = #{uid}")
// 查找文章和檢測(cè)權(quán)限在一步搞定
int delete(ArticleInfo articleInfo);
-
攔截器配置
- 攔截,不排除
2.3.3 前端代碼
function del(aid) {
// 0. 參數(shù)校驗(yàn)
if (parseInt(aid) == NaN || aid <= 0) {
return false;
}
jQuery.ajax({
method: "post",
url: "/art/delete",
contentType: "application/json; charset=utf8",
data: JSON.stringify({
id: aid,
}),
success: function (body) {
if (body.code == 200 && body.data == 1) {
location.href = location.href;
} else {
alert("刪除失??!\n");
}
},
});
}
2.3.4 測(cè)試
2.4 退出登錄
2.4.1 約定前后端交互接口
后端:
- /user/logout
- 根據(jù)當(dāng)前用戶進(jìn)行刪session操作
- 無(wú)返回值
前端:
- /user/logout
- a標(biāo)簽的get
2.4.2 后端代碼
- controller層
@RequestMapping("/logout")
public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 設(shè)置為null也可以,但這是因?yàn)槲覀兊呐袛嘣淼脑?/span>
//SessionUtils.setUser(request, null);
// 調(diào)用工具類里的注銷方法
SessionUtils.remove(request);
response.sendRedirect("blog_login.html");
}
/** * 注銷 * @param request */ public static void remove(HttpServletRequest request) { HttpSession session = request.getSession(false); if(session != null && session.getAttribute(ApplicationVariable.SESSION_KEY) != null) { session.removeAttribute(ApplicationVariable.SESSION_KEY); } }
-
攔截器配置
- 攔截,不排除
2.4.3 前端代碼
<a href="/user/logout">退出登錄</a>
2.4.4 測(cè)試
3. 修改文章
預(yù)期效果就是:原有數(shù)據(jù)顯示出來(lái),供用戶修改
3.1 頁(yè)面初始化
3.1.1 約定前后端接口
后端:
- /art/get_art
- 根據(jù)uid和aid查詢文章
- 返回文章信息
前端:
- /art/get_art
- post,json,aid
- 將數(shù)據(jù)投喂到網(wǎng)頁(yè)
3.1.2 后端代碼
- controller層
@RequestMapping("/get_art")
public CommonResult getArt(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {
// 1. 獲取當(dāng)前登錄用戶的id
int uid = SessionUtils.getUser(request).getId();
// 2. 設(shè)置到文章對(duì)象里
articleInfo.setUid(uid);
// 3. 查詢文章
ArticleInfo art = articleService.getArt(articleInfo);
// 4. 返回(查詢不到一個(gè)對(duì)象,是null;如果查詢不到對(duì)象集合,返回的是空集合)
return art == null ? CommonResult.fail(-1, "查詢不到!") : CommonResult.success(art);
}
- service層
public ArticleInfo getArt(ArticleInfo articleInfo) {
return articleMapper.getArticleCheck(articleInfo);
}
- mapper層
@Select("select * from articleinfo where id = #{id} and uid = #{uid}")
ArticleInfo getArticleCheck(ArticleInfo articleInfo);//檢查權(quán)限的查詢文章
@Select("select * from articleinfo where id = #{id}")
ArticleInfo getArticle(ArticleInfo articleInfo);
-
攔截器配置
- 攔截,不排除
3.1.3 前端代碼
<script>
var aid = getParamValue("aid");
// 1. 校驗(yàn)參數(shù)
function init() {
if (aid == null || aid <= 0) {
alert("非法參數(shù)!");
location.href = "myblog_lists.html";
return false;
}
// 2. 查詢文章
jQuery.ajax({
url: "/art/get_art",
method: "post",
contentType: "application/json; charset=utf8",
data: JSON.stringify({
id: aid,
}),
success: function (body) {
if (body.code == 302) {
location.href = body.msg;
return false;
}
if (body.code == 200) {
jQuery("#text").val(body.data.title);
jQuery("#content").val(body.data.content);
jQuery("#summary").val(body.data.summary);//用隱藏輸入框保存摘要信息
} else {
alert("發(fā)布失?。? + body.msg);
}
},
});
}
init();
</script>
注意:
- 如果直接寫(xiě)代碼的話,而不是調(diào)用方法,默認(rèn)頁(yè)面跟代碼一起加載,而調(diào)用方法是頁(yè)面加載后調(diào)用此init方法
- 如果不采取這種方式的話,會(huì)導(dǎo)致請(qǐng)求返回的頁(yè)面,被攔截器攔下
- 為什么還是用json而不是用querystring直接發(fā)送請(qǐng)求
- 習(xí)慣吧,因?yàn)閖son比較通用,如果還需要其他信息,querystring不方便
- 修改頁(yè)跟添加頁(yè)是一樣的,為什么不重用?
- 重用會(huì)導(dǎo)致一些沒(méi)有必要的判斷,不符合單一設(shè)計(jì)原則,麻煩/亂/開(kāi)發(fā)不舒適,耦合度高…
3.1.4 測(cè)試
3.2 修改文章
3.2.1 約定前后端交互接口
后端:
- /art/update
- 接受文章數(shù)據(jù)
- 返回受影響行數(shù)
前端:
- /art/update
- post,json,上傳文章數(shù)據(jù)
- 成功則跳轉(zhuǎn)到我的博客列表頁(yè)
3.2.2 后端代碼
- controller層
@RequestMapping("/update")
public CommonResult update(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {
// 0. 確認(rèn)用戶
int uid = SessionUtils.getUser(request).getId();
articleInfo.setUid(uid);
// 1. 校驗(yàn)參數(shù)
if(!APPUtils.hasLength(articleInfo.getContent(), articleInfo.getSummary(), articleInfo.getTitle())) {
return CommonResult.fail(-1, "非法參數(shù)!");
}
// 2. 修改
int rows = articleService.update(articleInfo);
// 3. 返回
return CommonResult.success(rows);
}
- service層
public int update(ArticleInfo articleInfo) {
return articleMapper.updateArticle(articleInfo);
}
-
mapper層
- 必須是有權(quán)限才能修改
- 更新時(shí)間修改為當(dāng)下
@Update("update articleinfo set content = #{content}, title = #{title}, summary = #{summary}, updatetime = now() where id = #{id} and uid = #{uid}")
int updateArticle(ArticleInfo articleInfo);
-
攔截器配置
- 攔截,不排除
3.2.3 前端代碼
function update() {
if (aid == null || aid <= 0) {
alert("非法參數(shù)!");
location.href = "myblog_lists.html";
return false;
}
var title = jQuery("#text");
var content = jQuery("#content");
// 1. 參數(shù)校驗(yàn)
if (title.val().trim() == "") {
alert("標(biāo)題不能為空!");
title.focus();
return false;
}
if (content.val().trim() == "") {
alert("正文不能為空!");
content.focus();
return false;
}
// 2. 輸入摘要
var summary = prompt("請(qǐng)輸入摘要:", jQuery("#summary").val());
if (summary.trim() == "") {
return false;
}
jQuery("#summary").val(summary);
// 3. 發(fā)送請(qǐng)求
jQuery.ajax({
url: "/art/update",
method: "POST",
contentType: "application/json; charset=utf8",
data: JSON.stringify({
id: aid,
title: title.val().trim(),
content: content.val().trim(),
summary: summary.trim(),
}),
// 3. 處理響應(yīng)
success: function (body) {
if (body.code == 302) {
location.href = body.msg;
return false;
}
if (body.code == 200 && body.data == 1) {
location.href = "myblog_lists.html";
} else {
alert("修改失?。? + body.msg);
}
},
});
}
3.2.4 測(cè)試
4. 博客詳情頁(yè)
4.1 期待效果
- 根據(jù)是否登錄,改變導(dǎo)航欄
- 根據(jù)querystring中的aid,顯示對(duì)應(yīng)的博文,和作者信息
- 每次訪問(wèn)成功,閱讀量加1(本次顯示是加1之前)
- 作者的文章總數(shù)通過(guò)后端計(jì)算
- 正文以html的樣式渲染出來(lái)
這樣的復(fù)雜查詢可以用到并發(fā)編程:
- 【JavaEE】Callable接口(NO.6線程創(chuàng)建方法)-JUC的常見(jiàn)類-與線程安全有關(guān)集合類_s:103的博客-CSDN博客
- 用有返回值的線程創(chuàng)建方式(獲取的時(shí)候若未結(jié)束,等待…)
4.2 約定前后端交換接口
后端:
- /art/detail
- 通過(guò)aid,找到文章
- 通過(guò)文章,uid找到作者,查詢總文章數(shù),通過(guò)aid修改文章閱讀量
- 返回:
- “l(fā)ogin”,true/false,true代表登錄中
- “count”,文章數(shù)
- “user”,用戶
- “art”,文章
前端:
- /art/detail
- json,aid
- 接受響應(yīng),投喂給代碼
4.3 后端代碼
-
controller層
- 查詢文章信息
- 校驗(yàn)文章是否存在
- 根據(jù)uid查詢用戶總文章數(shù)的任務(wù)
- 根據(jù)uid查詢用戶信息的任務(wù)
- 根據(jù)aid更新閱讀量的任務(wù)
- 線程池執(zhí)行任務(wù)
- 構(gòu)造響應(yīng)數(shù)據(jù),并返回
@Autowired
private ArticleService articleService;
@Autowired
private UserService userService;
@RequestMapping("/detail")
public CommonResult detail(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) throws ExecutionException, InterruptedException {
// 1. 查詢文章信息
ArticleInfo art = articleService.getArtByAid(articleInfo);
// 2. 校驗(yàn)文章是否存在
if(art == null) {
return CommonResult.fail(-1, "非法參數(shù)!");
}
// 3. 根據(jù)uid查詢用戶總文章數(shù)的任務(wù)
FutureTask<Integer> task1 = new FutureTask<Integer>(() -> {
return articleService.getArtNumberByUid(art.getUid());
});
// 4. 根據(jù)uid查詢用戶信息的任務(wù)
FutureTask<UserInfo> task2 = new FutureTask<UserInfo>(() -> {
return userService.getUserByUid(art.getUid());
});
// 5. 根據(jù)aid更新閱讀量的任務(wù)
FutureTask<Integer> task3 = new FutureTask<Integer>(() -> {
return articleService.incrementRCount(art.getId());
});
// 6. 線程池執(zhí)行任務(wù)
APPUtils.THREAD_POOL.submit(task1);
APPUtils.THREAD_POOL.submit(task2);
APPUtils.THREAD_POOL.submit(task3);
// 7. 構(gòu)造響應(yīng)數(shù)據(jù),并返回
Map<String, Object> map = new HashMap<>();
map.put("login", SessionUtils.getUser(request) != null);
map.put("count", task1.get());
map.put("user", task2.get());
map.put("art", art);
return CommonResult.success(map);
}
- service層
ArticleService:
public int getArtNumberByUid(int uid) {
return articleMapper.getArtNumberByUid(uid);
}
public int incrementRCount(int aid) {
return articleMapper.incrementRCount(aid);
}
UserService:
public UserInfo getUserByUid(int uid) {
return userMapper.getUserByUid(uid);
}
- mapper層
ArticleMapper:
@Select("select count(*) from articleinfo where uid=#{uid}")
int getArtNumberByUid(@Param("uid") int uid);
@Update("update articleinfo set rcount = rcount + 1 where id = #{aid}")
int incrementRCount(@Param("aid") int aid);
UserMapper:
@Select("select * from userinfo where id = #{uid}")
UserInfo getUserByUid(@Param("uid") int uid);
-
攔截器配置
- 排除攔截
- editor.md是個(gè)目錄,要排除整個(gè)目錄才對(duì),不然后面渲染不上去,之前可以渲染是因?yàn)槲覀兲幱诘卿洜顟B(tài)~
- 因?yàn)樵斍轫?yè)不需要登錄~
4.4 前端代碼
- 導(dǎo)航欄
- 網(wǎng)頁(yè)圖標(biāo)
- 右側(cè)用戶卡片
- 右側(cè)文章信息
var aid = getParamValue("aid");
function init() {
if (aid == null || aid <= 0) {
alert("非法參數(shù)!");
return false;
}
jQuery.ajax({
method: "post",
url: "/art/detail",
contentType: "application/json; charset=utf8",
data: JSON.stringify({
id: aid,
}),
success: function (body) {
if (body.code == 200) {
// 1. 導(dǎo)航欄顯示
if (body.data.login == false) {
jQuery("#icon").attr("href", "img/logo2.png");
jQuery(".navigation img").attr("src", " img/logo2.png");
jQuery(".navigation .space").css("width", "75%");
jQuery(".title").text("未登錄");
jQuery("#add").hide();
jQuery("#logout").text("登錄");
jQuery("#logout").attr("href", "blog_login.html");
}
// 2. 文章數(shù)顯示
jQuery("#count").text(body.data.count);
// 3. 用戶信息顯示
jQuery(".card img").attr("src", body.data.user.photo);
jQuery(".card h3").text(body.data.user.name);
if (body.data.user.git.trim() != "") {
jQuery(".card a").attr("href", body.data.user.git);
}
// 4. 文章信息顯示
jQuery(".article h3").text(body.data.art.title);
jQuery(".article .date").text(
body.data.art.createtime + " 閱讀量:" + body.data.art.rcount
);
editormd.markdownToHTML("pc", {
markdown: body.data.art.content,
});
} else {
alert("查看失敗:" + body.msg);
}
},
});
}
init();
4.5 測(cè)試
文章到此結(jié)束!謝謝觀看
可以叫我 小馬,我可能寫(xiě)的不好或者有錯(cuò)誤,但是一起加油鴨??!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-695871.html代碼:myblog_system/src · 游離態(tài)/馬拉圈2023年9月 - 碼云 - 開(kāi)源中國(guó) (gitee.com)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-695871.html
到了這里,關(guān)于【個(gè)人博客系統(tǒng)網(wǎng)站】我的博客列表頁(yè) · 增刪改我的博文 · 退出登錄 · 博客詳情頁(yè) · 多線程應(yīng)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!