一个月肝一个基于SpringBoot的在线教育系统【源码开源】【建议收藏】_在线教育 开源系统-程序员宅基地

技术标签: spring  spring boot  java  javaweb开发  java学习  

今天给大家开源一个基于springboot的在线教育平台系统,系统是小孟开发的,第一个版本是小锋开发的(小锋的博客),我进行了本版本的开发。

该系统完全免费、开源。

系统完美运行,无任何的bug,技术较多,可以当做面试的项目或者作为毕设的项目。

系统获取源码的方式见文章底部。

为防止刷着刷者找不到,大家点赞、收藏文章。

系统完美运行。具体的介绍如下所示。

目录

1. 技术介绍

2.功能介绍

3. 前端

3.1 首页

3.2 课程

3.3 登入

3.4 商品兑换

3.5 课程发布

4. 后端

4.1 登录

4.2 系统管理

4.3 课程管理

4.4 教师管理

4.5 导航菜单

4.6 轮播管理

4.7 通知管理

4.8 礼品管理

5,系统的核心代码

6,源码获取


1. 技术介绍

核心技术:SpringBoot+mybatis;

前端:layui;

开发工具:idea;

数据库:mysql5.7;

模版引擎:thymeleaf;

安全框架:SpringSecurity;

日志框架:logback;

数据库连接池:druid;

在线编辑器:ckeditor;

图片轮播组件:jQuerySwipeslider;

2.功能介绍

本项目分前台用户界面功能和后台管理功能;

前台用户界面功能:

  • 滚动大条幅展示重要通知和课程或者活动;

  • 展示课程,根据实际业务需求,展示课程推荐,最新课程,免费课程,实战课程;

  • 课程搜索,用户输入指定课程关键字,可以搜索查询,也可以根据课程类别分类,和类型进行搜索;

  • 课程详细展示

  • 用户登陆

  • 在线支付

后台管理功能:

  • 管理员登录

  • 课程管理

  • 课程类别管理

  • 用户管理

  • 授课老师管理

  • 订单管理

  • 菜单管理

  • 友情链接管理

  • 系统属性管理

  • 自定义帖子管理

  • 轮转图片帖子管理

3. 前端

3.1 首页

3.2 课程

提供按照课程的类别,类型以及搜索框进行快速查询相关课程

点击任意一门课程,免费课程可以直接观看,vip课程则需要通过支付宝或者微信缴费开通vip进行观看

3.3 登入

学习课程时候需要登录才能观看相关视频资料

登入后可以查看个人中心的相关功能

在我的订单界面可以查看已经购买的课程

3.4 商品兑换

3.5 课程发布

在课程发布页面可以提交发布的课程资料

在我的发布页面可以查看所有已经发布的课程相关信息,查看审核状态

4. 后端

4.1 登录

4.2 系统管理

包括用户管理,角色管理,菜单管理,可以查看对应的信息并添加,导入,修改或删除

角色管理界面可以为角色分配权限

4.3 课程管理

可以添加课程,对课程进行分类管理:公共课程,专业课程,免费课程等

在类别管理中可以添加课程的分类信息

在审核功能处可以对上传的视频进行审核

4.4 教师管理

4.5 导航菜单

4.6 轮播管理

4.7 通知管理

4.8 礼品管理

5,系统的核心代码

/**
 * 操作日志记录注解
 * Created by xiaomeng 2020-03-21 17:03
  *技术交流v:kaifazixun
 * 操作日志记录注解
 * Created by wangfan on 2020-03-21 17:03
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperLog {

    /**
     * 模块
     */
    String value();

    /**
     * 功能
     */
    String desc();

    /**
     * 是否记录请求参数
     */
    boolean param() default true;

    /**
     * 是否记录返回结果
     */
    boolean result() default false;

}*
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperLog {

    /**
     * 模块
     */
    String value();

    /**
     * 功能
     */
    String desc();

    /**
     * 是否记录请求参数
     */
    boolean param() default true;

    /**
     * 是否记录返回结果
     */
    boolean result() default false;

}
@Aspect
@Component
public class OperLogAspect {
    private ThreadLocal<Long> startTime = new ThreadLocal<>();
    @Autowired
    private OperRecordService operRecordService;

    @Pointcut("@annotation(com.egao.common.core.annotation.OperLog)")
    public void operLog() {
    }

    @Before("operLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        startTime.set(System.currentTimeMillis());
    }

    @AfterReturning(pointcut = "operLog()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        saveLog(joinPoint, result, null);
    }

    @AfterThrowing(value = "operLog()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        saveLog(joinPoint, null, e);
    }

    private void saveLog(JoinPoint joinPoint, Object result, Exception e) {
        // 获取reques对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (attributes == null ? null : attributes.getRequest());
        // 构建操作日志
        OperRecord operRecord = new OperRecord();
        operRecord.setUserId(getLoginUserId());
        if (startTime.get() != null) operRecord.setSpendTime(System.currentTimeMillis() - startTime.get());
        if (request != null) {
            operRecord.setRequestMethod(request.getMethod());
            operRecord.setUrl(request.getRequestURI());
            operRecord.setIp(UserAgentGetter.getIp(request));
        }
        // 记录异常信息
        if (e != null) {
            operRecord.setState(1);
            operRecord.setComments(StrUtil.sub(e.toString(), 0, 2000));
        }
public class BaseController {

    /**
     * 获取当前登录的user
     */
    public User getLoginUser() {
        Subject subject = SecurityUtils.getSubject();
        if (subject == null) return null;
        Object object = subject.getPrincipal();
        if (object != null) return (User) object;
        return null;
    }

    /**
     * 获取当前登录的userId
     */
    public Integer getLoginUserId() {
        User loginUser = getLoginUser();
        return loginUser == null ? null : loginUser.getUserId();
    }

}
/**
 * 用户管理
 * Created by xiaomeng 2020-12-24 16:10
*技术交流V:kaifazixun
 */
@Controller
@RequestMapping("/sys/user")
public class UserController extends BaseController {
    @Autowired
    private UserService userService;
    @Autowired
    private DictionaryDataService dictionaryDataService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private OrganizationService organizationService;

    @RequiresPermissions("sys:user:view")
    @RequestMapping()
    public String view(Model model) {
        model.addAttribute("sexList", dictionaryDataService.listByDictCode("sex"));
        model.addAttribute("organizationTypeList", dictionaryDataService.listByDictCode("organization_type"));
        model.addAttribute("rolesJson", JSON.toJSONString(roleService.list()));
        return "system/user.html";
    }

    /**
     * 个人中心
     */
    @RequestMapping("/info")
    public String userInfo(Model model) {
        model.addAttribute("user", userService.getFullById(getLoginUserId()));
        model.addAttribute("sexList", dictionaryDataService.listByDictCode("sex"));
        return "index/user-info.html";
    }

    /**
     * 分页查询用户
     */
    @OperLog(value = "用户管理", desc = "分页查询")
    @RequiresPermissions("sys:user:list")
    @ResponseBody
    @RequestMapping("/page")
    public PageResult<User> page(HttpServletRequest request) {
        PageParam<User> pageParam = new PageParam<>(request);
        pageParam.setDefaultOrder(null, new String[]{"create_time"});
        return userService.listPage(pageParam);
    }

    /**
     * 查询全部用户
     */
    @OperLog(value = "用户管理", desc = "查询全部")
    @RequiresPermissions("sys:user:list")
    @ResponseBody
    @RequestMapping("/list")
    public JsonResult list(HttpServletRequest request) {
        PageParam<User> pageParam = new PageParam<>(request);
        List<User> records = userService.listAll(pageParam.getNoPageParam());
        return JsonResult.ok().setData(pageParam.sortRecords(records));
    }

    /**
     * 根据id查询用户
     */
    @OperLog(value = "用户管理", desc = "根据id查询")
    @RequiresPermissions("sys:user:list")
    @ResponseBody
    @RequestMapping("/get")
    public JsonResult get(Integer id) {
        PageParam<User> pageParam = new PageParam<>();
        pageParam.put("userId", id);
        List<User> records = userService.listAll(pageParam.getNoPageParam());
        return JsonResult.ok().setData(pageParam.getOne(records));
    }
/**
 * 字典管理
 * Created by xiaomeng on 2021-03-14 11:29:03
 * 技术交流加v:kafazixun
 */
@Controller
@RequestMapping("/sys/dict")
public class DictionaryController extends BaseController {
    @Autowired
    private DictionaryService dictionaryService;

    @RequiresPermissions("sys:dict:view")
    @RequestMapping()
    public String view() {
        return "system/dictionary.html";
    }

    /**
     * 分页查询字典
     */
    @OperLog(value = "字典管理", desc = "分页查询")
    @RequiresPermissions("sys:dict:list")
    @ResponseBody
    @RequestMapping("/page")
    public PageResult<Dictionary> page(HttpServletRequest request) {
        PageParam<Dictionary> pageParam = new PageParam<>(request);
        return new PageResult<>(dictionaryService.page(pageParam, pageParam.getWrapper()).getRecords(), pageParam.getTotal());
    }

    /**
     * 查询全部字典
     */
    @OperLog(value = "字典管理", desc = "查询全部")
    @RequiresPermissions("sys:dict:list")
    @ResponseBody
    @RequestMapping("/list")
    public JsonResult list(HttpServletRequest request) {
        PageParam<Dictionary> pageParam = new PageParam<>(request);
        return JsonResult.ok().setData(dictionaryService.list(pageParam.getOrderWrapper()));
    }

    /**
     * 根据id查询字典
     */
    @OperLog(value = "字典管理", desc = "根据id查询")
    @RequiresPermissions("sys:dict:list")
    @ResponseBody
    @RequestMapping("/get")
    public JsonResult get(Integer id) {
        return JsonResult.ok().setData(dictionaryService.getById(id));
    }

6,源码获取

源获取点击下面,关注弹出的公众号图,

回复:精品课程

不是评论区回复,不是评论区回复,不是评论区回复,

资料获取加技术抱团,点击 关注

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mengchuan6666/article/details/120488576

智能推荐

Python编写一个程序,对给定字符串中出现的a~z字母频率进行分析,忽略大小写,采用 降序方式输出。_英文字符频率统计,a~z字母频率统计,采取降序输出-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏16次。编写一个程序,对给定字符串中出现的a~z字母频率进行分析,忽略大小写,采用 降序方式输出。##################################################txt=input("请输入一段英文文本:")txt=txt.lower()counts={}for i in txt: if i in "abcdefghijklmnopqrstuvwx..._英文字符频率统计,a~z字母频率统计,采取降序输出

记录一个傻错误:“error: expected identifier before string constant“-程序员宅基地

文章浏览阅读840次。然后我 在类的属性中定义了一个 ofstream 类型的变量,指定了路径,然后就会给我抱着个错误,号和,真够傻的:"error: expected identifier before string constant"就是 : 在类中,类的 无论什么属性 public private 等,都是不可以在定义的时候赋初值 的。_error: expected identifier before string constant

WPF 遍历DataTemplate(获取所有控件)_获取datatemplate里空间-程序员宅基地

文章浏览阅读1.5w次,点赞5次,收藏10次。情况1:在设定DataTemplate的Name,并且他是在前台表示时,获取DataTemplate里的指定控件。方法:http://blog.csdn.net/wackelbh/article/details/6003947(参考这篇文章)_获取datatemplate里空间

2021年最棒的10款Java框架,你喜欢哪个?_什么框架最好用-程序员宅基地

文章浏览阅读3.7k次,点赞3次,收藏7次。Java是一种强大的语言,当与框架相结合时,Java可以为您提供电子商务,银行,云计算,财务,大数据,股票市场,且更多的任何域的最佳解决方案。如果您刚刚从Java开始,请参阅Java Live Active使用此博客将通过您需要知道的所有重要概念来开始使用框架。什么是Java框架?作为模板或骨架的预先写代码的正文,其中一个开发人员可以根据需要填写其代码来使用和重用以创建应用程序,以便在他们打算引用其作为框架时使用的代码来创建应用程序。重用框架使开发人员能够在没有手动开销的情况下从头开始创建每.._什么框架最好用

安装oracle克隆数据库卡死,oracle数据库之克隆方法-程序员宅基地

文章浏览阅读729次。Oracle 数据库之克隆方法Oracle 8.1.7 for Linux系统,在安装上存在一切困难,尤其在Redhat7.2系统下安装的时候会出现很多意想不到的事情,譬如图形界面无法显示、xwin无法远程连接,在编译的过程中如果没有安装GCC,Glibc等等一些库文件,容易出现无法link的错误,而全部安装又会造成其他困难。因此在Oracle安装过程中总结出来了一些经验。介绍如下::Oracle..._fmw_home/oracle_common/bin/pasteconfig.sh 克隆 timeout

计算机考研408每日一题 day67_用足够容量的一维数组b对nxn阶-程序员宅基地

文章浏览阅读899次,点赞2次,收藏3次。将一个n×n的对称矩阵A的下三角部分按行存放在一个一维数组B中,A[0][0]存放在B[0]中,那么第i行的对角元素A[i][i]在B中的存放位置是___(中国科学院大学 2016)如果分时系统的时间片固定,那么___,则响应时间越长。(兰州大学 2005年)关于路由器说法正确的是___。(中国科学院大学 2015)通常所说的“溢出”,是指___(哈尔滨工程大学 2004年)_用足够容量的一维数组b对nxn阶

随便推点

深度学习笔记~集成方法bagging, boosting和stacking_bagging方法结合深度学习模型-程序员宅基地

文章浏览阅读2.4k次。转载:https://towardsdatascience.com/ensemble-methods-bagging-boosting-and-stacking-c9214a10a205作者:Joseph Rocca Ensemble methods: bagging, boosting andstackingIntroduction“Unity is ..._bagging方法结合深度学习模型

java 开发 文件夹创建和删除_文件的创建和删除java-程序员宅基地

文章浏览阅读6.7k次。//返回文件名称(文件夹读取文件)public static ArrayList<String> getFilesPath(String path) throws Exception {//目标集合fileListArrayList<String> fileList = new ArrayList<String>();File file = new ..._文件的创建和删除java

鸿蒙-南向轻内核开发实战系列(一)基于小熊派鸿蒙季开发板环境搭建_鸿蒙系统内核开发环境的搭建方法-程序员宅基地

文章浏览阅读1.9k次,点赞6次,收藏12次。前言前一段时间,我写过一篇关于LiteOS-A开发环境搭建的文章(实际上是将其作为独立的RTOS来开发的),今天正式讲一讲LiteOS作为鸿蒙内核子系统该如何开发。对于HarmonyOS,开发工作大致可以分为南向开发(内核、驱动)和北向开发(App应用)。我们主讲南向开发。在目前的鸿蒙2.0版本下,南向轻内核开发的资料相对更加完善,主要是针对LiteOS内核。讲到这里,能完整编译到手机上运行的鸿蒙镜像,可能大家还要再等一等了(笔者也很期待)。概述为了帮大家理清楚鸿蒙开发的套路,我们从头再梳理一遍相关_鸿蒙系统内核开发环境的搭建方法

勒索软件趋势和受害者影响统计数据【2023下半年】-程序员宅基地

文章浏览阅读928次,点赞16次,收藏18次。新钛云服已累计为您分享788篇技术干货1摘要2023年下半年,Leak 网站上发布了2,344 家公司的勒索软件感染。与2022 年下半年(2022年7月1日至2022年12月31日)相比,受影响的公司总数增加了79.2%。共有53个勒索软件组织处于活动状态,每个组织平均攻击了44家公司。有25个新的或修改的数据泄密网站。拥有数据泄密网站的新勒索软件组织,每个组织平均攻击约21家公司。2023年下...

libtorch c++调用 (五)Linux下的调用_linux 引用libtorch gpu set(cuda_toolkit_root_dir "/p-程序员宅基地

文章浏览阅读3.5k次,点赞5次,收藏12次。libtorch下载地址:https://download.pytorch.org/libtorch/cpu/libtorch-shared-with-deps-1.5.1%2Bcpu.zip在linux系统下新建一个文件夹如:pytorch_test文件夹下新建一个文件:main.cpp,文件内容如下:#include <iostream>#include <torch/torch.h> using namespace std; int main(){ _linux 引用libtorch gpu set(cuda_toolkit_root_dir "/path/to/cuda")

Cython+Pyinstaller Python编译与打包-程序员宅基地

文章浏览阅读3.3k次。Cython+Pyinstaller Python编译与打包示例项目结构:➜ cpdemo tree.|-- libs| |-- A| | `-- a.py| `-- B| `-- b.py`-- setup |-- build_pyd.py `-- main.py总共四个文件,A 和 B分别是两个类,其中mian.py 引用a,..._cython+pyinstaller

推荐文章

热门文章

相关标签