Java在线教育系统案例

wen java案例 3

本文目录导读:

Java在线教育系统案例

  1. 系统架构设计
  2. 核心功能实现
  3. 系统配置类
  4. 数据库设计
  5. 系统亮点

我来为您设计一个完整的Java在线教育系统案例,包含详细的功能模块和代码实现。

系统架构设计

技术栈

  • 后端: Spring Boot 2.x + MyBatis Plus + Spring Security + JWT
  • 前端: Vue.js + Element UI
  • 数据库: MySQL + Redis
  • 文件存储: 阿里云OSS

系统模块划分

online-education/
├── edu-admin           # 后台管理模块
├── edu-api            # 接口服务模块
├── edu-common         # 公共模块
├── edu-gateway        # 网关模块
├── edu-service        # 业务服务模块
│   ├── course-service # 课程服务
│   ├── user-service   # 用户服务
│   └── order-service  # 订单服务
└── edu-utils          # 工具类模块

核心功能实现

用户模块

用户实体类

@Data
@TableName("edu_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String username;
    @JsonIgnore
    private String password;
    private String nickname;
    private String avatar;
    private String email;
    private String phone;
    @TableLogic
    private Integer deleted;
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

用户服务实现

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Override
    public Result login(String username, String password) {
        // 查询用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        User user = userMapper.selectOne(wrapper);
        if (user == null) {
            return Result.error("用户不存在");
        }
        // 验证密码
        if (!BCrypt.checkpw(password, user.getPassword())) {
            return Result.error("密码错误");
        }
        // 生成JWT令牌
        String token = JwtUtil.generateToken(user.getId(), user.getUsername());
        // 存储用户信息到Redis
        redisTemplate.opsForValue().set("user:" + user.getId(), user, 24, TimeUnit.HOURS);
        Map<String, Object> data = new HashMap<>();
        data.put("token", token);
        data.put("user", user);
        return Result.success(data);
    }
    @Override
    public Result register(UserDTO userDTO) {
        // 检查用户名是否存在
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", userDTO.getUsername());
        if (userMapper.selectCount(wrapper) > 0) {
            return Result.error("用户名已存在");
        }
        // 创建新用户
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        user.setPassword(BCrypt.hashpw(userDTO.getPassword(), BCrypt.gensalt()));
        user.setAvatar("default.png");
        userMapper.insert(user);
        return Result.success("注册成功");
    }
}

课程模块

课程实体类

@Data
@TableName("edu_course")
public class Course {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String title;
    private String description;
    private String coverUrl;
    private Long teacherId;
    private String teacherName;
    private BigDecimal price;
    private Integer status; // 0-未发布 1-已发布
    private Integer categoryId;
    private Integer viewCount;
    private Integer buyCount;
    @TableLogic
    private Integer deleted;
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

课程查询服务

@Service
public class CourseServiceImpl implements CourseService {
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private ChapterMapper chapterMapper;
    @Override
    public PageResult<CourseVO> getCourseList(CourseQuery query) {
        Page<Course> page = new Page<>(query.getPageNum(), query.getPageSize());
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 1);
        // 按分类筛选
        if (query.getCategoryId() != null) {
            wrapper.eq("category_id", query.getCategoryId());
        }
        // 按关键词搜索
        if (StringUtils.hasText(query.getKeyword())) {
            wrapper.and(w -> w.like("title", query.getKeyword())
                             .or().like("description", query.getKeyword()));
        }
        // 按价格排序
        if ("price_asc".equals(query.getSort())) {
            wrapper.orderByAsc("price");
        } else if ("price_desc".equals(query.getSort())) {
            wrapper.orderByDesc("price");
        } else {
            wrapper.orderByDesc("create_time");
        }
        IPage<Course> coursePage = courseMapper.selectPage(page, wrapper);
        List<CourseVO> records = coursePage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        return new PageResult<>(coursePage.getTotal(), records);
    }
    @Override
    public CourseDetailVO getCourseDetail(Long id) {
        Course course = courseMapper.selectById(id);
        if (course == null) {
            throw new ServiceException("课程不存在");
        }
        // 增加浏览量
        courseMapper.increaseViewCount(id);
        // 查询章节信息
        List<Chapter> chapters = chapterMapper.selectList(
                new QueryWrapper<Chapter>().eq("course_id", id)
                                          .orderByAsc("sort")
        );
        CourseDetailVO detailVO = new CourseDetailVO();
        BeanUtils.copyProperties(course, detailVO);
        detailVO.setChapters(chapters);
        return detailVO;
    }
    private CourseVO convertToVO(Course course) {
        CourseVO vo = new CourseVO();
        BeanUtils.copyProperties(course, vo);
        return vo;
    }
}

视频处理模块

视频上传服务

@Service
public class VideoService {
    @Autowired
    private OSSClient ossClient;
    @Value("${aliyun.oss.bucket}")
    private String bucketName;
    @Value("${aliyun.oss.url}")
    private String ossUrl;
    public Result uploadVideo(MultipartFile file) {
        try {
            // 生成文件名称
            String fileName = UUID.randomUUID().toString() + "-" + file.getOriginalFilename();
            // 上传到OSS
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(file.getContentType());
            metadata.setContentLength(file.getSize());
            ossClient.putObject(bucketName, fileName, file.getInputStream(), metadata);
            // 生成访问URL
            String url = ossUrl + "/" + fileName;
            // 触发视频转码
            processVideo(fileName);
            return Result.success(url);
        } catch (Exception e) {
            throw new ServiceException("视频上传失败");
        }
    }
    private void processVideo(String fileName) {
        // 使用阿里云视频处理服务进行转码
        // 这里简化处理,实际应该调用多媒体转码服务
    }
}

秒杀功能

秒杀服务实现

@Service
public class SeckillServiceImpl implements SeckillService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SeckillMapper seckillMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    private static final String SECKILL_PREFIX = "seckill:";
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result seckill(SeckillDTO seckillDTO) {
        Long userId = seckillDTO.getUserId();
        Long courseId = seckillDTO.getCourseId();
        // 1. 预减库存
        Long stock = redisTemplate.opsForValue()
                .decrement(SECKILL_PREFIX + "stock:" + courseId);
        if (stock < 0) {
            // 恢复到0
            redisTemplate.opsForValue()
                    .increment(SECKILL_PREFIX + "stock:" + courseId);
            return Result.error("商品已售罄");
        }
        // 2. 防止重复购买
        Boolean flag = redisTemplate.opsForValue()
                .setIfAbsent(SECKILL_PREFIX + "order:" + userId + ":" + courseId, "1");
        if (!Boolean.TRUE.equals(flag)) {
            // 回补库存
            redisTemplate.opsForValue()
                    .increment(SECKILL_PREFIX + "stock:" + courseId);
            return Result.error("请勿重复购买");
        }
        // 3. 发送消息到消息队列
        SeckillMessage message = new SeckillMessage();
        message.setUserId(userId);
        message.setCourseId(courseId);
        rabbitTemplate.convertAndSend("seckill.exchange", "seckill.queue", message);
        return Result.success("秒杀成功,请等待发货");
    }
    @RabbitListener(queues = "seckill.queue")
    public void handleSeckillMessage(SeckillMessage message) {
        try {
            // 创建订单
            createOrder(message.getUserId(), message.getCourseId());
            // 删除秒杀标记
            redisTemplate.delete(SECKILL_PREFIX + "order:" 
                    + message.getUserId() + ":" + message.getCourseId());
        } catch (Exception e) {
            // 处理失败,回补库存
            redisTemplate.opsForValue()
                    .increment(SECKILL_PREFIX + "stock:" + message.getCourseId());
            log.error("秒杀处理失败", e);
        }
    }
    private void createOrder(Long userId, Long courseId) {
        // 创建订单逻辑
    }
}

学习笔记功能

笔记服务

@Service
public class NoteServiceImpl implements NoteService {
    @Autowired
    private NoteMapper noteMapper;
    @Override
    public Result addNote(NoteDTO noteDTO) {
        Note note = new Note();
        BeanUtils.copyProperties(noteDTO, note);
        note.setCreateTime(new Date());
        noteService.save(note);
        return Result.success(note);
    }
    @Override
    public Result getNoteList(Long userId, Long courseId) {
        QueryWrapper<Note> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        if (courseId != null) {
            wrapper.eq("course_id", courseId);
        }
        List<Note> notes = noteMapper.selectList(wrapper);
        return Result.success(notes);
    }
    @Override
    public Result updateNote(NoteDTO noteDTO) {
        Note note = noteMapper.selectById(noteDTO.getId());
        // 检查权限
        if (!note.getUserId().equals(noteDTO.getUserId())) {
            throw new ServiceException("无权修改他人笔记");
        }
        note.setContent(noteDTO.getContent());
        note.setUpdateTime(new Date());
        noteMapper.updateById(note);
        return Result.success("更新成功");
    }
}

系统配置类

JWT工具类

@Component
public class JwtUtil {
    @Value("${jwt.secret}")
    private String secret;
    @Value("${jwt.expiration}")
    private Long expiration;
    public String generateToken(Long userId, String username) {
        Date now = new Date();
        Date expireDate = new Date(now.getTime() + expiration * 1000);
        return Jwts.builder()
                .setSubject(username)
                .claim("userId", userId)
                .setIssuedAt(now)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
    public Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }
    public boolean validateToken(String token) {
        try {
            Claims claims = parseToken(token);
            return claims.getExpiration().after(new Date());
        } catch (Exception e) {
            return false;
        }
    }
}

统一返回结果

@Data
public class Result<T> {
    private Integer code;
    private String message;
    private T data;
    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMessage("操作成功");
        result.setData(data);
        return result;
    }
    public static <T> Result<T> success(String message) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMessage(message);
        return result;
    }
    public static <T> Result<T> error(String message) {
        Result<T> result = new Result<>();
        result.setCode(500);
        result.setMessage(message);
        return result;
    }
}

全局异常处理器

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(ServiceException.class)
    public Result handleServiceException(ServiceException e) {
        return Result.error(e.getMessage());
    }
    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        log.error("系统异常", e);
        return Result.error("系统繁忙,请稍后再试");
    }
}

数据库设计

-- 用户表
CREATE TABLE `edu_user` (
    `id` BIGINT NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(50) NOT NULL,
    `password` VARCHAR(100) NOT NULL,
    `nickname` VARCHAR(50) DEFAULT NULL,
    `avatar` VARCHAR(255) DEFAULT NULL,
    `email` VARCHAR(100) DEFAULT NULL,
    `phone` VARCHAR(20) DEFAULT NULL,
    `deleted` TINYINT DEFAULT '0',
    `create_time` DATETIME DEFAULT NULL,
    `update_time` DATETIME DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 课程表
CREATE TABLE `edu_course` (
    `id` BIGINT NOT NULL AUTO_INCREMENT, VARCHAR(200) NOT NULL,
    `description` TEXT,
    `cover_url` VARCHAR(255) DEFAULT NULL,
    `teacher_id` BIGINT DEFAULT NULL,
    `teacher_name` VARCHAR(50) DEFAULT NULL,
    `price` DECIMAL(10,2) DEFAULT '0.00',
    `status` TINYINT DEFAULT '0',
    `category_id` INT DEFAULT NULL,
    `view_count` INT DEFAULT '0',
    `buy_count` INT DEFAULT '0',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 章节表
CREATE TABLE `edu_chapter` (
    `id` BIGINT NOT NULL AUTO_INCREMENT,
    `course_id` BIGINT NOT NULL, VARCHAR(200) NOT NULL,
    `sort` INT DEFAULT '0',
    `video_url` VARCHAR(255) DEFAULT NULL,
    `duration` INT DEFAULT '0',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 订单表
CREATE TABLE `edu_order` (
    `id` BIGINT NOT NULL AUTO_INCREMENT,
    `order_no` VARCHAR(32) NOT NULL,
    `user_id` BIGINT NOT NULL,
    `course_id` BIGINT NOT NULL,
    `amount` DECIMAL(10,2) NOT NULL,
    `status` TINYINT DEFAULT '0',
    `create_time` DATETIME DEFAULT NULL,
    `pay_time` DATETIME DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

系统亮点

高并发处理

  • 使用Redis缓存热点数据
  • 消息队列异步处理订单
  • 数据库连接池优化

安全机制

  • JWT令牌认证
  • 密码加密存储
  • SQL注入防护

性能优化

  • 页面静态化
  • CDN加速
  • 数据库索引优化

扩展性

  • 微服务架构
  • 模块化设计
  • 统一的接口规范

这个案例涵盖了在线教育系统的核心功能,可以作为学习参考,实际生产环境需要根据具体需求进行调整和完善。

抱歉,评论功能暂时关闭!