55-硅谷课堂1(项目概述+MyBatisPlus使用+搭建项目环境+开发讲师管理接口)

55-硅谷课堂1(项目概述+MyBatisPlus使用+搭建项目环境+开发讲师管理接口)-- 笔记

笔记内容来源与尚硅谷教学视频


文章目录


笔记中涉及资源:

链接:https://pan.baidu.com/s/1fNdmp8CS9gx5K9QHoItsfQ
提取码:Coke

一、硅谷课堂概述

①:项目介绍

硅谷课堂是尚硅谷与腾讯云官方合作的项目,是一款基于微信公众号B2C模式的在线学习平台,该平台包含三大模块:直播、教学与微信消息服务;平台会定期推出直播课程,方便学员与名师之间的交流互动,学员也可以购买教学视频在线学习,分享直播与教学视频获取平台收益,平台支持直播、腾讯云视频点播、微信支付、微信授权登录、微信菜单、微信消息与腾讯云文件存储等一系列功能,为学员构建了一个全方位的在线学习平台。

硅谷课堂项目具有很强的实用性,业务场景贴近实际,技术应用紧跟市场潮流,完全按照市场需求开发。既是对主流Java技术的系统性梳理和整合,同时也是各种主流技术实际应用的练兵场,能够帮助Java程序员积累项目经验。本套教程会在腾讯云开发者社区同步上线,你也可以在“腾讯云开发者社区”学习和下载教程。

②:硅谷课程流程图

在这里插入图片描述

③:硅谷课堂功能架构

在这里插入图片描述

④:硅谷课堂技术架构

在这里插入图片描述

⑤:硅谷课堂核心技术

1.后端技术

SpringBoot:简化新Spring应用的初始搭建以及开发过程

SpringCloud:基于Spring Boot实现的云原生应用开发工具,SpringCloud使用的技术:(Spring Cloud Gateway、Spring Cloud Alibaba Nacos、Spring Cloud Alibaba Sentinel、Spring Cloud Alibaba Seata、Spring Cloud Task和Spring Cloud Feign等)

MyBatis-Plus:持久层框架

Redis:内存缓存

RabbitMQ:消息中间件

腾讯云:文件存储

腾讯云:视频点播

欢拓云直播:直播平台

微信支付

Nginx:负载均衡

Lombok

Mysql:关系型数据库

2. 前端技术

Vue.js:web 界面的渐进式框架

Node.js: JavaScript 运行环境

Axios:Axios 是一个基于 promise 的 HTTP 库

NPM:包管理器

Babel:转码器

Webpack:打包工具

3. 其他技术

Docker :容器技术

Git:代码管理工具

DockerFile:管理Docker镜像命令文本

二、技术点-MyBatisPlus

①:MyBatisPlus简介

1. 概述

官网:https://baomidou.com/
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

2. 特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多种数据库
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 XML 热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 支持关键词自动转义:支持数据库关键词(order、key…)自动转义,还可自定义关键词
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
  • 内置 Sql 注入剥离器:支持 Sql 注入剥离,有效预防 Sql 注入攻击

②:MyBatisPlus入门

在这里插入图片描述

1. 创建测试数据库和表

mybatis_plus

其表结构如下:

idnameageemail
1Jone18test1@baomidou.com
2Jack20test2@baomidou.com
3Tom28test3@baomidou.com
4Sandy21test4@baomidou.com
5Billie24test5@baomidou.com

其对应的建表语句如下:

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

其对应的数据库 Data 脚本如下:

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2. 创建项目和添加依赖

(1)使用 Spring Initializr 初始化 Spring Boot 工程

Group:com.atguigu

Artifact:mybatis-plus

版本:2.2.1.RELEASE

(2)项目引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
     </dependency>

    <!--mybatis-plus-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.1</version>
    </dependency>

    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!--lombok用来简化实体类-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

(3)idea中安装lombok插件

在这里插入图片描述

3. 创建配置文件

mysql5

#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus
spring.datasource.username=root
spring.datasource.password=123456

mysql8以上(spring boot 2.1)注意:driver和url的变化

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

注意:

1、这里的 url 使用了 ?serverTimezone=GMT%2B8 后缀,因为Spring Boot 2.1 集成了 8.0版本的jdbc驱动,这个版本的 jdbc 驱动需要添加这个后缀,否则运行测试用例报告如下错误:

java.sql.SQLException: The server time zone value ‘Öйú±ê׼ʱ¼ä’ is unrecognized or represents more

2、这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建议使用这个驱动,之前的 com.mysql.jdbc.Driver 已经被废弃,否则运行测试用例的时候会有 WARN 信息

4. 编写代码

(1)创建启动类

在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹

@SpringBootApplication
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MybatisPlusApplication {
    ......
}

(2)创建实体类

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

(3)创建Mapper

public interface UserMapper extends BaseMapper<User> {
    
}

(4)功能测试-查询所有记录

public class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelectList() {
        System.out.println(("----- selectAll method test ------"));
        //UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper
        //所以不填写就是无任何条件
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

注意:

IDEA在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。

为了避免报错,可以在 dao 层 的接口上添加 @Repository 注解

③:MyBatisPlus实现CRUD操作

1. 插入操作

public class CRUDTests {
    @Autowired
    private UserMapper userMapper;
    @Test
    public void testInsert(){
        User user = new User();
        user.setName("mary");
        user.setAge(18);
        user.setEmail("atguigu@qq.com");
        int result = userMapper.insert(user);
        System.out.println(result); //影响的行数
        System.out.println(user); //id自动回填
    }
}

**注意:**数据库插入id值默认为:全局唯一id

在这里插入图片描述

查看sql输出日志

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2. 主键策略

(1)ID_WORKER

MyBatis-Plus默认的主键策略是:ID_WORKER 全局唯一ID

(2)自增策略

  • 要想主键自增需要配置如下主键策略

    • 需要在创建数据表的时候设置主键自增
    • 实体字段中配置 @TableId(type = IdType.AUTO)
@TableId(type = IdType.AUTO)
private Long id;

其它主键策略:分析 IdType 源码可知

public enum IdType {
     /**
     * 数据库ID自增
     */
    AUTO(0),
    
    /**
     * 该类型为未设置主键类型
     */
    NONE(1),
    
    /**
     * 用户输入ID
     * 该类型可以通过自己注册自动填充插件进行填充
     */    
    INPUT(2),
    
    /**
     * 全局唯一ID
     */    
    ASSIGN_ID(3),
    
    /**
     * 全局唯一ID (UUID)
     */
    ASSIGN_UUID(4),
    
    /** @deprecated */
    @Deprecated
    ID_WORKER(3),
    /** @deprecated */
    @Deprecated
    ID_WORKER_STR(3),
    /** @deprecated */
    @Deprecated
    UUID(4);
    private final int key;
    private IdType(int key) {
        this.key = key;
    }
    public int getKey() {
        return this.key;
    }
}

3. 根据Id更新操作

**注意:**update时生成的sql自动是动态sql:UPDATE user SET age=? WHERE id=?

    @Test
    public void testUpdateById(){
        //1 根据id查询记录
        User user = userMapper.selectById(1L);
        //2 设置修改的值
        user.setAge(50);
        //3 调用方法修改
        int result = userMapper.updateById(user);
        System.out.println(result);
    }

4. 分页查询

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

(1)创建配置类

/**
 * 分页插件
 */
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

(2)测试selectPage分页

**测试:**最终通过page对象获取相关数据

@Test
public void testSelectPage() {
    Page<User> page = new Page<>(1,5);
    userMapper.selectPage(page, null);
    page.getRecords().forEach(System.out::println);
    System.out.println(page.getCurrent());
    System.out.println(page.getPages());
    System.out.println(page.getSize());
    System.out.println(page.getTotal());
    System.out.println(page.hasNext());
    System.out.println(page.hasPrevious());
}

控制台sql语句打印:SELECT id,name,age,email,create_time,update_time FROM user LIMIT 0,5

5. 根据id删除记录

@Test
public void testDeleteById(){
    int result = userMapper.deleteById(8L);
    System.out.println(result);
}

6. 批量删除

    @Test
    public void testDeleteBatchIds() {
        int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
        System.out.println(result);
    }

7. 逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

(1)数据库中添加 deleted字段

ALTER TABLE `user` ADD COLUMN `deleted` boolean

(2)实体类添加deleted字段

并加上 @TableLogic 注解

@TableLogic
private Integer deleted;

(3)application.properties 加入配置

此为默认值,如果你的默认值和mp默认的一样,该配置可无

mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0

(5)测试逻辑删除

  • 测试后发现,数据并没有被删除,deleted字段的值由0变成了1
  • 测试后分析打印的sql语句,是一条update
  • **注意:**被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作
/**
 * 测试 逻辑删除
 */
@Test
public void testLogicDelete() {
    int result = userMapper.deleteById(1L);
    System.out.println(result);
}

(7)测试逻辑删除后的查询

MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断

/**
 * 测试 逻辑删除后的查询:
 * 不包括被逻辑删除的记录
 */
@Test
public void testLogicDeleteSelect() {
    User user = new User();
    List<User> users = userMapper.selectList(null);
    users.forEach(System.out::println);
}

测试后分析打印的sql语句,包含 WHERE deleted=0

SELECT id,name,age,email,create_time,update_time,deleted FROM user WHERE deleted=0

④:MyBatisPlus条件构造器

在这里插入图片描述

Wrapper : 条件构造抽象类,最顶端父类

AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件

​ QueryWrapper : Entity 对象封装操作类,不是用lambda语法

​ UpdateWrapper : Update 条件封装,用于Entity对象更新操作

AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。

​ LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper

​ LambdaUpdateWrapper : Lambda 更新封装Wrapper

注意:以下条件构造器的方法入参中的 column 均表示数据库字段

1. QueryWrapper 使用

(1)ge、gt、le、lt

@Test
public void testSelect() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.ge("age", 28);
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}

(2)eq、ne

**注意:**seletOne返回的是一条实体记录,当出现多条时会报错

@Test
public void testSelectOne() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name", "Tom");
    User user = userMapper.selectOne(queryWrapper);
    System.out.println(user);
}

SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 AND name = ?

(3)like、likeLeft、likeRight

selectMaps返回Map集合列表

@Test
public void testSelectMaps() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper
        .like("name", "e")
        .likeRight("email", "t");
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
    maps.forEach(System.out::println);
}

SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 AND name LIKE ? AND email LIKE ?

(4)orderByDesc、orderByAsc

@Test
public void testSelectListOrderBy() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.orderByDesc("id");
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 ORDER BY id DESC

2. LambdaQueryWrapper 使用

@Test
public void testLambdaQuery() {
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(User::getAge,30);
    queryWrapper.like(User::getName,"张");
    List<User> list = userMapper.selectList(queryWrapper);
    System.out.println(list);
}

SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 AND age = ? AND name LIKE ?

⑤:MyBatisPlus封装Service层

1. 创建service

public interface UserService extends IService<User> {
    
}

2. 创建service实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

底层封装了注入Mapper过程
在这里插入图片描述

3. 方法调用测试

@SpringBootTest
class TestApplicationTests {

    //注入service
    @Autowired
    private UserService userService;
    
    //查询表所有数据
    @Test
    public void findAll() {
        List<User> userList = userService.list();
        for (User user:userList) {
            System.out.println(user);
        }
    }
}

三、搭建项目工程

①:项目数据库设计

1. 创建数据库和表

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

2. 数据库设计规则

以下规则只针对本模块,更全面的文档参考《阿里巴巴Java开发手册》:

1、库名与应用名称尽量一致

2、表名、字段名必须使用小写字母或数字,禁止出现数字开头,

3、表名不使用复数名词

4、表的命名最好是加上“业务名称_表的作用”。如,edu_teacher

5、表必备三字段:id, gmt_create, gmt_modified

说明:

其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。

(如果使用分库分表集群部署,则id类型为verchar,非自增,业务中使用分布式id生成器)

gmt_create, gmt_modified 的类型均为 datetime 类型,前者现在时表示主动创建,后者过去分词表示被 动更新。

6、单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

7、表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint (1 表示是,0 表示否)。

说明:任何字段如果为非负数,必须是 unsigned。

注意:POJO 类中的任何布尔类型的变量,都不要加 is 前缀。数据库表示是与否的值,使用 tinyint 类型,坚持 is_xxx 的 命名方式是为了明确其取值含义与取值范围。

正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。

8、小数类型为 decimal,禁止使用 float 和 double。 说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。

9、如果存储的字符串长度几乎相等,使用 char 定长字符串类型。

10、varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。

11、唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。

说明:uk_ 即 unique key;idx_ 即 index 的简称

12、不得使用外键与级联,一切外键概念必须在应用层解决。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

②:工程目录结构

在这里插入图片描述

模块说明

**ggkt_parent:**硅谷课堂根目录(父工程),管理多个子模块:

common:公共模块父节点

​ common_util:工具类模块,所有模块都可以依赖于它

​ service_utils:service服务的base包,包含service服务的公共配置类,所有service模块依赖于它

​ rabbit_utils:rabbitmq封装工具类

model:实体类相关模块

server-gateway:服务网关

service:api接口服务父节点

​ service_acl:权限管理接口服务

​ service_activity:优惠券api接口服务

​ service_live:直播课程api接口服务

​ service_order:订单api接口服务

​ service_user:用户api接口服务

​ service_vod:点播课程 api接口服务

​ service_wechat:公众号api接口服务

service-client:feign服务调用父节点

​ service-activity-client:优惠券api接口

​ service-live-client:直播课程api接口

​ service-order-client:订单api接口

​ service-user-client:用户api接口

​ service-vod-client:点播课程api接口

③:创建父工程

1. 创建父工程ggkt_parent

在idea开发工具中,使用 Spring Initializr 快速初始化一个 Spring Boot 模块

在这里插入图片描述

配置:

groupId:com.it

artifactId:classRoom_parent

在这里插入图片描述

2. 删除src目录

3. 引入依赖

修改SpringBoot版本为 :2.2.1.RELEASE

在这里插入图片描述

删除<dependencies>

添加如下依赖

    <properties>
        <skipTests>true</skipTests>
        <java.version>1.8</java.version>
        <cloud.version>Hoxton.RELEASE</cloud.version>
        <alibaba.version>2.2.0.RELEASE</alibaba.version>
        <mybatis-plus.version>3.4.1</mybatis-plus.version>
        <mysql.version>8.0.11</mysql.version>
        <swagger.version>2.9.2</swagger.version>
        <jwt.version>0.7.0</jwt.version>
        <fastjson.version>1.2.29</fastjson.version>
        <httpclient.version>4.5.1</httpclient.version>
        <easyexcel.version>2.2.0-beta2</easyexcel.version>
        <aliyun.version>4.5.14</aliyun.version>
        <jodatime.version>2.10.1</jodatime.version>
        <jwt.version>0.7.0</jwt.version>
        <xxl-job.version>2.3.0</xxl-job.version>
        <aliyun.oss.version>3.9.0</aliyun.oss.version>
    </properties>

    <!--配置dependencyManagement锁定依赖的版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--mybatis-plus 持久层-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
<!--                <version>3.4.1</version>-->
            </dependency>


            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>

            <dependency>
                <groupId>com.github.xiaoymin</groupId>
                <artifactId>knife4j-spring-boot-starter</artifactId>
                <version>2.0.8</version>
            </dependency>

            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
<!--                <version>0.7.0</version>-->
                <version>${jwt.version}</version>
            </dependency>


            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
<!--                <version>4.5.1</version>-->
                <version>${httpclient.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
<!--                <version>1.2.29</version>-->
                <version>${fastjson.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
<!--                <version>2.2.0-beta2</version>-->
                <version>${easyexcel.version}</version>
            </dependency>
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-sdk-core</artifactId>
<!--                <version>4.5.14</version>-->
                <version>${aliyun.version}</version>
            </dependency>

            <!--aliyunOSS-->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
<!--                <version>3.9.0</version>-->
                <version>${aliyun.oss.version}</version>
            </dependency>

            <!--日期时间工具-->
            <dependency>
                <groupId>joda-time</groupId>
                <artifactId>joda-time</artifactId>
<!--                <version>2.10.1</version>-->
                <version>${jodatime.version}</version>
            </dependency>

            <dependency>
                <groupId>com.xuxueli</groupId>
                <artifactId>xxl-job-core</artifactId>
<!--                <version>2.3.0</version>-->
                <version>${xxl-job.version}</version>
            </dependency>
            <!--swagger-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
<!--                <version>2.9.2</version>-->
                <version>${swagger.version}</version>
            </dependency>
            <!--swagger ui-->

            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
<!--                <version>2.9.2</version>-->
                <version>${swagger.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

④:创建model模块

1. 创建子模块model

在这里插入图片描述

2. 配置模块

groupId:com.it
artifactId:model

在这里插入图片描述

3. 引入依赖

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <scope>provided </scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <scope>provided </scope>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <!--在引用时请在maven中央仓库搜索2.X最新版本号-->
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
            <scope>provided </scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <scope>provided </scope>
        </dependency>

        <!--创建索引库的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <scope>provided </scope>
        </dependency>
    </dependencies>

4. 复制model代码

在这里插入图片描述

⑤:创建service模块

1. 创建子模块service

在这里插入图片描述

2. service模块引入依赖

<dependencies>
    <!--数据载体-->
    <dependency>
        <groupId>com.it</groupId>
        <artifactId>model</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <!--web 需要启动项目-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--mybatis-plus-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
    </dependency>

    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- 服务注册 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    <!-- 服务调用feign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <!-- 流量控制 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>

    <!--开发者工具-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

在这里插入图片描述

⑥:创建service_vod模块

在service模块创建子模块service_vod

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

四、后台管理系统-讲师管理接口

①:讲师管理模块需求

添加课程时候,需要选择所属讲师,所以要对讲师进行管理,就是基于讲师的CRUD操作

②:讲师管理模块配置

1. 生成模块代码

(1)引入代码生成器依赖(service_vod模块中)

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.3.1</version>
</dependency>

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
</dependency>

(2)复制生成代码工具类
在这里插入图片描述
修改代码中路径、数据库、包和表,复制到test目录下

  • 代码如下
public class CodeGet {

    public static void main(String[] args) {

        // 1、创建代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 2、全局配置
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        //gc.setOutputDir(projectPath + "/src/main/java");
        gc.setOutputDir("D:\\OOP\\java\\develop_idea\\09_IT_ClassRoom\\classRoom_parent\\service\\service_vod"+"/src/main/java");

        gc.setServiceName("%sService");	//去掉Service接口的首字母I
        gc.setAuthor("it");
        gc.setOpen(false);
        mpg.setGlobalConfig(gc);

        // 3、数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/classroom_vod?serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 4、包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.it");
        pc.setModuleName("vod"); //模块名

        pc.setController("controller");
        pc.setEntity("entity");
        pc.setService("service");
        pc.setMapper("mapper");
        mpg.setPackageInfo(pc);

        // 5、策略配置
        StrategyConfig strategy = new StrategyConfig();

        strategy.setInclude("teacher");

        strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略

        strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
        strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作

        strategy.setRestControllerStyle(true); //restful api风格控制器
        strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符

        mpg.setStrategy(strategy);

        // 6、执行
        mpg.execute();
    }
}

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

(3)实体类统一替换为model模块的实体类

在这里插入图片描述

2. 创建配置文件和启动类 (service_vod)

配置文件

# 服务端口
server.port=8301
# 服务名
spring.application.name=service-vod

# 环境设置:dev、test、prod
spring.profiles.active=dev

# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/classroom_vod?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root

#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

启动类

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

在这里插入图片描述

③:查询所有讲师列表接口

1. 编写controller

@RestController
@RequestMapping("/vod/teacher")
public class TeacherController {

    @Autowired
    private TeacherService teacherService;

    /**
     * url: http://localhost:8301/vod/teacher/findAll
     * 查询所有讲师
     * @return
     */
    @GetMapping("/findAll")
    public List<Teacher> findAll(){
        // 调用service方法
        List<Teacher> list = teacherService.list();
        return list;
    }
}

2. 编写配置类

@Configuration
@MapperScan("com.it.vod.mapper")
public class VodConfig {
}

在这里插入图片描述

3. 运行启动类

访问: http://localhost:8301/vod/teacher/findAll 得到json数据
在这里插入图片描述

④:逻辑删除讲师接口

1. 编写controller

TeacherController添加删除方法

    /**
     * 根据id删除讲师
     * @param id
     * @return
     */
    @DeleteMapping("/remove/{id}")
    public boolean removeTeacher(@PathVariable("id") Long id){
        boolean isSuccess = teacherService.removeById(id);
        return isSuccess;
    }

​ 因为删除讲师接口是delete提交方式,使用浏览器无法直接访问测试,可以通过工具测试,比如Postman,我们这里通过整合Swagger2进行接口测试

⑤:配置Swagger2生成API接口文档

配置笔记路径:https://blog.csdn.net/cygqtt/article/details/127406232

⑥:定义统一返回结果对象

项目中我们会将响应封装成json返回,一般我们会将所有接口的数据格式统一, 使前端(iOS Android, Web)对数据的操作更一致、轻松。

一般情况下,统一返回数据格式没有固定的格式,只要能描述清楚返回的数据状态以及要返回的具体数据就可以。但是一般会包含状态码、返回消息、数据这几部分内容

例如,我们的系统要求返回的基本数据格式如下:

列表:

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "id": 2,
      "name": "欧阳老师",
      "intro": "高级讲师"
    }
  ],
  "ok": true
}

分页:

{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "id": 2,
        "name": "欧阳老师",
        "intro": "高级讲师"
      },
      {
        "id": 4,
        "name": "上官老师",
        "intro": "高级讲师"
      },
      {
        "id": 5,
        "name": "东方老师",
        "intro": "高级老师"
      }
    ],
    "total": 10,
    "size": 3,
    "current": 1,
    "orders": [],
    "hitCount": false,
    "searchCount": true,
    "pages": 2
  },
  "ok": true
}

没有返回数据:

{
  "code": 200,
  "message": "成功",
  "data": null,
  "ok": true
}

失败:

{
  "code": 201,
  "message": "失败",
  "data": null,
  "ok": false
}

1. 创建结果类

在service_utils模块创建interfacle定义返回状态码
在这里插入图片描述

import lombok.Getter;

/**
 * 统一返回结果状态信息类
 *
 */
@Getter
public enum ResultCodeEnum {

    SUCCESS(200,"成功"),
    FAIL(201, "失败"),
    SERVICE_ERROR(2012, "服务异常"),
    DATA_ERROR(204, "数据异常"),
    ILLEGAL_REQUEST(205, "非法请求"),
    REPEAT_SUBMIT(206, "重复提交"),

    LOGIN_AUTH(208, "未登陆"),
    PERMISSION(209, "没有权限"),

    PHONE_CODE_ERROR(211, "手机验证码错误"),

    MTCLOUD_ERROR(210, "直播接口异常"),

    COUPON_GET(220, "优惠券已经领取"),
    COUPON_LIMIT_GET(221, "优惠券已发放完毕"),

    FILE_UPLOAD_ERROR( 21004, "文件上传错误"),
    FILE_DELETE_ERROR( 21005, "文件刪除错误"),

    VOD_PALY_ERROR(209, "请购买后观看"),;

    private Integer code;

    private String message;

    private ResultCodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

在service_utils模块创建结果类

@Data
@Api(tags = "全局统一返回结果")
public class Result<T> {

    @ApiModelProperty(value = "返回码")
    private Integer code; // 状态码

    @ApiModelProperty(value = "返回状态信息(成功 失败)")
    private String message; // 返回状态信息(成功 失败)

    @ApiModelProperty(value = "返回数据")
    private T data; // 返回数据

    public Result() {
    }

    /**
     * 统一返回数据方法
     * @param code
     * @param message
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> buid(Integer code, String message, T data) {
        Result<T> result = new Result<>();
        if (data != null){
            result.setData(data);
        }
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    /**
     *成功 无返回数据
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(){
        return ok(null);
    }

    /**
     * 成功 有返回数据
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(T data){
        return buid(200,"成功~",data);
    }

    /**
     * 失败 无返回数据
     * @param <T>
     * @return
     */
    public static<T> Result<T> fail(){
        return fail(null);
    }

    /**
     * 失败 有返回数据
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> fail(T data){
        return buid(201,"失败~",data);
    }

    /**
     * 修改返回状态信息
     * @param msg
     * @return
     */
    public Result<T> message(String msg){
        this.setMessage(msg);
        return this;
    }

    /**
     * 修改返回状态码
     * @param code
     * @return
     */
    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }
}

2. 修改controller返回结果

@Api(tags = "讲师管理接口")
@RestController
@RequestMapping(value="/admin/vod/teacher")
public class TeacherController {

    @Autowired
    private TeacherService teacherService;

    // http://localhost:8301/admin/vod/teacher/findAll
    //1 查询所有讲师
    @ApiOperation("查询所有讲师")
    @GetMapping("findAll")
    public Result findAllTeacher() {
        //调用service方法
        List<Teacher> list = teacherService.list();
        return Result.ok(list).message("查询数据成功");
    }

    // remove/1
    //2 逻辑删除讲师
    @ApiOperation("逻辑删除讲师")
    @DeleteMapping("remove/{id}")
    public Result removeTeacher(@ApiParam(name = "id", value = "ID", required = true)
                                     @PathVariable Long id) {
        boolean isSuccess = teacherService.removeById(id);
        if(isSuccess) {
            return Result.ok(null);
        } else {
            return Result.fail(null);
        }
    }
}
  • 重新启动服务,测试查询和删除功能(正常)

⑦:条件分页查询讲师列表接口

1. 创建配置类

/**
 * 配置类
 */
@Configuration
@MapperScan("com.it.vod.mapper")
public class VodConfig {

    /**
     * 分页插件
     * @return PaginationInterceptor
     */
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

2. 创建查询条件对象

在这里插入图片描述

@Data
public class TeacherQueryVo {
	
	@ApiModelProperty(value = "讲师姓名")
	private String name;

	@ApiModelProperty(value = "头衔 1高级讲师 2首席讲师")
	private Integer level;

	@ApiModelProperty(value = "入驻时间")
	private String joinDateBegin;

	@ApiModelProperty(value = "入驻时间")
	private String joinDateEnd;
}

3. 编写controller

//条件查询分页列表
@ApiOperation(value = "获取分页列表")
@PostMapping("{page}/{limit}")
public Result index(
        @ApiParam(name = "page", value = "当前页码", required = true)
        @PathVariable Long page,
        @ApiParam(name = "limit", value = "每页记录数", required = true)
        @PathVariable Long limit,
        @ApiParam(name = "teacherVo", value = "查询对象", required = false)
        @RequestBody(required = false) TeacherQueryVo teacherQueryVo) {
    //创建page对象,传递当前页和每页记录数
    Page<Teacher> pageParam = new Page<>(page, limit);
    //获取条件值
    String name = teacherQueryVo.getName();//讲师名称
    Integer level = teacherQueryVo.getLevel();//讲师级别
    String joinDateBegin = teacherQueryVo.getJoinDateBegin();//开始时间
    String joinDateEnd = teacherQueryVo.getJoinDateEnd();//结束时间
    //封装条件
    QueryWrapper<Teacher> wrapper = new QueryWrapper<>();
    if(!StringUtils.isEmpty(name)) {
        wrapper.like("name",name);
    }
    if(!StringUtils.isEmpty(level)) {
        wrapper.eq("level",level);
    }
    if(!StringUtils.isEmpty(joinDateBegin)) {
        wrapper.ge("join_date",joinDateBegin);
    }
    if(!StringUtils.isEmpty(joinDateEnd)) {
        wrapper.le("join_date",joinDateEnd);
    }
    //调用方法得到分页查询结果
    IPage<Teacher> pageModel = teacherService.page(pageParam, wrapper);
    return Result.ok(pageModel);
}

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

⑧:添加讲师接口

1. 编写controller

@ApiOperation(value = "新增")
@PostMapping("save")
public Result save(@RequestBody Teacher teacher) {
	teacherService.save(teacher);
	return Result.ok(null);
}

⑨:修改讲师接口

1. 编写id查询方法

@ApiOperation(value = "获取")
@GetMapping("get/{id}")
public Result get(@PathVariable Long id) {
    Teacher teacher = teacherService.getById(id);
    return Result.ok(teacher);
}

2. 编写修改方法

@ApiOperation(value = "修改")
@PutMapping("update")
public Result updateById(@RequestBody Teacher teacher) {
    teacherService.updateById(teacher);
    return Result.ok(null);
}

⑩:批量删除讲师接口

1. 编写controller

@ApiOperation(value = "根据id列表删除")
@DeleteMapping("batchRemove")
public Result batchRemove(@RequestBody List<Long> idList) {
	teacherService.removeByIds(idList);
	return Result.ok(null);
}

测试

  • 添加讲师
    在这里插入图片描述
    在这里插入图片描述
  • 查询讲师
    在这里插入图片描述
    在这里插入图片描述
  • 经过测试其他功能都正常

五、统一异常处理

在这里插入图片描述

①:制造异常

除以0

int a = 10/0;

我们想让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要统一异常处理

②:全局异常处理

1. 创建统一异常处理器

在service_utils中创建统一异常处理类GlobalExceptionHandler.java:

/**
 * 统一异常处理类
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result error(Exception e){
        e.printStackTrace();
        return Result.fail().message("执行了全局异常处理");
    }
}

2. 测试

在这里插入图片描述

③:处理特定异常

1. 添加异常处理方法

GlobalExceptionHandler.java中添加

@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public Result error(ArithmeticException e){
	e.printStackTrace();
	return Result.fail().message("执行了特定异常处理");
}

2. 测试

在这里插入图片描述

4、处理自定义异常

在这里插入图片描述

4.1、创建自定义异常类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClassRoomException extends RuntimeException{

    private Integer code;

    private String message;

}

4.2、业务中需要位置抛出

try {
    int i = 10/0;
} catch (Exception e) {
    throw new ClassRoomException(201,"执行了自定义异常");
}

4.3、添加异常处理方法

GlobalExceptionHandler.java中添加

     * 自定义异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(ClassRoomException.class)
    @ResponseBody
    public Result error(ClassRoomException e){
        log.error("自定义...........");
        return Result.fail().code(e.getCode()).message(e.getMessage());
    }

4.4、测试

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七@归七

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值