diff --git a/.gitignore b/.gitignore index 26eb1be..9d19433 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ .idea/ +# 忽略生成的目标文件所在文件夹 target/ # 忽略上传图片的文件夹 upload/ # 忽略日志文件夹 logs/ +# 忽略缓存文件夹 +cache/ + # Compiled class file *.class diff --git a/cache/.ehcache-diskstore.lock b/cache/.ehcache-diskstore.lock deleted file mode 100644 index e69de29..0000000 diff --git a/cache/blog-cache.data b/cache/blog-cache.data deleted file mode 100644 index dfdf1f2..0000000 Binary files a/cache/blog-cache.data and /dev/null differ diff --git a/src/main/java/cc/bnblogs/Application.java b/src/main/java/cc/bnblogs/Application.java index 7c7ce49..a69c1d2 100644 --- a/src/main/java/cc/bnblogs/Application.java +++ b/src/main/java/cc/bnblogs/Application.java @@ -3,6 +3,7 @@ package cc.bnblogs; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; +import org.springframework.scheduling.annotation.EnableAsync; /** @@ -10,6 +11,7 @@ import org.springframework.cache.annotation.EnableCaching; * @createTime: 2022/10/16 */ @EnableCaching +@EnableAsync @SpringBootApplication public class Application { public static void main(String[] args) { diff --git a/src/main/java/cc/bnblogs/common/MailHelper.java b/src/main/java/cc/bnblogs/common/MailHelper.java index f0d781f..56e9923 100644 --- a/src/main/java/cc/bnblogs/common/MailHelper.java +++ b/src/main/java/cc/bnblogs/common/MailHelper.java @@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import javax.mail.MessagingException; @@ -31,6 +32,7 @@ public class MailHelper { * @param subject 主题 * @param text 内容 */ + @Async public void sendMail(String toSend, String subject, String text) { MimeMessage message = javaMailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message); diff --git a/src/main/java/cc/bnblogs/common/WebSite.java b/src/main/java/cc/bnblogs/common/WebSite.java index ea8d1c7..1efb841 100644 --- a/src/main/java/cc/bnblogs/common/WebSite.java +++ b/src/main/java/cc/bnblogs/common/WebSite.java @@ -14,6 +14,7 @@ import java.util.List; @Component @ConfigurationProperties(prefix = "website") public class WebSite { + public static final String LOGIN_SIGN = "login_sign"; // 站点名称 private String title; // SEO的关键字 @@ -22,6 +23,10 @@ public class WebSite { private String description; // 站长昵称 private String nickname; + // 管理员姓名 + private String username; + // 管理员密码 + private String password; // 站长头像 private String avatar; // 站长坐标 diff --git a/src/main/java/cc/bnblogs/config/WebConfig.java b/src/main/java/cc/bnblogs/config/WebConfig.java index 7d8cc3a..c83304d 100644 --- a/src/main/java/cc/bnblogs/config/WebConfig.java +++ b/src/main/java/cc/bnblogs/config/WebConfig.java @@ -1,9 +1,9 @@ package cc.bnblogs.config; import cc.bnblogs.common.LRUCache; -import cc.bnblogs.common.Result; -import com.fasterxml.jackson.databind.ObjectMapper; +import cc.bnblogs.interceptor.LoginInterceptor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.server.ConfigurableWebServerFactory; import org.springframework.boot.web.server.ErrorPage; @@ -11,12 +11,10 @@ import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.File; /** @@ -30,8 +28,23 @@ public class WebConfig implements WebMvcConfigurer { @Value("${upload.base-dir}") private String baseDir; + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册拦截器,添加拦截路由和放行路由 + registry.addInterceptor(loginInterceptor) + .addPathPatterns("/admin/**") + .excludePathPatterns("/admin/login","/admin/logout","/admin/login.html"); + } + + private final LoginInterceptor loginInterceptor; + public static final Integer MAX_LRU_CACHE_SIZE = 20; + public WebConfig(LoginInterceptor loginInterceptor) { + this.loginInterceptor = loginInterceptor; + } + + @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 创建static目录到/static/的路由 diff --git a/src/main/java/cc/bnblogs/controller/AdminController.java b/src/main/java/cc/bnblogs/controller/AdminController.java index 928a6dd..4639253 100644 --- a/src/main/java/cc/bnblogs/controller/AdminController.java +++ b/src/main/java/cc/bnblogs/controller/AdminController.java @@ -1,15 +1,24 @@ package cc.bnblogs.controller; +import cc.bnblogs.common.ArticleSearch; +import cc.bnblogs.common.Result; +import cc.bnblogs.common.WebSite; import cc.bnblogs.pojo.Article; import cc.bnblogs.pojo.Category; import cc.bnblogs.service.ArticleService; import cc.bnblogs.service.CategoryService; +import cc.bnblogs.service.CommentService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; +import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.thymeleaf.util.StringUtils; +import javax.servlet.http.HttpSession; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Objects; @@ -22,14 +31,25 @@ import java.util.Objects; public class AdminController { private final CategoryService categoryService; private final ArticleService articleService; - - public AdminController(CategoryService categoryService, ArticleService articleService) { + private final CommentService commentService; + private final WebSite webSite; + public AdminController(CategoryService categoryService, ArticleService articleService, CommentService commentService, WebSite webSite) { this.categoryService = categoryService; this.articleService = articleService; + this.commentService = commentService; + this.webSite = webSite; } @GetMapping("/") - public String index() { + public String index(Model model) { + // 获取文章总数、分类总数、总评论数、未读评论数、最新的5篇文章、最新的5条评论 + model.addAttribute("ArticleCount",articleService.count()); + model.addAttribute("CategoryCount",categoryService.count()); + model.addAttribute("CommentAll",commentService.count(null)); + model.addAttribute("CommentNotReadCount",commentService.count(false)); + model.addAttribute("NewArticleList",articleService.search(ArticleSearch.builder() + .type(Article.TYPE_ARTICLE).pageNum(1).pageSize(5).build()).getRows()); + model.addAttribute("NewCommentList",commentService.list(null,1,5).getRows()); return "admin/index"; } @GetMapping("/category.html") @@ -56,7 +76,9 @@ public class AdminController { } @GetMapping("/comment.html") - public String comment() { + public String comment(@RequestParam(required = false)Boolean view, Model model) { + // 给前端返回一个isView参数用来选中对应按扭 + model.addAttribute("isView",view); return "admin/comment"; } @@ -77,4 +99,40 @@ public class AdminController { model.addAttribute("pageTitle", Objects.isNull(article.getId()) ? "创建新文章" : "编辑文章---" + article.getTitle()); return "admin/write"; } + + /** + * 前台访问登陆页面 + * @return + */ + @GetMapping("/login.html") + public String login() { + return "admin/login"; + } + + /** + * 登录校验 + * @param username 用户名 + * @param password 密码 + * @return + */ + @PostMapping("/login") + public String login(String username, String password, Model model, HttpSession session) { + // 用户名和密码都一致,登录成功 + if (StringUtils.equals(webSite.getPassword(), DigestUtils + .md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8))) + && StringUtils.equals(username,webSite.getUsername())) { + session.setAttribute(WebSite.LOGIN_SIGN,true); + return "redirect:/admin/"; + } + else { + model.addAttribute("errorMsg","用户名或密码错误!"); + return "admin/login"; + } + } + + @GetMapping("/logout") + public String logout(HttpSession session) { + session.removeAttribute(WebSite.LOGIN_SIGN); + return "admin/login"; + } } diff --git a/src/main/java/cc/bnblogs/controller/CommentController.java b/src/main/java/cc/bnblogs/controller/CommentController.java index e8e7365..87131f5 100644 --- a/src/main/java/cc/bnblogs/controller/CommentController.java +++ b/src/main/java/cc/bnblogs/controller/CommentController.java @@ -1,9 +1,15 @@ package cc.bnblogs.controller; +import cc.bnblogs.common.PageHelper; import cc.bnblogs.common.Result; +import cc.bnblogs.common.WebSite; import cc.bnblogs.enums.ResultEnum; +import cc.bnblogs.pojo.Article; import cc.bnblogs.pojo.Comment; import cc.bnblogs.service.CommentService; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -17,18 +23,29 @@ import java.util.Objects; @RequestMapping("/admin/comment") public class CommentController { private final CommentService commentService; + private final WebSite webSite; - public CommentController(CommentService commentService) { + + public CommentController(CommentService commentService, WebSite webSite) { this.commentService = commentService; + this.webSite = webSite; } /** - * 请求所有评论的接口 - * @return 返回所有评论 + * 根据评论是否已读返回分页后的评论列表 + * 按评论创建时间降序返回 + * @param view 是否已读 + * @param pageNumber 页号 + * @param pageSize 页大小 + * @return 分页后的评论 */ @GetMapping("/") - public Result> list() { - return Result.success(commentService.list()); + public Result> list(@RequestParam(required = false) Boolean view, + @RequestParam(required = false,defaultValue = "1") Integer pageNumber, + @RequestParam(required = false,defaultValue = "1")Integer pageSize) { + pageNumber = Math.max(1,pageNumber); + pageSize = Math.max(1,pageSize); + return Result.success(commentService.list(view,pageNumber,pageSize)); } /** @@ -67,4 +84,37 @@ public class CommentController { commentService.delete(id); return Result.success(); } + + /** + * 一键已读所有评论 + */ + @GetMapping("/read") + public Result readAll(){ + commentService.readAll(); + return Result.success(); + } + + /** + * 回复评论 + * @param pid 父评论id + * @param aid 文章id + * @param message 回复内容 + * @return 操作结果 + */ + @PostMapping("/{pid}") + public Result reply(@PathVariable Integer pid,Integer aid,String message) { + // 构造一个comment对象 + // 填充站长的昵称、邮箱、网站地址、父评论id、文章id、回复内容 + Comment comment = Comment.builder() + .article(Article.builder().id(aid).build()) + .nickname(webSite.getNickname()) + .email(webSite.getMail()) + .url(webSite.getDomain()) + .pid(pid) + .content(message) + .build(); + // 保存评论 + commentService.save(comment); + return Result.success(); + } } diff --git a/src/main/java/cc/bnblogs/interceptor/LoginInterceptor.java b/src/main/java/cc/bnblogs/interceptor/LoginInterceptor.java new file mode 100644 index 0000000..be4535e --- /dev/null +++ b/src/main/java/cc/bnblogs/interceptor/LoginInterceptor.java @@ -0,0 +1,33 @@ +package cc.bnblogs.interceptor; + +import cc.bnblogs.common.WebSite; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.util.Objects; + +/** + * @author zfp@bnblogs.cc + * @createTime: 2022/10/23 + * @description: 登录拦截器 + */ +@Component +public class LoginInterceptor implements HandlerInterceptor { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + HttpSession session = request.getSession(); + Boolean sign = (Boolean) session.getAttribute(WebSite.LOGIN_SIGN); + if (Objects.nonNull(sign) && sign) { + return true; + } + else { + request.setAttribute("errorMsg","请登录后再操作!"); + // 当Session中没有登录信息时我们直接转发到登录页面并给出请登录后再进行操作的提示 + request.getRequestDispatcher("/admin/login.html").forward(request,response); + return false; + } + } +} diff --git a/src/main/java/cc/bnblogs/mapper/CommentMapper.java b/src/main/java/cc/bnblogs/mapper/CommentMapper.java index 300758e..bfeff4c 100644 --- a/src/main/java/cc/bnblogs/mapper/CommentMapper.java +++ b/src/main/java/cc/bnblogs/mapper/CommentMapper.java @@ -5,6 +5,9 @@ import cc.bnblogs.pojo.Comment; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -35,4 +38,27 @@ public interface CommentMapper extends JpaRepository { * @return 该父评论下的所有评论 */ List findAllByPidOrderByCreatedDesc(Integer pid); + + /** + * 将所有未读评论改为已读 + */ + @Modifying + @Transactional(rollbackFor = {Exception.class}) + @Query(value = "update blog_comment set view=true where view=false ", nativeQuery = true) + void readAll(); + + /** + * 根据view选择不同的评论 + * @param view 是否已读 + * @param pageable 分页器 + * @return 评论列表 + */ + Page findAllByView(Boolean view, Pageable pageable); + + /** + * 根据view的值统计评论数 + * @param view 是否已读 + * @return 评论个数 + */ + Long countCommentByView(Boolean view); } diff --git a/src/main/java/cc/bnblogs/service/CommentService.java b/src/main/java/cc/bnblogs/service/CommentService.java index c48c8ae..150789d 100644 --- a/src/main/java/cc/bnblogs/service/CommentService.java +++ b/src/main/java/cc/bnblogs/service/CommentService.java @@ -10,7 +10,8 @@ import cc.bnblogs.pojo.Comment; import cc.bnblogs.utils.UpdateUtil; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.scheduling.annotation.Async; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import java.util.Date; @@ -48,12 +49,13 @@ public class CommentService { } /** - * 获取评论总数 - * - * @return 评论总数 + * 根据是否view的取值返回评论数(null:表示所有) + * @param view 是否已读 + * @return 评论个数 */ - public long count() { - return commentMapper.count(); + public long count(Boolean view) { + return Objects.isNull(view) ? + commentMapper.count(): commentMapper.countCommentByView(view); } /** @@ -87,7 +89,9 @@ public class CommentService { comment.setPid(findCommentPid(comment.getPid())); } commentMapper.save(comment); - } else { + } + // 修改评论内容 + else { Comment one = detail(comment.getId()); UpdateUtil.copyNullProperties(comment, one); commentMapper.save(one); @@ -99,7 +103,6 @@ public class CommentService { * * @param id 文章id */ - @Async public void sendMailToWebsite(Integer id) { Article article = articleMapper.findById(id).orElse(null); if (Objects.isNull(article)) { @@ -119,7 +122,6 @@ public class CommentService { * @param cid 被评论的评论id * @param reply 回复内容 */ - @Async public void sendMailToComment(Integer id, Integer cid, String reply) { Article article = articleMapper.findById(id).orElse(null); if (Objects.isNull(article)) { @@ -170,4 +172,17 @@ public class CommentService { // 评论内容-当前页数-评论总数-总页数 return PageHelper.builder().rows(page.getContent().stream().peek(x -> x.setChildren(commentMapper.findAllByPidOrderByCreatedDesc(x.getId()))).collect(Collectors.toList())).currentPage(pageNumber).total(page.getTotalElements()).totalPages(page.getTotalPages()).build(); } + + public void readAll() { + commentMapper.readAll(); + } + + public PageHelper list(Boolean view, Integer pageNumber, Integer pageSize) { + Pageable pageable = PageRequest.of(pageNumber-1,pageSize, Sort.by(Sort.Direction.DESC,"created")); + Page page = Objects.isNull(view) ? commentMapper.findAll(pageable) : commentMapper.findAllByView(view,pageable); + return PageHelper.builder() + .rows(page.getContent()) + .total(page.getTotalElements()) + .build(); + } } diff --git a/src/main/java/cc/bnblogs/utils/CookieUtil.java b/src/main/java/cc/bnblogs/utils/CookieUtil.java index 250a2b2..7bf9f26 100644 --- a/src/main/java/cc/bnblogs/utils/CookieUtil.java +++ b/src/main/java/cc/bnblogs/utils/CookieUtil.java @@ -31,8 +31,8 @@ public class CookieUtil { } public static void setCookie(HttpServletResponse response, String cookieName, String value) { - // 有效期为7天 - setCookie(response, cookieName, value, 7 * 24 * 60 * 60); + // 有效期为1天 + setCookie(response, cookieName, value, 24 * 60 * 60); } public static void deleteCookie(HttpServletResponse response, String cookieName) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f80f902..5835d20 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -73,6 +73,8 @@ website: domain: http://localhost:8080 #域名 avatar: https://hugo.bnblogs.cc/images/img/20220215001349.png nickname: barney + username: admin + password: 0192023a7bbd73250516f069df18b500 address: 广东 广州 tags: - java diff --git a/src/main/resources/templates/admin/article.html b/src/main/resources/templates/admin/article.html index aa7d2e4..7be2606 100644 --- a/src/main/resources/templates/admin/article.html +++ b/src/main/resources/templates/admin/article.html @@ -10,7 +10,7 @@
@@ -41,8 +41,8 @@
- - + +
@@ -60,6 +60,7 @@ pageSize: 5, // 每页5条数据 pageList: [5, 10, 15], // 可选页大小 responseHandler: function (res) { + console.log(res.data); return res.data }, //这个是查询参数,就是bootstrap-table请求后端时携带的参数 diff --git a/src/main/resources/templates/admin/banner.html b/src/main/resources/templates/admin/banner.html index c1a4c9c..bada408 100644 --- a/src/main/resources/templates/admin/banner.html +++ b/src/main/resources/templates/admin/banner.html @@ -10,10 +10,10 @@
- -
@@ -70,8 +70,8 @@
@@ -135,8 +135,8 @@ align: "center", width: 180, formatter: function (value) { - return ` - ` + return ` + ` } } ], diff --git a/src/main/resources/templates/admin/category.html b/src/main/resources/templates/admin/category.html index dd322b1..cb9f3dd 100644 --- a/src/main/resources/templates/admin/category.html +++ b/src/main/resources/templates/admin/category.html @@ -8,7 +8,8 @@
- +
@@ -36,8 +37,8 @@ @@ -75,8 +76,8 @@ align: "center", width: 180, formatter: function (value) { - return ` - ` + return ` + ` } } ], diff --git a/src/main/resources/templates/admin/comment.html b/src/main/resources/templates/admin/comment.html index e6b1a23..9344de0 100644 --- a/src/main/resources/templates/admin/comment.html +++ b/src/main/resources/templates/admin/comment.html @@ -1,232 +1,219 @@ - - 评论管理 + + 评论管理 +
-
- -
-
-
- - @@ -58,13 +58,12 @@ diff --git a/src/main/resources/templates/admin/friends.html b/src/main/resources/templates/admin/friends.html index df6aac6..48ca519 100644 --- a/src/main/resources/templates/admin/friends.html +++ b/src/main/resources/templates/admin/friends.html @@ -10,7 +10,7 @@
-
@@ -43,8 +43,8 @@
@@ -87,8 +87,8 @@ align: "center", width: 180, formatter: function (value) { - return ` - ` + return ` + ` } } ], diff --git a/src/main/resources/templates/admin/index.html b/src/main/resources/templates/admin/index.html index 5d80ffc..6d99b74 100644 --- a/src/main/resources/templates/admin/index.html +++ b/src/main/resources/templates/admin/index.html @@ -10,9 +10,9 @@

网站概要

-

目前有 83 篇文章, 并有 5010 条关于你的评论在 9 个分类中.

-

其中有 12条 评论未查看:

-

点此查看

+

目前有 篇文章, 并有 条关于你的评论在 个分类中.

+

其中有 条 评论未查看:

+

点此查看

@@ -20,25 +20,9 @@
  • 最新文章
  • -
  • - 09-28 - Conda虚拟环境使用 -
  • -
  • - 05-26 - 关于我这些年的经历 -
  • -
  • - 04-28 - 我曾是少年 -
  • -
  • - 03-07 - 迷茫 -
  • -
  • - 02-10 - Spring Boot 3.0 M1 发布 +
  • + +
  • @@ -47,26 +31,11 @@
  • 最新评论
  • -
  • - 09-29 - 再度再度: 发现这个主题很特别! -
  • -
  • - 09-29 - 再度再度: 就OK间科技看 -
  • -
  • - 09-28 - duelex: 喜欢作者的这个风格,希望作者不断进步 -
  • -
  • - 09-27 - 蜘蛛: 阿巴阿巴 -
  • -
  • - 09-10 - 妄想: 需要插件 +
  • + +
  • +
    diff --git a/src/main/resources/templates/admin/login.html b/src/main/resources/templates/admin/login.html index 98539be..831508f 100644 --- a/src/main/resources/templates/admin/login.html +++ b/src/main/resources/templates/admin/login.html @@ -1,5 +1,5 @@ - + Title @@ -7,29 +7,36 @@ + diff --git a/src/main/resources/templates/admin/navigation.html b/src/main/resources/templates/admin/navigation.html index dc0c1d0..cbc101c 100644 --- a/src/main/resources/templates/admin/navigation.html +++ b/src/main/resources/templates/admin/navigation.html @@ -10,11 +10,11 @@
    - -
    @@ -74,8 +74,8 @@
    @@ -150,7 +150,8 @@ align: "center", width: 180, formatter: function (value) { - return `` + return ` + ` } } ] diff --git a/src/test/java/cc/bnblogs/test/TestMd5Password.java b/src/test/java/cc/bnblogs/test/TestMd5Password.java new file mode 100644 index 0000000..c010823 --- /dev/null +++ b/src/test/java/cc/bnblogs/test/TestMd5Password.java @@ -0,0 +1,23 @@ +package cc.bnblogs.test; + +import cc.bnblogs.Application; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.DigestUtils; + +import java.nio.charset.StandardCharsets; + +/** + * @author zfp@bnblogs.cc + * @createTime: 2022/10/23 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class TestMd5Password { + @Test + public void testMd5() { + System.out.println(DigestUtils.md5DigestAsHex("admin123".getBytes(StandardCharsets.UTF_8))); + } +}