博客管理系统

文章目录

  • 博客管理系统
    • 一、项目演示
    • 二、项目介绍
    • 三、系统部分功能截图
    • 四、部分代码展示
    • 五、底部获取项目(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;该管理器能有效地存储和管理用户连接详情及登…

c++ (C++ Primer 中文版(第 5 版))奇妙判奇偶

奇妙判奇偶 平时&#xff0c;咱们判断一个数是奇还是偶时&#xff0c;使用对2取模的方法&#xff0c;今天偶然看到一个新的方法&#xff1a;i& 0x1。该法将i与16进制1按位与&#xff0c;效果是取i二进制最近一位的数值&#xff0c;是0就是偶数&#xff0c;是1就是奇数。测…

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

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

26.特殊类的设计(设计不能被拷贝的类、只能在堆上创建对象的类、只能在栈上创建对象的类、不能被继承的类/只能创建一个对象(单例模式))

1.设计一个类&#xff0c;不能被拷贝 拷贝只会发生在两个场景中&#xff1a;拷贝构造函数以及赋值运算符重载 因此想要让一个类禁止拷贝&#xff0c;只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 方式一&#xff1a;C98中&#xff0c; 将拷贝构造函数与赋值运算符…

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

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

技术支持-KA指标提升

一 提升关键客户&#xff08;Key Account, KA&#xff09;问题解决效率与体验 建立快速响应机制&#xff1a; 设立专门的KA服务团队&#xff0c;确保客户问题能被即时接收和响应。实施多渠道接入&#xff08;如电话、短信、邮件、在线聊天等&#xff09;&#xff0c;让客户可以…

黄啤:醇厚与经典的传承

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

【C++风云录】深度剖析:人体解剖学与医学影像处理

计算机视觉与医学成像&#xff1a;六种工具的比较 前言 本文旨在通过详尽而深入的介绍&#xff0c;让读者更好地理解和使用六种重要的程序库&#xff1a;ITK-SNAP、Slicer、VTK、OpenCV、dcm4che以及DCMTK。每一个程序库的部分均包含了它们的简介&#xff0c;安装方法&#x…

转移插槽笔记

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

消息 队列

使用消息队列实现的2个终端之间的互相聊天&#xff0c;并使用信号控制消息队列的读取方式。 当键盘按ctrlc的时候&#xff0c;切换消息读取方式&#xff0c;一般情况为读取指定编号的消息&#xff0c;按ctrlc之后&#xff0c;指定的编号不读取&#xff0c;读取其他所有编号的消…

【C++ 】红黑树

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

信息系统安全选择题 1-10章 汇总【太原理工大学】

第一章 1.信息未经授权不能改变的安全特性称为_D b.有效性 a.保密性 d.完整性 c.可控性 2.信息系统防止信息非法泄露的安全特性称为_D b.有效性 a.完整性 d.保密性 c.可控性 6.《国际通用信息安全评价标准ISO/IEC 15408》在安全保证要求中定义了7个评价保证等级&…

上海理工大学程序设计 D方块游戏

原题链接&#xff1a;D-方块游戏 本来以为是搜索&#xff0c;没想到是数学。 //冷静&#xff0c;冷静&#xff0c;冷静 //调不出来就重构 #pragma GCC optimize(2) #pragma GCC optimize("O3") #include<bits/stdc.h> #define endl \n using namespace std;…

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…

视觉检测系统,是否所有产品都可以进行视觉检测?

视觉检测系统作为一种先进的质检工具&#xff0c;虽然具有广泛的应用范围&#xff0c;但并非所有产品都适合进行视觉检测。本文将探讨视觉检测系统的适用范围及其局限性。 随着机器视觉技术的快速发展&#xff0c;视觉检测系统已广泛应用于各个行业&#xff0c;为产品质检提供…

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

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