在线教育项目第二天

一、前后端分离开发

前端
    html css js jq
    主要作用:数据显示
    使用Ajax调用接口,返回json数据
后端
    controller service mapper
    主要作用:返回数据或操作数据
    开发接口指的是开发controller service mapper的过程
开发文档
    后端根据开发文档开发接口
    前端根据开发文档调用接口

二、讲师管理模块后端

1、创建数据库和数据表

create database inline_education;
use inline_education;

CREATE TABLE `edu_teacher` (
  `id` char(19) NOT NULL COMMENT '讲师ID',
  `name` varchar(20) NOT NULL COMMENT '讲师姓名',
  `intro` varchar(500) NOT NULL DEFAULT '' COMMENT '讲师简介',
  `career` varchar(500) DEFAULT NULL COMMENT '讲师资历,一句话说明讲师',
  `level` int(10) unsigned NOT NULL COMMENT '头衔 1高级讲师 2首席讲师',
  `avatar` varchar(255) DEFAULT NULL COMMENT '讲师头像',
  `sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
  `is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='讲师';

INSERT INTO `edu_teacher` VALUES 
	('1','张三','近年主持国家自然科学基金(6项)、江苏省重大科技成果转化项目(5项)、江苏省产学研前瞻性联合研究项目(3项)、省工业科技支撑、省高技术、省自然科学基金等省部级及其企业的主要科研项目40多个,多个项目在企业成功转化,产生了较好的经济、社会和环境效益。积极开展产学研科技合作,并与省内16家企业建立了江苏省研究生工作站,其中6家为江苏省优秀研究生工作站','高级',1,'https://guli-file-190513.oss-cn-beijing.aliyuncs.com/avatar/default.jpg',0,0,'2019-10-30 14:18:46','2019-11-12 13:36:36'),	
	('1189389726308478977','晴天','高级讲师简介','高级讲师资历',2,'https://online-teach-file.oss-cn-beijing.aliyuncs.com/teacher/2019/10/30/de47ee9b-7fec-43c5-8173-13c5f7f689b2.png',1,0,'2019-10-30 11:53:03','2019-10-30 11:53:03'),
	('1189390295668469762','李刚','高级讲师简介','高级讲师',2,'https://online-teach-file.oss-cn-beijing.aliyuncs.com/teacher/2019/10/30/b8aa36a2-db50-4eca-a6e3-cc6e608355e0.png',2,0,'2019-10-30 11:55:19','2019-11-12 13:37:52'),
	('1189426437876985857','王二','高级讲师简介','高级讲师',1,'https://online-teach-file.oss-cn-beijing.aliyuncs.com/teacher/2019/11/08/e44a2e92-2421-4ea3-bb49-46f2ec96ef88.png',0,0,'2019-10-30 14:18:56','2019-11-12 13:37:35'),
	('1189426464967995393','王五','高级讲师简介','高级讲师',1,'https://online-teach-file.oss-cn-beijing.aliyuncs.com/teacher/2019/10/30/65423f14-49a9-4092-baf5-6d0ef9686a85.png',0,0,'2019-10-30 14:19:02','2019-11-12 13:37:18'),
	('1192249914833055746','李四','高级讲师简介','高级讲师',1,'https://online-teach-file.oss-cn-beijing.aliyuncs.com/teacher/2019/11/07/91871e25-fd83-4af6-845f-ea8d471d825d.png',0,0,'2019-11-07 09:18:25','2019-11-12 13:37:01'),('1192327476087115778','1222-12-12','1111','11',1,'https://online-teach-file.oss-cn-beijing.aliyuncs.com/teacher/2019/11/08/5805c6cd-c8ad-4a77-aafd-d2e083bfd8a4.png',0,1,'2019-11-07 14:26:37','2019-11-11 16:26:26'),
	('1195337453429129218','test','sdfsdf','sdfdf',1,'https://guli-file-190513.oss-cn-beijing.aliyuncs.com/avatar/default.jpg',0,1,'2019-11-15 21:47:12','2019-11-15 21:47:27');

注意:表必备三字段 id gmt_create gmt_modified

2、项目结构

创建父工程
    类型:pom
    管理依赖版本和放公共依赖
    子模块一
        创建子子模块,如讲师管理模块
    子模块二
父工程是springboot工程,子模块和子子模块都是maven工程
orange-parent:在线教学根目录(父工程),管理四个子模块:
    canal-client:canal数据库表同步模块(统计同步数据)
    common:公共模块父节点
        common-util:工具类模块,所有模块都可以依赖于它
        service-base:service服务的base包,包含service服务的公共配置类,所有service模块依赖于它
        spring-security:认证与授权模块,需要认证授权的service服务依赖于它
    infrastructure:基础服务模块父节点
        api-gateway:api网关服务
    service:api接口服务父节点
        service-acl:用户权限管理api接口服务(用户管理、角色管理和权限管理等)
        service-cms:cms api接口服务
        service-edu:教学相关api接口服务
        service-msm:短信api接口服务
        service-order:订单相关api接口服务
        service-oss:阿里云oss api接口服务
        service-statistics:统计报表api接口服务
        service-ucenter:会员api接口服务
        service-vod:视频点播api接口服务

3、创建项目

创建父工程orange_parent
创建一个springboot项目作为父工程
修改pom.xml
    在<artifactId>orange_parent</artifactId>后面加上<packaging>pom</packaging>
    删除dependencies标签,统一将依赖放到子模块中,父工程放依赖的版本
    删除src目录
    添加properties标签确定依赖的版本
    添加dependencyManagement标签锁定依赖的版本,对版本进行管理,不是直接用,用还需要引入
创建子模块service
父工程右键新建Module 选择Maven
修改pom.xml
    <artifactId>service</artifactId>后加上<packaging>pom</packaging>
    添加依赖,父工程中只是对依赖版本的管理,没有真正引入
    注意:如果有的依赖报错unknown,可以查看依赖仓库中的版本给依赖加上version标签
    将spring-boot-starter-web之上的依赖注释,否则如果功能没有写完就启动会报错
    spring-boot-starter-web依赖指的是该子模块是一个web工程
删除src目录
创建service的子模块service_edu
在resources文件夹中创建配置文件application.properties
注意pom.xml中的mysql版本要在8以上,否则spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver会报错
编写controller service mapper
使用mp提供的代码生成器,将CodeGenerator.java复制到test/java中
    将代码输出目录改为绝对路径
    主键生成策略改为ID_WORKER_STR,因为表中id是char类型
    修改数据库配置,代码生成器不能直接使用application.properties中的数据库配置,但可以参考着改
    修改包名配置
    修改策略配置中的表名
    执行
编写讲师列表接口
EduTeacherController
    @RestController注解
        @Controller表示将被注解的内容交给spring管理
        @ResponseBody表示需要返回数据
    注入service
        private EduTeacherService eduTeacherService;
    创建返回讲师列表的方法findAllTeachers
        方法加上注解@GetMapping("findAll") findAll是资源路径 get是rest风格
        调用service的list方法
            List<EduTeacher> teachers = eduTeacherService.list(null);
        mapper注入service的代码已经自动生成
创建启动类EduApplication
加上注解@SpringBootApplication
创建main方法
    SpringApplication.run(EduApplication.class, args);
创建配置类,配置mapper扫描和其它的插件
加上@MapperScan("com.xm.eduservice.mapper")和@Configuration
其中的service有接口和实现类,而mapper只有接口没有实现类,所以需要在配置类上加上注解@MapperScan("com.xm.eduservice.mapper")
加上性能分析插件
启动项目
run启动类的main方法
错误:org/springframework/boot/web/servlet/filter/OrderedHttpPutFormContentFilter
解决:父工程的pom.xml中加上
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>2.4.1</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
错误:This application has no explicit mapping for /error, so you are seeing this as a fallback
原因:注入service没有加上注解@Autowired
问题:默认返回的json时间格式带有时区且是世界标准时间,不是北京时间
解决:在application.properties中加上
编写讲师逻辑删除功能
配置逻辑删除插件
给EduTeacher的isDeleted属性加上@TableLogic
EduTeacherController创建讲师逻辑删除的方法removeTeacher
    方法加上注解@DeleteMapping("{id}") 指的是参数id需要通过路径传递
    参数传递@PathVariable String id 指的是路径中的id
整合swagger进行测试
    swagger好处:1、可以生成在线的接口文档 2、方便接口测试
    在orange_parent下创建公共模块common,整合swagger,使地所有模块都可以使用
    引入依赖,加上<packaging>pom</packaging>,因为还要在里面创建子模块
    删除src目录
    在common里创建子模块service_base
    在service_base里创建配置类SwaggerConfig,加上注解@Configuration和@EnableSwagger2
        配置swagger插件和在线api文档的信息
    使用
        在service的pom.xml中引入service_base的依赖
        在service_edu的启动类中加上注解@ComponentScan(basePackages = {"com.xm"})
            使得启动时会去扫描com.xm下的内容,加载配置类SwaggerConfig
        启动service_edu
        访问swagger http://localhost:8001/swagger-ui.html
            页面会列出当前可以进行测试的Controller
            Controller下显示可以进行测试的接口
            点击接口展开,输入参数,点击Try it out测试,会显示返回数据
    给接口加上注释
        给EduTeacherController加上注解@Api(value = "讲师管理"),页面上会显示相应的注释
        给findAllTeachers方法加上注解@ApiOperation(value = "所有讲师列表")
        给removeTeacher方法加上注解@ApiOperation(value = "根据ID逻辑删除讲师")
        给removeTeacher方法的参数id加上注解@ApiParam(name = "id", value = "讲师ID", required = true)
    错误:Unable to infer base url. This is common when using dynamic servlet registration or when the API is behind an API Gateway. The base url is the root of where all the swagger resources are served. For e.g. if the api is available at http://example.org/api/v2/api-docs then the base url is http://example.org/api/. Please enter the location manually:
    解决:给service_edu的启动类中加上注解@EnableSwagger2
统一返回数据格式
json有两种格式 对象和数组 实际中通常混合使用
    {
     "success": 布尔, //响应是否成功
     "code": 数字, //响应码
     "message": 字符串, //返回消息
     "data": HashMap //返回数据,放在键值对中
    }
在common模块下创建子模块common_utils
在common-utils下将返回状态码抽取为一个接口或常量类或枚举
    public interface ResultCode {
        public static Integer SUCCESS = 20000;//成功
        public static Integer ERROR = 20001;//失败
    }
在common-utils下创建统一返回结果类R
    加上属性success code message给 data,给属性加上注解@ApiModelProperty(value = "是否成功"),swagger页面上会显示注释
    加上注解@Data,自动创建空参构造和get set方法
    将构造方法私有化,不允许别人直接new,要使用R只能调用其中的ok方法和error方法
    创建成功和失败的静态方法
    创建属性的设置方法,其均返回this,即谁调用就返回谁,可以实现链式编程
service的pom.xml加上common_utils的依赖
将EduTeacherController中的方法的返回值均改为R
    注意引入的R是自己创建的类,不是baomidou里的
讲师分页功能
EduConfig配置分页插件PaginationInterceptor
EduTeacherController创建分页查询讲师方法pageListTeacher
    参数使用注解@GetMapping("pageTeacher/{current}/{size}")通过路径传递
    创建Page对象pageTeacher,泛型为EduTeacher
    调用service的方法page,传入参数page对象pageTeacher和查询条件,条件可以为null
        调用该方法,底层会将分页的所有数据封装到pageTeacher对象中
        可以使用pageTeacher对象来获取分页的所有数据,如总记录数和当前页的数据
    调用R的data方法将总记录数和当前页的数据设置到R对象中,并返回R对象
带多条件组合查询的讲师分页功能
    页面组件:查询条件输入框 查询按钮 讲师列表 页码条
    将条件值传递到接口中
        将条件值封装到vo对象中,将对象传递到接口中
    创建TeacherQuery类
        添加属性 讲师姓名 级别 入驻开始时间和结束时间
    EduTeacherController创建pageTeacherCondition方法,使用路径传递参数
        参数current size使用注解@GetMapping("pageTeacher/{current}/{size}")通过路径传递
        传入参数为current size TeacherQuery对象condition
        创建Page对象pageTeacher,传入current和size
        创建QueryWrapper对象wrapper,构建查询条件
            取出条件输入框的值,判断是否为空,不为空则调用wrapper的方法动态拼接条件
        调用service的方法page,传入参数pageTeacher和wrapper
        调用R的data方法将总记录数和当前页的数据设置到R对象中,并返回R对象
        给方法的参数TeacherQuery condition加上注解@RequstBody(required = false)
            表示使用json传递数据,将数据封装到对应对象中去
            @ResponseBody 表示返回数据,一般为json数据
            注意参数加上@RequestBody后,方法需要使用@PostMapping
面试题:用过spring里的哪些注解?
        @RequestBody传递json数据 @ResponseBody返回json数据 @PathVariable通过路径传递的参数
新增讲师功能
给EduTeacher类的gmtCreate加上@TableField(fill = FieldFill.INSERT),gmtModified加上@TableField(fill = FieldFill.INSERT_UPDATE)
在service_base模块中创建自动填充类MyMetaObjectHandler,实现接口MetaObjectHandler,复写方法
    注意wrapper拼接查询条件时,使用的是表中的字段名;而自动填充时使用的是实体类的属性名
EduTeacherController创建添加讲师的方法addTeacher
    使用Post请求
    使用注解@RequestBody传递json格式的参数
    调用service的save方法,返回布尔类型的标记
    判断标记做出返回
测试
    注意不需要自己设置id 创建时间和修改时间
讲师修改功能
根据讲师id查询,便于前端回显
    创建方法
        @GetMapping("getTeacherById/{id}")
        public R getTeacherById(@PathVariable String id) {
            EduTeacher teacher = eduTeacherService.getById(id);
            return R.ok().data("teacher", teacher);
        }
修改
    创建方法
        @PostMapping("updateTeacher")
        public R updateTeacher(@RequestBody EduTeacher teacher) {
            boolean flag = eduTeacherService.updateById(teacher);
            if (flag) {
                return R.ok();
            } else {
                return R.error();
            }
        }
        如果使用put提交要先将路径传入的id设置到方法参数teacher中,再调用方法updateById
测试
    修改讲师接口不用手动设置创建时间和更新时间,但一定要设置id,因为要调用方法updateById
统一异常处理
程序出现异常会报500错误,可以将其改为自己定义的提示
全局异常处理
    在service_base中创建统一异常处理类GlobalExceptionHandler,加上注解@ControllerAdvice
        创建error方法处理所有异常
    service_base的pom.xml引入common_utils依赖,将service的pom.xml中的common_utils依赖删除,防止多次引入
特定异常处理
    GlobalExceptionHandler中创建方法
    有特定异常处理,优先执行特定异常处理
自定义异常处理
    创建自定义异常类OrangeException,继承RuntimeException,加上属性,加上@Data @AllArgsConstructor生成有参构造 @NoArgsConstructor生成无参构造
    GlobalExceptionHandler中创建方法
    自定义异常不会自动抛出,需要手动抛出
        try {
            int i = 10 / 0;
        } catch (OrangeException e) {
            throw new OrangeException(20001, "执行了自定义异常OrangeException处理")
        }
统一日志处理Logback
通过日志可以看到程序的运行状态,更好地定位问题
日志级别
    OFF FATAL ERROR WARN INFO DEBUG ALL 越后打印的信息越多
    默认springboot控制台只打印INFO及以上级别的日志,application.properties可以配置日志级别
        logging.level.root=WARN
Logback日志工具
    可以将日志输出到文件中
    也可以使用log4j工具
    使用
        删除application.properties中的日志配置
        默认有idea彩色日志插件grep-console
        resources中创建logback-spring.xml
    输出异常信息
        在统一异常处理类GlobalExceptionHandler上加上注解@Slf4j
        在异常处理方法中加上
            log.error(e.getMessage());
            表示将异常信息输出到error文件中
        输出更具体的异常信息
            创建工具类ExceptionUtil
            OrangeException中创建toString方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值