博客管理系统

文章目录

  • 博客管理系统
    • 一、项目演示
    • 二、项目介绍
    • 三、系统部分功能截图
    • 四、部分代码展示
    • 五、底部获取项目(9.9¥带走)

博客管理系统

一、项目演示

博客系统

二、项目介绍

三个角色:游客 用户 管理员

游客可以浏览文章, 游客可以登录注册成用户,发布文章 管理自己的文章,评论和回复,点赞评论回复文章等

管理员可以对整个系统用户管理,文章管理,分类管理,角色权限管理,评论管理等等

2、项目技术
语言:java
框架:SpringBoot、MyBatis、JQuery、html
数据库:MySQL

三、系统部分功能截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、部分代码展示

package com.example.forum.config.shiro;import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import com.example.forum.common.constant.CommonConstant;
import com.example.forum.entity.Permission;
import com.example.forum.entity.Role;
import com.example.forum.service.PermissionService;
import com.example.forum.service.RoleService;
import com.example.forum.service.UserService;
import com.example.forum.entity.User;
import com.example.forum.enums.CommonParamsEnum;
import com.example.forum.enums.TrueFalseEnum;
import com.example.forum.enums.UserStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;@Slf4j
public class MyRealm extends AuthorizingRealm {@Autowired@Lazyprivate UserService userService;@Autowired@Lazyprivate RoleService roleService;@Autowired@Lazyprivate PermissionService permissionService;/*** 认证信息(身份验证) Authentication 是用来验证用户身份*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {log.info("认证-->MyShiroRealm.doGetAuthenticationInfo()");//1.验证用户名User user;String account = (String) token.getPrincipal();if (Validator.isEmail(account)) {user = userService.findByEmail(account);} else {user = userService.findByUserName(account);}if (user == null) {//用户不存在log.info("用户不存在! 登录名:{}, 密码:{}", account, token.getCredentials());return null;}Role role = roleService.findByUserId(user.getId());if (role != null) {user.setRole(role.getRole());}//2.判断账号是否被封号if (!Objects.equals(user.getStatus(), UserStatusEnum.NORMAL.getCode())) {throw new LockedAccountException("账号被封禁");}//3.首先判断是否已经被禁用已经是否已经过了10分钟Date loginLast = DateUtil.date();if (null != user.getLoginLast()) {loginLast = user.getLoginLast();}Long between = DateUtil.between(loginLast, DateUtil.date(), DateUnit.MINUTE);if (StringUtils.equals(user.getLoginEnable(), TrueFalseEnum.FALSE.getValue()) && (between < CommonParamsEnum.TEN.getValue())) {log.info("账号已锁定! 登录名:{}, 密码:{}", account, token.getCredentials());throw new LockedAccountException("账号被锁定,请10分钟后再试");}//4.封装authenticationInfo,准备验证密码SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, // 用户名user.getUserPass(), // 密码ByteSource.Util.bytes(CommonConstant.PASSWORD_SALT), // 盐getName() // realm name);System.out.println("realName:" + getName());return authenticationInfo;}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();User user = (User) principals.getPrimaryPrincipal();Role role = roleService.findByRoleId(user.getId());authorizationInfo.addRole(role.getRole());List<Permission> permissions = permissionService.listPermissionsByRoleId(role.getId());//把权限的URL全部放到authorizationInfo中去Set<String> urls = permissions.stream().map(p -> p.getUrl()).collect(Collectors.toSet());authorizationInfo.addStringPermissions(urls);return authorizationInfo;}
}
package com.example.forum.controller.admin;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.forum.controller.common.BaseController;
import com.example.forum.entity.Category;
import com.example.forum.dto.JsonResult;
import com.example.forum.service.CategoryService;
import com.example.forum.util.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;/*** <pre>*     后台分类管理控制器* </pre>**/
@Slf4j
@Controller
@RequestMapping(value = "/admin/category")
public class CategoryController extends BaseController {@Autowiredprivate CategoryService categoryService;/*** 查询所有分类并渲染category页面** @return 模板路径admin/admin_category*/@GetMappingpublic String categories(@RequestParam(value = "page", defaultValue = "0") Integer pageNumber,@RequestParam(value = "size", defaultValue = "10") Integer pageSize,@RequestParam(value = "sort", defaultValue = "cateSort") String sort,@RequestParam(value = "order", defaultValue = "desc") String order, Model model) {Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order);Page<Category> categoryPage = categoryService.findAll(page);model.addAttribute("categories", categoryPage.getRecords());model.addAttribute("pageInfo", PageUtil.convertPageVo(page));return "admin/admin_category";}/*** 新增/修改分类目录** @param category category对象* @return 重定向到/admin/category*/@PostMapping(value = "/save")@ResponseBodypublic JsonResult saveCategory(@ModelAttribute Category category) {categoryService.insertOrUpdate(category);return JsonResult.success("保存成功");}/*** 删除分类** @param cateId 分类Id* @return JsonResult*/@DeleteMapping(value = "/delete")@ResponseBodypublic JsonResult checkDelete(@RequestParam("id") Long cateId) {//1.判断这个分类有文章Integer count = categoryService.countPostByCateId(cateId);if (count != 0) {return JsonResult.error("该分类已经有了文章,无法删除");}categoryService.delete(cateId);return JsonResult.success("删除成功");}/*** 跳转到修改页面** @param cateId cateId* @param model  model* @return 模板路径admin/admin_category*/@GetMapping(value = "/edit")public String toEditCategory(Model model,@RequestParam(value = "page", defaultValue = "0") Integer pageNumber,@RequestParam(value = "size", defaultValue = "10") Integer pageSize,@RequestParam(value = "sort", defaultValue = "cateSort") String sort,@RequestParam(value = "order", defaultValue = "desc") String order,@RequestParam("id") Long cateId) {Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order);//更新的分类Category category = categoryService.get(cateId);if (category == null) {return this.renderNotFound();}model.addAttribute("updateCategory", category);// 所有分类Page<Category> categoryPage = categoryService.findAll(page);model.addAttribute("categories", categoryPage.getRecords());model.addAttribute("pageInfo", PageUtil.convertPageVo(page));return "admin/admin_category";}
}
package com.example.forum.controller.admin;import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.forum.controller.common.BaseController;
import com.example.forum.entity.Comment;
import com.example.forum.entity.Post;
import com.example.forum.entity.User;
import com.example.forum.exception.MyBusinessException;
import com.example.forum.dto.JsonResult;
import com.example.forum.dto.QueryCondition;
import com.example.forum.enums.*;
import com.example.forum.service.CommentService;
import com.example.forum.service.PostService;
import com.example.forum.service.UserService;
import com.example.forum.util.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.Objects;/*** <pre>*     后台回复管理控制器* </pre>*/
@Slf4j
@Controller
@RequestMapping(value = "/admin/comment")
public class CommentController extends BaseController {@Autowiredprivate CommentService commentService;@Autowiredprivate PostService postService;@Autowiredprivate UserService userService;/*** 渲染回复管理页面** @param model      model* @param pageNumber page 当前页码* @param pageSize   size 每页显示条数* @return 模板路径admin/admin_comment*/@GetMappingpublic String comments(Model model,@RequestParam(value = "keywords", defaultValue = "") String keywords,@RequestParam(value = "page", defaultValue = "1") Integer pageNumber,@RequestParam(value = "size", defaultValue = "15") Integer pageSize,@RequestParam(value = "sort", defaultValue = "createTime") String sort,@RequestParam(value = "order", defaultValue = "desc") String order) {Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order);Comment condition = new Comment();
//        condition.setAcceptUserId(loginUserId);condition.setCommentContent(keywords);Page<Comment> comments = commentService.findAll(page, new QueryCondition<>(condition));List<Comment> commentList = comments.getRecords();commentList.forEach(comment -> comment.setPost(postService.get(comment.getPostId())));commentList.forEach(comment -> comment.setUser(userService.get(comment.getUserId())));model.addAttribute("comments", commentList);model.addAttribute("pageInfo", PageUtil.convertPageVo(page));model.addAttribute("keywords", keywords);model.addAttribute("sort", sort);model.addAttribute("order", order);return "admin/admin_comment";}/*** 我发送的回复** @param model      model* @param pageNumber page 当前页码* @param pageSize   size 每页显示条数* @return 模板路径admin/admin_comment*/@GetMapping("/send")public String sendComments(Model model,@RequestParam(value = "keywords", defaultValue = "") String keywords,@RequestParam(value = "page", defaultValue = "1") Integer pageNumber,@RequestParam(value = "size", defaultValue = "15") Integer pageSize,@RequestParam(value = "sort", defaultValue = "createTime") String sort,@RequestParam(value = "order", defaultValue = "desc") String order) {User user = getLoginUser();Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order);Comment condition = new Comment();condition.setUserId(user.getId());condition.setCommentContent(keywords);Page<Comment> comments = commentService.findAll(page, new QueryCondition<>(condition));List<Comment> commentList = comments.getRecords();commentList.forEach(comment -> comment.setPost(postService.get(comment.getPostId())));commentList.forEach(comment -> comment.setUser(userService.get(comment.getUserId())));model.addAttribute("comments", commentList);model.addAttribute("pageInfo", PageUtil.convertPageVo(page));model.addAttribute("keywords", keywords);model.addAttribute("sort", sort);model.addAttribute("order", order);return "admin/admin_comment";}/*** 我发送的回复** @param model      model* @param pageNumber page 当前页码* @param pageSize   size 每页显示条数* @return 模板路径admin/admin_comment*/@GetMapping("/receive")public String receiveComments(Model model,@RequestParam(value = "keywords", defaultValue = "") String keywords,@RequestParam(value = "page", defaultValue = "1") Integer pageNumber,@RequestParam(value = "size", defaultValue = "15") Integer pageSize,@RequestParam(value = "sort", defaultValue = "createTime") String sort,@RequestParam(value = "order", defaultValue = "desc") String order) {User user = getLoginUser();Page page = PageUtil.initMpPage(pageNumber, pageSize, sort, order);Comment condition = new Comment();condition.setAcceptUserId(user.getId());condition.setCommentContent(keywords);Page<Comment> comments = commentService.findAll(page, new QueryCondition<>(condition));List<Comment> commentList = comments.getRecords();commentList.forEach(comment -> comment.setPost(postService.get(comment.getPostId())));commentList.forEach(comment -> comment.setUser(userService.get(comment.getUserId())));model.addAttribute("comments", commentList);model.addAttribute("pageInfo", PageUtil.convertPageVo(page));model.addAttribute("keywords", keywords);model.addAttribute("sort", sort);model.addAttribute("order", order);return "admin/admin_comment";}/*** 删除回复** @param commentId commentId* @return string 重定向到/admin/comment*/@DeleteMapping(value = "/delete")@ResponseBodypublic JsonResult moveToAway(@RequestParam("id") Long commentId) {//回复Comment comment = commentService.get(commentId);//检查权限basicCheck(comment);commentService.delete(commentId);return JsonResult.success("删除成功");}/*** 回复回复,并通过回复** @param commentId      被回复的回复* @param commentContent 回复的内容* @return 重定向到/admin/comment*/@PostMapping(value = "/reply")@ResponseBodypublic JsonResult replyComment(@RequestParam("id") Long commentId,@RequestParam("commentContent") String commentContent) {//博主信息User loginUser = getLoginUser();//被回复的回复Comment lastComment = commentService.get(commentId);User user = userService.get(lastComment.getUserId());String at = user != null ? user.getUserDisplayName() : "楼上";if (lastComment == null) {return JsonResult.error("回复不存在");}Post post = postService.get(lastComment.getPostId());if (post == null) {return JsonResult.error("文章不存在");}//保存回复Comment comment = new Comment();comment.setUserId(loginUser.getId());comment.setPostId(lastComment.getPostId());String lastContent = "<a href='#comment-id-" + lastComment.getId() + "'>@" + at + "</a> ";comment.setCommentContent(lastContent + HtmlUtil.escape(commentContent));comment.setCommentParent(commentId);comment.setAcceptUserId(lastComment.getUserId());comment.setPathTrace(lastComment.getPathTrace() + lastComment.getId() + "/");commentService.insertOrUpdate(comment);return JsonResult.success("回复成功");}/*** 批量删除** @param ids 回复ID列表* @return*/@DeleteMapping(value = "/batchDelete")@ResponseBodypublic JsonResult batchDelete(@RequestParam("ids") List<Long> ids) {//批量操作//1、防止恶意操作if (ids == null || ids.size() == 0 || ids.size() >= 100) {return new JsonResult(ResultCodeEnum.FAIL.getCode(), "参数不合法!");}//2、检查用户权限//文章作者、回复人、管理员才可以删除List<Comment> commentList = commentService.findByBatchIds(ids);for (Comment comment : commentList) {basicCheck(comment);}//3、删除commentService.batchDelete(ids);return JsonResult.success("删除成功");}/*** 检查文章是否存在和用户是否有权限控制** @param comment*/private void basicCheck(Comment comment) {Long loginUserId = getLoginUserId();if (comment == null) {throw new MyBusinessException("回复不存在");}//文章Post post = postService.get(comment.getPostId());if (post == null) {throw new MyBusinessException("回复所在文章不存在");}//检查权限,文章的作者和收到回复和管理员的可以删除if (!Objects.equals(post.getUserId(), loginUserId) && !Objects.equals(comment.getAcceptUserId(), loginUserId) && !loginUserIsAdmin()) {throw new MyBusinessException("没有权限");}}}

五、底部获取项目(9.9¥带走)

有问题,或者需要协助调试运行项目的也可以

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

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

相关文章

[Kubernetes] sealos 部署 K8s v1.25.0 集群

文章目录 1.sealos 介绍2.操作系统基础配置3.安装部署 K8s4.验证 K8s 集群5.部署测试资源 1.sealos 介绍 Sealos 是一个基于 Kubernetes 内核的云操作系统发行版。它采用云原生方式&#xff0c;摒弃传统的云计算架构&#xff0c;转向以 Kubernetes 为云内核的新架构。这使得企…

FileZilla一款免费开源的FTP软件,中文正式版 v3.67.0

01 软件介绍 FileZilla 客户端是一个高效且可信的跨平台应用程序&#xff0c;支持 FTP、 FTPS 和 SFTP 协议&#xff0c;其设计宗旨在于为用户提供一个功能丰富且直观的图形界面。此客户端的核心特性包括一个站点管理器&#xff0c;该管理器能有效地存储和管理用户连接详情及登…

tauri2.0bate版本支持移动端开发了,ios和android开发有福了

Tauri 是一个开源框架&#xff0c;用于构建轻量级、高性能的桌面应用程序。它是使用 Web 技术&#xff08;如 HTML、CSS 和 JavaScript&#xff09;来创建用户界面&#xff0c;同时利用 Rust 语言提供的api功能。Tauri 的目标是提供一种更高效、更安全的方式来开发跨平台的桌面…

OpenAI 或将推出多模态人工智能数字助理;研究发现部分 AI 系统已学会「说谎」丨 RTE 开发者日报 Vol.203

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

黄啤:醇厚与经典的传承

啤酒的历史悠久&#xff0c;种类繁多&#xff0c;而黄啤作为其中的一种经典风格&#xff0c;一直备受人们的喜爱。Fendi club黄啤作为精酿啤酒的代表&#xff0c;完善地传承了黄啤的醇厚与经典&#xff0c;为消费者带来了与众不同的口感体验。 Fendi club黄啤在酿造过程中&…

转移插槽笔记

4.3.4.转移插槽 我们要将num存储到7004节点&#xff0c;因此需要先看看num的插槽是多少&#xff1a; 如上图所示&#xff0c;num的插槽为2765. 我们可以将0~3000的插槽从7001转移到7004&#xff0c;命令格式如下&#xff1a; 具体命令如下&#xff1a; 建立连接&#xff1a;…

【C++ 】红黑树

1.1 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路 径会比其他路径长出俩倍&#xff…

R语言:肿瘤突变负荷分析

> merge_maf <- function(metadata, path){ #通过合并path,还有sample sheet前两列得到每一个文件的完整路径 filenames <- file.path(path, metadata$file_id, metadata$file_name, fsep .Platform$file.sep) message (##############…

Vulnhub-wp 获取vulnhub靶机wp搜索工具

项目地址:https://github.com/MartinxMax/vulnhub-wp 简介 搜索Vulnhub平台的解题文章,之过滤返回出正确可访问的页面 使用 $ python3 vulnhubwp.py 支持模糊搜索 [] Query: kiop 进入选项4,获取wp地址 [] Choice options: 4

DML之操作数据表

1. 插入数据 (1). 前言 前文我们实现了如果创建表&#xff0c;接下来我们将学习如何向数据表中插入数据.插入有两种方式. (2). 方式1 : 情况1 : 使用该语法一次只能向表中插入一条记录.为表中的任意字段按默认的顺序插入数据.值列表中需要为表的每一个字段指定值.并且值…

网络库-libevent介绍

1.简介 libevent是一个事件驱动的网络库&#xff0c;主要用于构建可扩展的网络服务器。它提供了跨平台的API&#xff0c;支持多种事件通知机制&#xff0c;如select、poll、epoll、kqueue等。 主要组件 event: 表示一个具体的事件&#xff0c;包括事件类型、事件回调等。eve…

【网络安全入门】你必须要有的学习工具(附安装包)零基础入门到进阶,看这一篇就够了!

工欲善其事必先利其器 在新入门网络安全的小伙伴而言。这些工具你必须要有所了解。本文我们简单说说这些网络安全工具吧&#xff01; Web安全类 Web类工具主要是通过各种扫描工具&#xff0c;发现web站点存在的各种漏洞如sql注入、xss等。从而获取系统权限&#xff0c;常用的…

iZotope RX 11 for Mac:音频修复的终极利器

在音频制作的浩瀚星海中&#xff0c;每一份声音都是珍贵的宝石&#xff0c;但往往被各种噪音、杂音所掩盖。此刻&#xff0c;iZotope RX 11 for Mac犹如一位专业的匠人&#xff0c;以其精湛的技术&#xff0c;将每一份声音雕琢至完美。 iZotope RX 11 for Mac&#xff0c;这是…

创新点!CNN与LSTM结合,实现更准预测、更快效率、更高性能!

推荐一个能发表高质量论文的好方向&#xff1a;LSTM结合CNN。 LSTM擅长捕捉序列数据中的长期依赖关系&#xff0c;而CNN则擅长提取图像数据的局部特征。通过结合两者的优势&#xff0c;我们可以让模型同时考虑到数据的时序信息和空间信息&#xff0c;减少参数降低过拟合风险&a…

MySQL—子查询

目录 ▐ 子查询概述 ▐ 准备工作 ▐ 标量子查询 ▐ 列子查询 ▐ 表子查询 ▐ 多信息嵌套 ▐ 子查询概述 • 子查询也称嵌套查询&#xff0c;即在一个查询语句中又出现了查询语句 • 子查询可以出现在from 后面 或where后面 • 出现在 from 后称表子查询&#xff0c;结…

远程终端协议TELNET

一、概述 TELNET是一个简单的远程终端协议&#xff0c;是互联网正式标准。 实现在本地对远程计算机进行操作&#xff1b;在本地键盘输入的字符通过应用层TELNET协议传输到远程服务器上&#xff0c;同时远程服务器把字符传送过来显示在本地的显示器上&#xff1b;TELNET协议采…

智能制造装备业项目数字化管理之项目模板管理

智能制造装备&#xff0c;作为工业4.0的核心组成部分&#xff0c;正日益受到全球制造业的关注。这类装备融合了信息技术和制造技术&#xff0c;旨在提高生产效率、降低成本并增强产品的个性化。然而&#xff0c;随着智能制造装备行业的飞速发展&#xff0c;项目管理复杂性也在不…

软件文档-总体测试计划书(Word原件2024)

软件资料清单列表部分文档&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&#xff0c;用户需求说明书&#xff0c;概要设计说明书&#xff0c;技术解决…

Spring事件分析以及多种使用方式实践 使用场景 附可执行demo

我们先说说它的特点&#xff0c;优缺点&#xff0c;以及使用场景&#xff0c;然后再说具体是怎么做的 Spring事件驱动的优点 松耦合 事件驱动模型通过发布-订阅机制促进组件间的解耦&#xff0c;发送者和接收者不需要直接知道对方的存在&#xff0c;只需关注事件本身&#xff…

【机器学习-06】Scikit-Learn机器学习工具包进阶指南:机器学习分类模型实战与数据可视化分析

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…