• 谷粒学苑_第二天


    第二天:

    讲师管理模块(后端):

    1.导入(设计)数据库

    设计库设计规约(参考了《阿里巴巴java开发手册》):
    在这里插入图片描述

    项目结构

    创建父工程 pom类型 管理依赖的版本,放公共依赖

    guli_parent

    子工程:详细的功能模块

    service

    子子模块:更细分的功能模块

    service_edu

    application.yml

    server:
      port: 8001
    spring:
      application:
        name: service-edu
      profiles:
        active: dev  #环境设置: dev,test,prod
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8
        username: root
        password: 148963
    
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      global-config:
          db-config:
            id-type: ASSIGN_UUID
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    编写controller service mapper

    使用mp的代码生成器

    个人使用mybatisX插件进行自动生成

    MybatisX导入edu_teacher

    先在idea导入mysql
    在这里插入图片描述

    选中一个表,点这个选项
    在这里插入图片描述

    按照管理只要改这4个就行

    拼接成一个完整的路径

    module path(模块路径名)/base path(项目路径名)/base package(包名)/relative package(实体类的包名)

    注意:1.可能各个路径会自动给错,需要检查手动修改

    ​ 2.base package要用点隔离

    ​ 3.实体类包可以写dto或者entity
    在这里插入图片描述

    上面斟酌选择(我加了一个Lombok,maven导入的是3以上的版本,选择mybatis-plus3),下面可以删掉不需要的内容
    在这里插入图片描述

    导入成功
    在这里插入图片描述

    如果出现导的包报错,就调整这两个地方的maven版本一致就行
    在这里插入图片描述

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-npuEwgFz-1662112899188)(D:/lkw%E7%9A%84%E6%96%87%E4%BB%B6/lkw%E7%9A%84md/md%E5%9B%BE%E7%89%87/image-20220830120439615.png)]

    注意修改一些字段,有些字段和属性不能匹配

    讲师列表

    编写第一个controller

    1.创建类,添加注解(默认Rest风格)

    ​ @RestController

    ​ @RequestMapping(“/eduservice/teacher”)

    2.注入Service

    private EduTeacherService eduTeacherService;

    创建一个findAllTeacher方法,使用的GetMapping方法

    package com.lkw.serviceedu.controller;
    
    import com.lkw.serviceedu.entity.EduTeacher;
    import com.lkw.serviceedu.service.EduTeacherService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/eduservice/teacher")
    public class EduTeacherController {
        //注入service
        @Autowired
        private EduTeacherService eduTeacherService;
    
        
        //http://localhost:8001/eduservice/teacher/findAll
        //GetMapping,获取全部的教师列表
        @GetMapping("findAll")
        public List<EduTeacher> findAllTeacher(){
            //调用service的list,查询条件为null(查到的所有都返回)
            List<EduTeacher> list=eduTeacherService.list(null);
            return list;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    config包

    ​ 里面可以加分页,逻辑删除,性能测试之类的配置

    package com.lkw.eduservice.config;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @MapperScan("com.lkw.eduservice.mapper")
    public class EduConfig {
         //乐观锁
        //自动填充
        //分页
        //逻辑删除
        //性能插件
       
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    启动测试

    注意把service的pom.xml的这些多余依赖注释掉,然后刷新maven
    在这里插入图片描述

    启动并且查询成功
    在这里插入图片描述
    检查链接:http://localhost:8001/eduservice/teacher/findAll

    配置时间格式

    在application.yml添加

    spring:
    	jackson:
        	date-format: yyyy-MM-dd HH:mm:ss
        	time-zone: GMT+8
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    讲师删除

    使用的逻辑删除,在配置类添加逻辑删除插件

    //mp版本大于3.1.1不需要配置逻辑删除插件

    //给实体类的逻辑删除属性添加逻辑删除注解
    在这里插入图片描述

    继续编写EduTeacherController,使用@deleteMapping(“{id}”)

     //http://localhost:8001/eduservice/teacher/delete/1
        //逻辑删除讲师
        @DeleteMapping("{id}")
        public boolean removeTeacher(@PathVariable String id){
            return eduTeacherService.removeById(id);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    讲师删除测试

    本项目使用的swagger2,3版本暂时不能配上

    swagger3快速上手

    丝袜哥的作用:获取项目的api,生成准确实时的接口文档

    依赖:

    
    <dependency>
        <groupId>io.springfoxgroupId>
        <artifactId>springfox-boot-starterartifactId>
        <version>3.0.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    添加一个配置类

    package com.lkw.servicebase;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.bind.annotation.RestController;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.oas.annotations.EnableOpenApi;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    
    @Configuration
    @EnableOpenApi
    public class SwaggerConfig {
        @Bean
        public Docket docket(){
            return new Docket(DocumentationType.OAS_30)
                    .apiInfo(apiInfo())
                    .enable(true)
                    .groupName("这是组名")
                    .select()
                    .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                    .paths(PathSelectors.any())
                    .build();
        }
    
    
        @SuppressWarnings("all")
        public ApiInfo apiInfo(){
            return new ApiInfo(
                    "这是标题",
                    "这是描述",
                    "v1.0",
                    "2279719702@qq.com", //开发者团队的邮箱
                    "lkw",
                    "许可证",  //许可证
                    "http://www.baidu.com" //许可证链接
            );
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在启动类添加注解**@EnableWebMvc**

    启动并访问:http://localhost:8080/swagger-ui/index.html

    其他的交给翻译,然后自己看吧

    springcloud+swagger2

    建立一个common子模块和service_base子子模块,为了所有模块都能用
    在这里插入图片描述

    引入common模块的依赖,删除common的src目录:

        <dependencies>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-data-redisartifactId>
            dependency>
    
            
            <dependency>
                <groupId>org.apache.commonsgroupId>
                <artifactId>commons-pool2artifactId>
                <version>2.6.0version>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
                <scope>provided scope>
            dependency>
    
            
            <dependency>
                <groupId>com.baomidougroupId>
                <artifactId>mybatis-plus-boot-starterartifactId>
                <scope>provided scope>
            dependency>
    
            
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <scope>provided scope>
            dependency>
    
            
            <dependency>
                <groupId>io.springfoxgroupId>
                <artifactId>springfox-swagger2artifactId>
                <scope>provided scope>
            dependency>
            <dependency>
                <groupId>io.springfoxgroupId>
                <artifactId>springfox-swagger-uiartifactId>
                <scope>provided scope>
            dependency>
    
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-data-redisartifactId>
            dependency>
    
            
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    创建SwaggerConfig

    package com.lkw.servicebase;
    
    import com.google.common.base.Predicates;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.service.Contact;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
    
        @Bean
        public Docket webApiConfig(){
    
            return new Docket(DocumentationType.SWAGGER_2)
                    .groupName("webApi")
                    .apiInfo(webApiInfo())
                    .select()
    //                .paths(Predicates.not(PathSelectors.regex("/admin/.*")))
                    .paths(Predicates.not(PathSelectors.regex("/error.*")))
                    .build();
    
        }
    
        private ApiInfo webApiInfo(){
    
            return new ApiInfoBuilder()
                    .title("网站-课程中心API文档")
                    .description("本文档描述了课程中心微服务接口定义")
                    .version("1.0")
                    .contact(new Contact("Helen", "http://atguigu.com", "55317332@qq.com"))
                    .build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    service模块的maven引入service_base模块

    <dependency>
         <groupId>com.lkw.servicebasegroupId>
         <artifactId>service_baseartifactId>
         <version>0.0.1-SNAPSHOTversion>
     dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在EduApplication启动类添加组件扫描注解

    @ComponentScan(basePackages={“com.lkw.*”})

    http://localhost:8001/swagger-ui.html

    springcloud+swagger3

    直接改依赖和注解就行
    http://localhost:8001/swagger-ui/

    最后注意给Controller添加注解:@Api(value=“讲师管理模块”)

    给方法添加注解

    在这里插入图片描述

    统一返回数据格式

    将响应封装成一个json使得所有的接口数据格式都统一,方便前端使用,方便维护

    因为json数据格式只有两种(对象,数组),可以设计出较为合适的返回值类型

    {
        "success": 布尔,//相应是否成功
        "code": 数字,//响应码
        "message": 字符串,//返回消息
        "data": HashMap //返回数据,放在键值对里
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在common创建子模块:common_utils

    创建interface,定义返回状态码

    例如成功:20001 失败20001

    package com.lkw.commonutils;
    
    public interface ResultCode {
    
        public static Integer SUCCESS = 20000;//成功
    
        public static Integer ERROR = 20001;//失败
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    统一返回结果类:R

    package com.lkw.commonutils;
    
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @Data
    public class R {
        @ApiModelProperty(value = "是否成功")
        private Boolean success;
    
        @ApiModelProperty(value = "返回码")
        private Integer code;
    
        @ApiModelProperty(value = "返回消息")
        private String message;
    
        @ApiModelProperty(value = "返回数据")
        private Map<String, Object> data = new HashMap<String, Object>();
    
        //构造器私有化,使得不能new该对象
        private R() {
        }
    
        //成功静态方法
        public static R ok() {
            R r = new R();
            r.setSuccess(true);
            r.setCode(ResultCode.SUCCESS);
            r.setMessage("成功");
            return r;
        }
    
        //失败静态方法
        public static R error() {
            R r = new R();
            r.setSuccess(false);
            r.setCode(ResultCode.ERROR);
            r.setMessage("失败");
            return r;
        }
    
        public R success(Boolean success) {
            this.setSuccess(success);
            return this;
        }
    
        public R message(String message) {
            this.setMessage(message);
            return this;
        }
    
        public R code(Integer code) {
            this.setCode(code);
            return this;
        }
    
        public R data(String key, Object value) {
            this.data.put(key, value);
            return this;
        }
    
        public R data(Map<String, Object> map) {
            this.setData(map);
            return this;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    引入依赖到service

    <dependency>
        <groupId>com.lkw.commonutilsgroupId>
        <artifactId>common_utilsartifactId>
        <version>0.0.1-SNAPSHOTversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    修改Controller的返回结果

    package com.lkw.eduservice.controller;
    
    import com.lkw.commonutils.R;
    import com.lkw.eduservice.entity.EduTeacher;
    import com.lkw.eduservice.service.EduTeacherService;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @Api(value = "讲师管理功能")//注解还有其他输出功能,暂时不写
    @RestController
    @RequestMapping("/eduservice/teacher")
    public class EduTeacherController {
        //注入service
        @Autowired
        private EduTeacherService eduTeacherService;
        //GetMapping,获取全部的教师列表
    
        //http://localhost:8001/eduservice/teacher/findAll
        @ApiOperation(value = "所有讲师列表")
        @GetMapping("findAll")
        public R findAllTeacher(){
            //调用service的list,查询条件为null(查到的所有都返回)
            List<EduTeacher> list=eduTeacherService.list(null);
    
            return R.ok().data("items",list);
        }
    
        //http://localhost:8001/eduservice/teacher/delete/1
    
        @ApiOperation(value = "逻辑删除讲师")
        @DeleteMapping("{id}")
        public R removeTeacher(@PathVariable String id){
            boolean b = eduTeacherService.removeById(id);
            if(b){
                return R.ok();
            }else {
                return R.error();
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    丝袜哥测试

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

    讲师分页功能

    配置mybatis的分页插件,在service_edu的config里

    @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            // 添加分页插件
            PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor();
            // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求。默认false
            pageInterceptor.setOverflow(false);
            // 单页分页条数限制,默认无限制
            pageInterceptor.setMaxLimit(500L);
            // 设置数据库类型
            pageInterceptor.setDbType(DbType.MYSQL);
    
            interceptor.addInnerInterceptor(pageInterceptor);
            return interceptor;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    添加新方法:

    //{current}/{limit}======当前页/最多限制页数
    @ApiOperation(value = "教师列表分页" )
    @GetMapping("pageTeacher/{current}/{limit}")
    public R pageListTeacher(@PathVariable long current ,@PathVariable long limit){
        //创建page对象
        Page<EduTeacher> eduTeacherPage=new Page<>(current,limit);
        //调用方法实现分页,会把得到的数据封装给eduTeacherPage,查询条件为null
        eduTeacherService.page(eduTeacherPage,null);
        //得到总记录数
        long total = eduTeacherPage.getTotal();
        //得到list数据集合
        List<EduTeacher> records = eduTeacherPage.getRecords();
        //返回的可以自己创建一个map集合,然后将两个对象合成一个对象,但是这里用的链式编程,两种结果都一样
        return R.ok().data("total",total).data("rows",records);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    丝袜哥测试

    返回总数量17,两个讲师数据

    在这里插入图片描述

    条件分页查询

    把条件封装成对象,再传递到接口,所以应该创建一个vo类,

    几大分层的定义

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

    DTO(Data Transfer Object)数据传输对象

    VO (view object/value object)表示层对象

    BO(bussines object)业务层对象//由PO继续包装成的对象

    PO(persistent object)持久对象

    DO(domain object)领域实体对象

    创建一个vo类

    在entity创建一个vo.TeacherQuery.java

    package com.lkw.eduservice.entity.vo;
    
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    @Data
    public class TeacherQuery {
    
        private static final long serialVersionUID = 1L;
    
        @ApiModelProperty(value = "教师名称,模糊查询")
        private String name;
    
        @ApiModelProperty(value = "头衔 1高级讲师 2首席讲师")
        private Integer level;
    
        @ApiModelProperty(value = "查询开始时间", example = "2019-01-01 10:10:10")
        private String begin;//注意,这里使用的是String类型,前端传过来的数据无需进行类型转换
    
        @ApiModelProperty(value = "查询结束时间", example = "2019-12-01 10:10:10")
        private String end;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    编写controller

    //4.条件查询分页方法
    @ApiOperation(value = "条件查询分页方法")
    @PostMapping("pageTeacherCondition/{current}/{limit}")
    public R pageTeacherCondition(@PathVariable Long current,
                                  @PathVariable Long limit,
                                  @RequestBody(required = false) TeacherQuery teacherQuery) {
        //创建page
        Page<EduTeacher> pageCondition = new Page<>(current, limit);
    
        //QueryWrapper,构建条件
        QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>();
        //多条件组合查询,动态sql
        String name = teacherQuery.getName();
        Integer level = teacherQuery.getLevel();
        String begin = teacherQuery.getBegin();
        String end = teacherQuery.getEnd();
        //判断条件是否为空,拼接条件
        if (!StringUtils.isEmpty(level)) {
            wrapper.eq("level", level);
        }
        if (!StringUtils.isEmpty(name)) {
            wrapper.like("name", name);
        }
        if (!StringUtils.isEmpty(begin)) {
            wrapper.ge("gmt_create", begin);//大于等于
        }
        if (!StringUtils.isEmpty(end)) {
            wrapper.le("gmt_create", end);//小于等于
        }
    
        wrapper.orderByDesc("gmt_create");
    
        //调用方法,实现分页查询
        eduTeacherService.page(pageCondition, wrapper);
    
        long total = pageCondition.getTotal();//获取总记录数
        List<EduTeacher> records = pageCondition.getRecords();//获取分页后的list集合
        HashMap<String, Object> map = new HashMap<>();
        map.put("total", total);
        map.put("rows", records);
        return R.ok().data(map);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    @RequestMapping,@RequestBody与@ResponseBody

    @RequestMapping:请求映射,

    用于映射(匹配?) url地址 与 类或方法,

    一般放在Controller类上

    @RequestBody:请求,

    使用json接收传输,转化封装成对应对象

    (后面的(required=false表示该值不是必须的,可以忽略))
    在这里插入图片描述

    @ResponseBody:响应,

    java对象转json直接写入到HTTP响应正文,

    一般放在Controller的方法上
    在这里插入图片描述

    丝袜哥测试

    单条件测试
    在这里插入图片描述

    符合的数据有3个,返回两条数据
    在这里插入图片描述

    全条件测试
    在这里插入图片描述
    在这里插入图片描述

    新增讲师

    在eduteacher类添加自动填充的注解,

    @TableField(fill= FieldFill.INSERT)
    private Date gmtCreate;
    
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建一个自动填充类
    在这里插入图片描述

    添加内容:

    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
    
        @Override
        public void insertFill(MetaObject metaObject) {
            //fieldName不是字段名(gmt_create),而是类的属性名(gmtCreate)
            this.setFieldValByName("gmtCreate", new Date(), metaObject);
            this.setFieldValByName("gmtModified", new Date(), metaObject);
        }
        @Override
        public void updateFill(MetaObject metaObject) {
            this.setFieldValByName("gmtModified", new Date(), metaObject);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    添加接口方法

    @ApiOperation("添加教师")
    @PostMapping("addTeacher")
    public R addTeacher(@RequestBody EduTeacher eduTeacher) {
        //可能缺一点数据判断
        boolean save = eduTeacherService.save(eduTeacher);
        if (save) {
            return R.ok();
        } else
            return R.error();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    根据id查询讲师,修改讲师

    @ApiOperation("根据ID查询教师")
    @GetMapping("getTeacher/{id}")
    public R getTeacher(@PathVariable String id) {
        EduTeacher eduTeacher = eduTeacherService.getById(id);
        return R.ok().data("teacher", eduTeacher);
    }
    
    @ApiOperation("修改教师")
    @PostMapping("updateTeacher")
    public R updateTeacher(@RequestBody EduTeacher eduTeacher) {
        boolean b = eduTeacherService.updateById(eduTeacher);
        if (b) {
            return R.ok();
        } else
            return R.error();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    丝袜哥测试

    根据id查询讲师
    在这里插入图片描述

    id写2,时间删掉,其他改改
    在这里插入图片描述

    如果一直500,检查一下eduTeacher类的属性和字段是不是匹配的

    异常处理

    创建两个类在service_base模块
    在这里插入图片描述

    package com.lkw.servicebase.exceptionhandler;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * 自定义异常类
     */
    @Data
    @AllArgsConstructor  //有参数构造器
    @NoArgsConstructor   //生成无参数构造
    public class GuliException extends RuntimeException {
        private Integer code;//状态码
        private String msg;//输出消息
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package com.lkw.servicebase.exceptionhandler;
    
    
    
    import com.lkw.commonutils.R;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Slf4j
    @ControllerAdvice
    public class GlobalExceptionHandler {
        
        //全局异常处理
        @ExceptionHandler(Exception.class)
        public R error(Exception e){
            e.printStackTrace();
            return R.error().message("执行全局异常处理");
        }
        
    
    
        //指定异常执行方法(算术异常)
        @ExceptionHandler(ArithmeticException.class)
        @ResponseBody//为了能够返回数据
        public R error(ArithmeticException e){
            e.printStackTrace();
            return R.error().message("方法执行ArithmeticException异常!");
        }
    
        //自定义的异常处理
        @ExceptionHandler(GuliException.class)
        @ResponseBody
        public R error(GuliException e){
            log.error(e.getMessage());
            e.printStackTrace();
            return R.error().code(e.getCode()).message(e.getMsg());
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    随便在一个controller里加int i=10/0;,来模拟算术异常

    再在随便一个方法里模拟一个自定义异常:

    /*
    //模拟的自定义异常
            try {
                int i=10/0;
            } catch (Exception e) {
                throw new GuliException(20001,"执行了自定义异常");
            }
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    丝袜哥测试

    全局异常处理:

    指定异常处理
    在这里插入图片描述

    自定义异常处理
    在这里插入图片描述

    初学用全局就行吧

    详细异常处理待补全

    统一日志处理

    日志级别

    高 低

    OFF,FATAL,ERROR,WARN,INFO,DEBUG,ALL

    在yml里配置当前的控制台的日志级别:

    logging:
      level:
        root: warn
    
    • 1
    • 2
    • 3

    默认是info级别

    Logback

    ,一个类似于log4j的东西

    配置时需要注释掉其他两个的日志配置
    在这里插入图片描述

    在resources下创建logback-spring.xml

    
    <configuration scan="true" scanPeriod="10 seconds">
        
        
        
        
    
        <contextName>logbackcontextName>
        
        <property name="log.path" value="D:/guli_log/edu"/>
    
        
        
        
        
        
        
        
        <property name="CONSOLE_LOG_PATTERN"
                  value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
    
    
        
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            
            
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>INFOlevel>
            filter>
            <encoder>
                <Pattern>${CONSOLE_LOG_PATTERN}Pattern>
                
                <charset>UTF-8charset>
            encoder>
        appender>
    
    
        
    
        
        <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            
            <file>${log.path}/log_info.logfile>
            
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
                <charset>UTF-8charset>
            encoder>
            
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                
                <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
                
                <maxHistory>15maxHistory>
            rollingPolicy>
            
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>INFOlevel>
                <onMatch>ACCEPTonMatch>
                <onMismatch>DENYonMismatch>
            filter>
        appender>
    
        
        <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            
            <file>${log.path}/log_warn.logfile>
            
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
                <charset>UTF-8charset> 
            encoder>
            
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.logfileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
                
                <maxHistory>15maxHistory>
            rollingPolicy>
            
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>warnlevel>
                <onMatch>ACCEPTonMatch>
                <onMismatch>DENYonMismatch>
            filter>
        appender>
    
    
        
        <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            
            <file>${log.path}/log_error.logfile>
            
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
                <charset>UTF-8charset> 
            encoder>
            
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.logfileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
                
                <maxHistory>15maxHistory>
            rollingPolicy>
            
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERRORlevel>
                <onMatch>ACCEPTonMatch>
                <onMismatch>DENYonMismatch>
            filter>
        appender>
    
        
        
        
        <springProfile name="dev">
            
            <logger name="com.guli" level="INFO"/>
    
            
            <root level="INFO">
                <appender-ref ref="CONSOLE"/>
                <appender-ref ref="INFO_FILE"/>
                <appender-ref ref="WARN_FILE"/>
                <appender-ref ref="ERROR_FILE"/>
            root>
        springProfile>
    
    
        
        <springProfile name="pro">
    
            <root level="INFO">
                <appender-ref ref="CONSOLE"/>
                <appender-ref ref="DEBUG_FILE"/>
                <appender-ref ref="INFO_FILE"/>
                <appender-ref ref="ERROR_FILE"/>
                <appender-ref ref="WARN_FILE"/>
            root>
        springProfile>
    
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164

    在第十行改日志路径

    启动测试

    有文件,有内容,搞定,

    红色是因为没有拉近git
    在这里插入图片描述

    将 异常 输出到文件

    在GlobalExceptionHandler类添加注解:@Slf4j

    补充上这个代码:
    在这里插入图片描述

    打上这个注解,用log.info()来代替System.out.println();更省性能(好像是自带多线程)

    启动测试

    添加到github

    详细看我的主页里有关git上传的博客

    创建远程仓库:
    在这里插入图片描述

    复制链接

    在这里插入图片描述

    输入链接

    在这里插入图片描述

    成功:

    也可以在下面这写好README
    在这里插入图片描述

  • 相关阅读:
    error /var/lib/jenkins/workspace/*/node_modules/node-sass: Command failed.
    记一次正式环境升级docker服务基础进行版本异常
    揭开ChatGPT面纱(3):使用OpenAI进行文本情感分析(embeddings接口)
    算法设计与分析 SCAU11079 可以移动的石子合并(优先做)
    C++文件 I/O操作
    Cadence OrCAD Capture 新放置的元件为问号无法自动编号解决方法
    19. 如何使用 ABAP 程序消费 SAP ABAP OData 服务
    代码随想录算法训练营 动态规划part08
    ESP32C3 LuatOS TM1650②动态显示累加整数
    微信小程序学习之五种页面跳转方法.
  • 原文地址:https://blog.csdn.net/m0_52070517/article/details/126668322