【Java】基于SpringCloud的考研复试辅导平台

1、前端请求后端服务提供的接口。

2、后端服务的控制层Controller接收前端的请求。

3、Contorller层调用Service层进行业务处理。

4、Service层调用Dao持久层对数据持久化。

XXX-api:接口工程,为前端提供接口。

XXX-service: 业务工程,为接口工程提供业务支撑。

XXX-model: 数据模型工程,存储数据模型类、数据传输类型等。

XXX-content:内容管理模块工程,负责聚合XXX-api、XXX-service、XXX-model

1、分析数据模型

下边从查询条件、查询列表两个方面分析数据模型

①查询条件:

包括:课程名称、课程审核状态、课程发布状态

课程名称:可以模糊搜索

课程审核状态:未提交、已提交、审核通过、审核未通过

课程发布状态:未发布、已发布、已下线

因为是分页查询所以查询条件中还要包括当前页码、每页显示记录数。

②查询结果:

查询结果中包括:课程id、课程名称、任务数、创建时间、是否付费、审核状态、类型,操作

任务数:该课程所包含的课程计划数,即课程章节数。

是否付费:课程包括免费、收费两种。

类型:录播、直播。

因为是分页查询所以查询结果中还要包括总记录数、当前页、每页显示记录数。

2、生成PO类

PO即持久对象(Persistent Object),它们是由一组属性和属性的get和set方法组成,PO对应于数据库的表。使用mybatis-plus的generator工程生成PO类、Mapper接口、Mapper的xml文件。

①Dto(Data Access Object):配合PO进行增删改查。

②VO( View Object) :与前端进行交互的Java对象。

③Bo( Business Object)表示一个业务对象。

④PO(Persistant Object):数据库中的一条记录映射成的Java对象。

3、设计查询课程接口

①协议

采用HTTP,查询类接口通常为get或post,查询条件较少的使用get,较多的使用post。确定content-type,参数以什么数据格式提交,结果以json格式响应。

②分析请求参数

根据前边对数据模型的分析,请求参数为:课程名称、课程审核状态、当前页码、每页显示记录数。

根据分析的请求参数定义模型类。

③分析响应结果

根据前边对数据模型的分析,响应结果为数据列表加一些分页信息(总记录数、当前页、每页显示记录数)。 

数据列表中数据的属性包括:课程id、课程名称、任务数、创建时间、审核状态、类型。

注意:查询结果中的审核状态为数据字典中的代码字段,前端会根据审核状态代码找到对应的名称显示。

根据分析的响应结果定义模型类。

④分析完成,使用SpringBoot注解开发一个Http接口。

⑤使用接口文档工具查看接口的内容。

⑥ 接口中调用Service方法完成业务处理。

4、生成接口文档

来利用Swagger开源项目,Swagger是一个在线接口文档的生成工具。

写完接口以后,写一个controller类,用Swagger生成接口文档,把接口文档发给前端工程师。

5、实现查询课程接口

先写mapper层,再写service接口。创建PO类、Mapper接口、Mapper的xml文件,每个PO类对应数据库的每张表,每张表需要创建一个Mapper接口和Mapper的xml映射文件 。

持久层使用MyBatis-Plus,使用generator工程生成的mapper接口和mapper映射文件 拷贝到service工程。(自动生成mapper接口与mapper映射文件)

测试mapper

①在service工程的pom.xml中添加依赖

②在config包下配置Mybatis-Plus

/**
 * <P>
 *        Mybatis-Plus 配置
 * </p>
 */
@Configuration
@MapperScan("com.xuecheng.content.mapper")
public class MybatisPlusConfig {
   /**
    * 定义分页拦截器
    */
   @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor() {
      MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
      return interceptor;
   }
   

分页插件的原理:

首先分页参数放到ThreadLocal中,拦截执行的sql,根据数据库类型添加对应的分页语句重写sql,例如:(select * from table where a) 转换为 (select count(*) from table where a)和(select * from table where a limit ,)

计算出了total总条数、pageNum当前第几页、pageSize每页大小和当前页的数据,是否为首页,是否为尾页,总页数等。

③单元测试需要的配置文件

在test/resources下创建 log4j2-dev.xml、bootstrap.yml:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
    username: root
    password: mysql
# 日志文件配置路径
logging:
  config: classpath:log4j2-dev.xml

④编写启动类

单元测试工作在test目录,在test下添加启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ContentApplication {
    public static void main(String[] args) {
        SpringApplication.run(ContentApplication.class, args);
    }
}

⑤编写测试类

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.Course.base.model.PageParams;
import com.Course.base.model.PageResult;
import com.Course.content.mapper.CourseBaseMapper;
import com.Course.content.model.dto.QueryCourseParamsDto;
import com.Course.content.model.po.CourseBase;
import org.apache.commons.lang.StringUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class CourseBaseMapperTests {

    @Autowired
    CourseBaseMapper courseBaseMapper;


    @Test
    void testCourseBaseMapper() {
        CourseBase courseBase = courseBaseMapper.selectById(74L);
        Assertions.assertNotNull(courseBase);

        //测试查询接口
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        //查询条件
        QueryCourseParamsDto queryCourseParamsDto = new QueryCourseParamsDto();
        queryCourseParamsDto.setCourseName("java");
        queryCourseParamsDto.setAuditStatus("202004");
        queryCourseParamsDto.setPublishStatus("203001");

        //拼接查询条件(重点)
        //根据课程名称模糊查询  name like '%名称%'
        queryWrapper.like(StringUtils.isNotEmpty(queryCourseParamsDto.getCourseName()),CourseBase::getName,queryCourseParamsDto.getCourseName());
        //根据课程审核状态
        queryWrapper.eq(StringUtils.isNotEmpty(queryCourseParamsDto.getAuditStatus()),CourseBase::getAuditStatus,queryCourseParamsDto.getAuditStatus());
        //todo:按课程发布状态查询



        //分页参数
        PageParams pageParams = new PageParams();
        pageParams.setPageNo(1L);//页码
        pageParams.setPageSize(3L);//每页记录数
        Page<CourseBase> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());

        //分页查询E page 分页参数, @Param("ew") Wrapper<T> queryWrapper 查询条件
        Page<CourseBase> pageResult = courseBaseMapper.selectPage(page, queryWrapper);

        //数据
        List<CourseBase> items = pageResult.getRecords();
        //总记录数
        long total = pageResult.getTotal();

        //准备返回数据 List<T> items, long counts, long page, long pageSize
        PageResult<CourseBase> courseBasePageResult = new PageResult<>(items, total, pageParams.getPageNo(), pageParams.getPageSize());
        System.out.println(courseBasePageResult);
    }

}

难点

写查询接口发现数据不对。

把SQL语句格式化,找出参数(把SQL补齐),贴到MySQL客户端看看能不能拿到数据,看SQL哪里写错了。

6、开发业务层

①数据字典表

如果客户需要频繁修改数据库里的某一个字段的内容,比如把所有的“审核未通过”改成“未通过”,过一段时间又要改成“XXX”,在原表上改太麻烦,建立一个数据字典表,把数据和字段连接起来。需要修改的时候,修改字段对应的那个数据即可。

[
    {"code":"202001","desc":"审核未通过"},
    {"code":"202002","desc":"未审核"},
    {"code":"202003","desc":"审核通过"}
]

②编写service接口

package com.course.content.service;

import com.course.base.model.PageParams;
import com.course.base.model.PageResult;
import com.course.content.model.dto.QueryCourseParamsDto;
import com.course.content.model.po.CourseBase;

/**
 * @description 课程基本信息管理业务接口
 * @author Mr.M
 * @date 2022/9/6 21:42
 * @version 1.0
 /
public interface CourseBaseInfoService  {

 /*
  * @description 课程查询接口
  * @param pageParams 分页参数
  * @param queryCourseParamsDto 条件条件
  * @return com.course.base.model.PageResult<com.xuecheng.content.model.po.CourseBase>
 */
  PageResult<CourseBase> queryCourseBaseList(PageParams pageParams, QueryCourseParamsDto queryCourseParamsDto);

 }

创建接口实现类

package com.course.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.course.base.model.PageParams;
import com.course.base.model.PageResult;
import com.course.content.mapper.CourseBaseMapper;
import com.course.content.model.dto.QueryCourseParamsDto;
import com.course.content.model.po.CourseBase;
import com.course.content.service.CourseBaseInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @description 课程信息管理业务接口实现类

 * @version 1.0
 */
@Service
public class CourseBaseInfoServiceImpl  implements CourseBaseInfoService {


 @Autowired
 CourseBaseMapper courseBaseMapper;

 @Override
 public PageResult<CourseBase> queryCourseBaseList(PageParams pageParams, QueryCourseParamsDto queryCourseParamsDto) {


  //构建查询条件对象
  LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
  //构建查询条件,根据课程名称查询
     queryWrapper.like(StringUtils.isNotEmpty(queryCourseParamsDto.getCourseName()),CourseBase::getName,queryCourseParamsDto.getCourseName());
  //构建查询条件,根据课程审核状态查询
     queryWrapper.eq(StringUtils.isNotEmpty(queryCourseParamsDto.getAuditStatus()),CourseBase::getAuditStatus,queryCourseParamsDto.getAuditStatus());
//构建查询条件,根据课程发布状态查询
//todo:根据课程发布状态查询

  //分页对象
  Page<CourseBase> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());
  // 查询数据内容获得结果
  Page<CourseBase> pageResult = courseBaseMapper.selectPage(page, queryWrapper);
  // 获取数据列表
  List<CourseBase> list = pageResult.getRecords();
  // 获取数据总数
  long total = pageResult.getTotal();
  // 构建结果集
  PageResult<CourseBase> courseBasePageResult = new PageResult<>(list, total, pageParams.getPageNo(), pageParams.getPageSize());
  return courseBasePageResult;


 }


}

前后端联调,nginx解决跨域访问

7、课程分类查询

查询树形结构的表(多级),使用递归实现课程分类的查询。

with recursive t1 as (
select * from  course_category p where  id= '1'
union all
 select t.* from course_category t inner join t1 on t1.id = t.parentid
)
select *  from t1 order by t1.id, t1.orderby

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

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

相关文章

SQLite使用的临时文件(二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite数据库文件损坏的可能几种情况 下一篇&#xff1a;未发表 ​ 1. 引言 SQLite的显着特点之一它是一个数据库由一个磁盘文件组成。 这简化了 SQLite 的使用&#xff0c;因为移动或备份 数据库就像复制单个文…

第4周 Python程序流程控制刷题(选择结构)

单击题目&#xff0c;直接跳转到页面刷题&#xff0c;一周后公布答案。 B2050&#xff1a;三角形判断B2037&#xff1a;奇偶数判断B2039&#xff1a;整数大小比较P5711&#xff1a;闰年判断P5714&#xff1a;肥胖问题B2043&#xff1a;判断能否被 3&#xff0c;5&#xff0c;7…

shell编程-jq命令详解

文章目录 前言一、jq简介1. 简介2. 语法3. 命令选项 二、用于处理json数据1. 过滤1.1 标识运算符1.2 基本过滤1.3 获取对象属性1.3 迭代数组元素1.4 获取数组元素1.5 使用运算符 2. 类型和值2.1 数组构造2.2 对象构造2.3 递归下降 3. 内置运算符和函数3.1 算术运算符3.2 函数3.…

PCL点云处理之最小中值平方(Lmeds法)拟合平面(二百三十四)

PCL点云处理之 最小中值平方法(Lmeds)拟合平面(二百三十四) 一、算法介绍一、拟合原理二、具体实现1.代码2.结果一、算法介绍 (本文提供详细注释,输出拟合平面参数和平面点云) Lmeds(Least Median of Squares)是一种统计学方法,用于拟合数据并减少异常值对拟合结果…

CISP证书如何查询?软考信息安全工程师和CISP哪个好?

在信息安全领域&#xff0c;证书是衡量一个人专业能力和经验的重要标志。 CISP(国家信息安全专业人员认证)和软考信息安全工程师证书都是业内认可度较高的证书。 那么&#xff0c;对于想要提升自己信息安全能力的人来说&#xff0c;究竟应该如何选择呢&#xff1f; 下面将为…

汽车信息安全--密钥管理系统初探(1)

目录 1.为什么需要密钥管理 2.常见密钥种类 3.小结 当真正开始思考如何设计基于HSM的密钥管理系统,才发现基于之前vHSM的套路是相当不完备的。 仅仅是依靠AUTOSAR KeyM和CSM提出的密钥管理要点作为需求,总觉得是无根之水,不够踏实。因此我打算从密钥的实际使用场景、HSM…

基础篇Redis

基础篇Redis 1.Redis简单介绍 Redis是一种键值型的NoSql数据库&#xff0c;这里有两个关键字&#xff1a; 键值型NoSql 其中键值型&#xff0c;是指Redis中存储的数据都是以key.value对的形式存储&#xff0c;而value的形式多种多样&#xff0c;可以是字符串.数值.甚至json…

前端-html-01

1.HTML的标签分类 1.1常用排版标签 标签名语义和功能属性单标签还是双标签h1 ~ h6一级标题~六级标题无双标签p段落无双标签hr分隔线无单标签br换行无单标签pre原格式显示无双标签div无语义&#xff0c;用于页面布局无双标签 1.1.1h标题标签 <!DOCTYPE html> <htm…

【Node.js 常用命令(第一篇)】揭秘Node.js:掌握这些常用命令,让你在开发路上风生水起!

目录 前言 30条常用的Node.js 命令 1. node - 启动 Node.js REPL 或执行脚本 2. npm - Node.js 包管理器 3. npx - 执行 Node 包程序 4. nodemon - 自动重启 Node.js 应用 5. express - 快速搭建 Web 应用框架 6. git - 版本控制系统 7. mocha - 测试框架 8. eslint …

面试算法-104-乘积最大子数组

题目 给你一个整数数组 nums &#xff0c;请你找出数组中乘积最大的非空连续 子数组 &#xff08;该子数组中至少包含一个数字&#xff09;&#xff0c;并返回该子数组所对应的乘积。 测试用例的答案是一个 32-位 整数。 示例 1: 输入: nums [2,3,-2,4] 输出: 6 解释: 子数…

python ch8 函数

# 如何编写函数&#xff0c;以及如何传递实参&#xff0c;让函数能够访问完成其工作所需 # 的信息&#xff1b;如何使用位置实参和关键字实参&#xff0c;以及如何接受任意数量的实参&#xff1b;显示输出的函数和返 # 回值的函数&#xff1b;如何将函数同列表、字典、if语句…

Android_NDK调试

第一步&#xff1a; 链接log动态库 在Android.mk文件中添加 LOCAL_LDLIBS -llog 注意&#xff1a;一定要在 include $(BUILD_SHARED_LIBRARY) 之上添加&#xff0c;因为当执行到这句话的时候就表示所有的lib动态库已经加载完毕了&#xff0c;所以当你在这句代码之后再添加…

C++ 中常用的 STL

标准模板库 (STL) 是 C 标准库中一个强大的组件&#xff0c;它提供了各种通用数据结构和算法。STL 旨在提高代码的可重用性、效率和可读性。本文将介绍 C 中一些常用的 STL&#xff0c;并提供代码示例。 容器 容器是用于存储和组织数据的对象。STL 中提供了以下几种容器&…

Redis I/O多路复用

I/O多路复用 Redis的I/o多路复用中&#xff0c;将多个连接放到I/O复用程序中&#xff0c;这个复用程序具体是什么&#xff0c;是Redis的主线程吗 在Redis的I/O多路复用机制中&#xff0c;“复用程序”实际上指的是操作系统提供的系统调用接口&#xff0c;如Linux下的epoll、sel…

ZYNQ学习之Ubuntu环境下的Shell与APT下载工具

基本都是摘抄正点原子的文章&#xff1a;<领航者 ZYNQ 之嵌入式Linux 开发指南 V3.2.pdf&#xff0c;因初次学习&#xff0c;仅作学习摘录之用&#xff0c;有不懂之处后续会继续更新~ 一、Ubuntu Shell操作 简单的说Shell 就是敲命令。国内把 Linux 下通过命令行输入命令叫…

如何本地搭建群晖虚拟机并实现无quickconnect服务环境远程访问

文章目录 前言本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是前排提醒&#xff1a; 1. 搭建群晖虚拟机1.1 下载黑群晖文件vmvare虚拟机安装包1.2 安装VMware虚拟机&#xff1a;1.3 解压黑群晖虚拟机文件1.4 虚拟机初始化1.5 没有搜索到黑群晖的解…

蓝桥04数组矩阵

04数组矩阵 顺时针打印二维数组 0所在行列清零 z字形打印二维数组 找出边界为1的最大子方针 返回子数组最大累加和 子矩阵最大累加和 矩阵运算 顺时针打印二维数组 int[][] arr {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16},{17,18,19,20}};int r 0;int c 0;int…

中国象棋C++

题目描述 在中国象棋中正所谓新手玩车&#xff0c;熟手玩炮&#xff0c;老手玩马&#xff0c;由此可见象棋中炮的地位还是比较高的。 给定一个nm的棋盘&#xff0c;全部摆满炮&#xff0c;我们视所有炮都不属于同一阵营&#xff0c;他们之间可以相互攻击但不能不进行攻击直接移…

解密Google Cloud 全新 PaLM2及创新应用

&#x1f4f8;背景 因长期在大模型相关的部门工作&#xff0c;每天接收到很多和AI相关的信息&#xff0c;但小编意识到目前理解到的一些AI知识还有些片面。 恰逢稀土掘金开发者大会有谈到大模型相关的知识&#xff0c;于是借此机会&#xff0c;对大模型相关的一些知识再了解一…

面试问答:什么是索引?它有哪些优缺点?它的适用/不适用场景?哪些情况会造成索引失效?

文章目录 &#x1f412;个人主页&#xff1a;信计2102罗铠威&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;什么是索引&#xff1f;&#xff08;按角度答&#xff01;&#xff1a;作用&#xff0c;存放位置&#xff09;&#x1f415;索引的优缺点&…