一、全局异常处理
springboot默认异常会映射到.error进行异常处理,但提示不友好,下面自定义异常处理类,提供友好展示。
1.自定义异常类
在common_util模块com.zhengyibao.yygh.common.exception包下添加YyghException异常类
package com.zhengyibao.yygh.common.exception;
import com.zhengyibao.yygh.common.result.ResultCodeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author wenmiao
* @create 2021-09-29 8:37
* @explain 自定义全局异常类YyghException
*/
@Data //lombok,提供code的get,set等方法
@ApiModel("自定义全局异常类")
public class YyghException extends RuntimeException{ //RuntimeException运行时异常
@ApiModelProperty(value = "异常状态码")
private Integer code;
//通过 code状态码 和 message错误消息 创建异常对象
public YyghException(String message,Integer code){
super(message);
this.code=code;
}
//接收枚举类型对象resultCodeEnum
public YyghException(ResultCodeEnum resultCodeEnum){
super(resultCodeEnum.getMessage());
this.code=resultCodeEnum.getCode();
}
@Override
public String toString(){
return "YyghException{" +
"code="+code+
",message="+this.getMessage()+
"}";
}
}
2.添加全局异常处理类
在common_util模块com.zhengyibao.yygh.common.exception包下添加GlobalExceptionHandler异常类
package com.zhengyibao.yygh.common.exception;
import com.zhengyibao.yygh.common.result.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author wenmiao
* @create 2021-09-29 8:29
* @explain 全局异常处理类
*/
@ControllerAdvice //增强controller,有三个功能:1.全局异常处理 2.全局数据绑定 3.全局数据预处理
public class GlobalExceptionHandler {
//全局统一Exception异常处理
@ExceptionHandler(Exception.class) //设置什么类型异常执行(异常类型)
@ResponseBody //让数据用json格式执行
public Result error(Exception e){
e.printStackTrace();
return Result.fail();
}
//自定义YyghException异常处理
@ExceptionHandler(YyghException.class)
@ResponseBody
public Result yyghError(YyghException yyghException){
return Result.fail();
}
}
3.测试全局异常类
模拟自定义异常,不是系统异常,需要使用throw new手动抛出
# service_hosp模块com.zhengyibao.yygh.hosp.controller包下的HospitalSetController表现层类
//6.查,根据id获取医院设置
@ApiOperation(value = "根据id获取医院设置")
@GetMapping("getHospitalSetById/{id}")
public Result getHospitalSetById(@PathVariable long id){
//模拟自定义异常,不是系统异常,需要使用throw new YyghException手动抛出
try {
int i=1/0;
}catch (Exception e){
throw new YyghException("失败",201);
}
HospitalSet list=hospitalSetService.getById(id);
return Result.ok(list);
}
二、全局日志处理
1.配置控制台日志级别
日志记录器(Logger)的行为的分等级的:OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
默认,springboot从控制台打印出来的日志级别只有INFO及以上级别,越往右包含信息越多
在service_util的resources/application.properties添加以下配置
# 设置日志级别为DEBUG,默认为INFO,错误信息只能在控制台中进行删除
logging.level.root=DEBUG
级别 | 含义 |
---|---|
OFF | 全部日志关闭 |
FATAL | 致命错误信息 |
ERROR | 错误信息 |
WARN | 警告信息 |
INFO | 基本信息(springboot默认) |
DEBUG | 所有调试信息(包括INFO,WARN和ERROR) |
ALL | 全部日志关闭 |
2.logback日志框架
springboot内部使用logback作为日志框架,与log4j相似
在service_util的resources建立logback-spring.xml文件(固定文件名)
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 日志级别从低到高:TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出-->
<!-- scan=true ,配置文件若发送改变,会被重新加载, 默认为true-->
<!-- scanPeriod:监测配置文件是否有修改的时间间隔,当scan=true时才会生效, 默认单位为毫秒,默认时间间隔为 1分钟-->
<!-- debug=true,打印出logback内部日志信息,实时查看logback的运行状态, 默认值为false-->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<!-- name值是变量名称,value值是变量定义的值,通过定义的值会被插入到logger上下文中,定义变量后,可以使用"${}"来使用变量-->
<property name="log.path" value="E:/IDEA/yygh_log/edu"/>
<!-- 彩色日志,CONSOLE_LOG_PATHERN配置格式变量,magenta:洋红,boldMagenta:粗红,cyan:青色,white:白色-->
<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)"/>
<!--logback.xml文件中<appender>和<logger>的顺序:<appender>应该在<logger>的前面-->
<!-- 输出到控制台-->
<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>
<!--此日志文件只记录ERROR级别的-->
<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会继承上级的级别-->
<!--生产环境:打印到控制台-->
<!--dev是在application.properties中配置的-->
<springProfile name="dev">
<!--可以输出项目中的debug日志,包括mybatis的sql日志-->
<logger name="com.zhengyibao" 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="ERROR_FILE"/>
<appender-ref ref="WARN_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>