SpringBoot项目新增和修改讲师接口开发day2-3

一: 新增功能自动填充封装

在这里插入图片描述

1、 创建包service_base项目下com.atguigu.servicebase新建handler,创建自动填充类 MyMetaObjectHandler类:
package com.atguigu.servicebase.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 新增自定义的实现类
 */
@Slf4j //lombok 记录日志
@Component //组件扫描注入容器管理
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("================新增成功!===================");
        //传入的不是字段.属性名称
        this.setFieldValByName("gmtCreate",new Date(),metaObject);
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("================更新成功!===================");
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }
}
2、在实体类添加自动填充注解
package com.atguigu.eduservice.entity;

import com.baomidou.mybatisplus.annotation.*;
import java.util.Date;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 讲师实体类
 * </p>
 * @author testjava
 * @since 2020-09-14
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="EduTeacher对象", description="讲师")
public class EduTeacher implements Serializable {

   @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT) //插入填充字段
    private Date gmtCreate;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE) //插入和更新填充字段
    private Date gmtModified;

二: service_edu项目 Controller 定义方法

1: 新增:
    /**
     * ===========================添加讲师接口的方法==================================
     * RequestBody : 通过 json 传入数据并做封装到该方法中
     * ResponseBody: 返回 json 数据
     */
    @ApiOperation(value = "新增讲师的接口")
    @PostMapping("addTeacher")
    /**
     * 通过对象形式进行传递RequestBody
     */
    public R addTeacher(
                    @ApiParam(name = "eduTeacher",value = "添加讲师数据",required = false)
                    @RequestBody EduTeacher eduTeacher){ //传递 json 数据并封装到该对象中EduTeacher
        boolean save = teacherService.save(eduTeacher);
        //如果说 boolean 类型返回是 true那么返回数据成功
        if(save){
            return R.success();
            //如果说它是false 那么返回失败传递
        } else {
            return R.error();
        }
    }
}
2: 添加成功
3、根据讲师 id 修改查询
 	/**
     * ===========================根据讲师 id 修改查询==================================
     * RequestBody : 通过 json 传入数据并做封装到该方法中
     * ResponseBody: 返回 json 数据
     */
    @ApiOperation(value = "根据 id 修改查询")
    @GetMapping("getTeacher/{id}")
    public R getTeacher(
            @ApiParam(name = "id",value = "讲师 ID",required = true)
            @PathVariable String id){
        EduTeacher eduTeacher = teacherService.getById(id);
        return R.success().data("teacher",eduTeacher);
    }

在这里插入图片描述

4: 讲师修改功能

在这里插入图片描述

	/**
     * ===========================讲师修改功能==================================
     * RequestBody : 通过 json 传入数据并做封装到该方法中
     * ResponseBody: 返回 json 数据
     */
    @ApiOperation(value = "修改讲师的数据")
    @PostMapping("updateTeacher")
    public R updateTeacher(
            @ApiParam(name = "eduTeacher",value = "修改讲师数据",required = true)
            @RequestBody EduTeacher eduTeacher){
        //调用teacherService的updateById根据对象修改数据
        boolean update = teacherService.updateById(eduTeacher);

        //判断 如果修改为 true 那么数据修改成功
        if (update) {
            return R.success();
            //如果失败那么 false
        } else {
            return R.error();
        }
    }
}

三、什么是统一异常处理

1、制造异常
 /**
     * ===========================分页查询讲师的方法==================================
     * 分页查询讲师的方法
     * current 代表当前页
     * limit 每页显示的记录数
     */
    @ApiOperation(value = "分页查询讲师列表")
    @GetMapping("pageTeacher/{current}/{limit}") //get提交
    public R pageListTeacher(
                            @ApiParam(name = "current",value = "当前页数",required = true)
                            @PathVariable long current,
                            @ApiParam(name = "limit",value = "每页记录数",required = true)
                            @PathVariable long limit ){
        //创建 page 对象
        Page<EduTeacher> pageTeacher = new Page<>(current,limit);

        int i = 10/0; //手动添加异常

        //调用方法实现分页
        //调用方法时候.底层做了封装.把分页所有的数据封装到pageTeacher对象里面
        teacherService.page(pageTeacher,null);

        long total = pageTeacher.getTotal(); //记录总页数
        //getRecords 返回的 list 集合
        List<EduTeacher> records = pageTeacher.getRecords(); //数据list 集合

        //返回的每页总数
        //返回每页的 list 的数据
        return R.success().data("total",total).data("rows:", records);
    }

在这里插入图片描述

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

四: 统一异常处理

在这里插入图片描述

1、创建统一异常处理器
  • 在service-base中创建统一异常处理类GlobalExceptionHandler.java:
package com.atguigu.servicebase.exceptionhandler;

import com.atguigu.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)//说明所有异常都会执行
    @ResponseBody //为了会返回 json 数据
    public R error(Exception e){
        log.info("=====================统一异常处理类执行成功!=====================");
        e.printStackTrace();
        return R.error().message("执行了全局异常处理....");
    }
}
测试

在这里插入图片描述

2: 全局异常处理机制
package com.atguigu.servicebase.exceptionhandler;

import com.atguigu.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)//说明所有异常都会执行
    @ResponseBody //为了会返回 json 数据
    public R error(Exception e){
        log.info("=====================统一异常处理类执行成功!=====================");
        e.printStackTrace();
        return R.error().message("执行了全局异常处理....");
    }
3: 特定异常处理机制

在这里插入图片描述

    //指定特定异常
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody //返回json 数据
    public R error(ArithmeticException e){
        log.info("=====================指定特定异常成功!=====================");
        e.printStackTrace();
        return R.error().message("执行了特定算术异常处理....");
    }
4: 自定义异常处理机制

在这里插入图片描述

  • 自定义异常需手动在 service_base 公共配置 com.atguigu.servicebase包exceptionhandler下添加自定义的异常类 HeartException 自定义起名: 然后继承RuntimeException超类实现里面的方法
package com.atguigu.servicebase.exceptionhandler;

/**
 * 类 描 述:TODD
 * 项目名称:guli_parent
 * 类 名 称:HeartException
 * 创建时间:2020/9/16 6:13 PM
 * 创 建 人:huanghao
 *
 * @version: V2.2
 */

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 自定义的异常类
 */
@Data
@AllArgsConstructor  //生成一个全参数的构造函数
@NoArgsConstructor   //生成一个无参数的构造函数
public class HeartException extends RuntimeException {

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

    @ApiModelProperty(value = "异常信息")
    private String msg;
}

  • 然后控制器层 捕获 自定义异常
     //try catch 去捕获当前自定义的异常类
        try{
            int i = 10/0;
        }catch (Exception e){
            //执行自定义异常类
            throw new HeartException(20001,"执行了自定义异常处理....");
        }
  • 启动main方法 进行测试

五: 日志

在这里插入图片描述

1、配置日志级别
  • 日志记录器(Logger)的行为是分等级的。如下表所示:
  • 分为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
  • 默认情况下,spring boot从控制台打印出来的日志级别只有INFO及以上级别,可以配置日志级别
//application.properties 配置该信息
# 设置日志级别
logging.level.root=WARN   WARN INFO ERROR DEBUG

# Mybatis_plus 配置日志打印
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
  • 这种方式只能将日志打印在控制台上

六: Logback日志

1、配置logback日志
  • 删除application.properties中的日志配置
  • resources 中创建 logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="10 seconds">
    <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
    <!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
    <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
    <!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->

    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="/Users/huanghao/GitHub_git/guli_parent/edu" />
    <!-- 彩色日志 -->
    <!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
    <!-- magenta:洋红 -->
    <!-- boldMagenta:粗红-->
    <!-- cyan:青色 -->
    <!-- white:白色 -->
    <!-- magenta:洋红 -->
    <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">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!--输出到文件-->
    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_info.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 WARN 日志 -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_warn.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_error.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender><logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              如果未设置此属性,那么当前logger将会继承上级的级别。
    -->
    <!--
        使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
        第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
        第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:
     -->
    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <!--可以输出项目中的debug日志,包括mybatis的sql日志-->
        <logger name="com.guli" level="INFO" />
        <!--
            root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
            level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
            可以包含零个或多个appender元素。
        -->
        <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>
2、将错误日志输出到文件
  • GlobalExceptionHandler.java 中 类上添加注解
/**
 * 统一异常处理类
 */
@Slf4j //记录日志
@ControllerAdvice //注解定义全局异常处理类
public class GlobalExceptionHandler {
  • 异常输出语句
   //指定出现什么异常执这个方法
    @ExceptionHandler(Exception.class)//说明所有异常都会执行
    @ResponseBody //为了会返回 json 数据
    public R error(Exception e){
        log.info("=====================统一异常处理类执行成功!=====================");
		log.error(e.getMessage()); //打印到 logback 生成的文件中
        e.printStackTrace();
        return R.error().message("执行了全局异常处理....");
    }

3、将日志堆栈信息输出到文件

在这里插入图片描述

  • 输出到文件中的 error 信息

2020-09-16 21:28:27.911 [http-nio-8001-exec-8] ERROR c.a.s.exceptionhandler.GlobalExceptionHandler - 执行了自定义异常处理…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
it讲师创业-在线教育经验分享实战视频课程是一门旨在帮助有意创业的IT讲师们成功在在线教育领域开展业务的课程。在线教育是一个蓬勃发展的行业,而作为IT讲师,通过在线教育平台开设自己的课程是一个有吸引力的创业选择。然而,成功创业涉及到很多方面的知识和技能,而这门课程就提供了这些必要的经验分享和实战指导。 该课程的内容包括以下几个方面。首先,它会介绍在线教育市场的趋势和机会,让学员了解当前市场的竞争格局和机遇。其次,课程会教授如何选择适合自己的在线教育平台,并提供使用不同平台的实操指导。此外,课程还会介绍如何设计优质的课程内容,包括教学方法、教材准备和评估等方面的技巧。 另外,该课程也会分享一些成功创业者的故事和经验,学员可以从中汲取灵感和启发。此外,还会提供一些市场推广和品牌建设的实用技巧,帮助学员在推广自己的课程时更具竞争力。 通过这门课程,IT讲师们可以获取到在线教育领域创业所需的核心知识和实践经验。他们将学会如何选择合适的平台、设计优质的课程、推广自己的品牌,并充分利用市场机遇来实现成功创业。无论是想要全职从事在线教育还是作为兼职企业,该课程将为IT讲师们提供宝贵的帮助和指导,使他们能够更加自信和成功地进入这个快速发展的行业。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值