统一异常处理器
让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要统一异常处理。
统一异常处理的目的:在切面中处理异常、返回统一的异常结果对象
@ControllerAdvice注解:ControllerAdvice本质上是一个Component,aop,起到一个拦截作用。
Spring的@ExceptionHandler注解,可以用来统一处理方法抛出的异常。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public R error(Exception e){
e.printStackTrace();
return R.error();
}
}
当然也会有一些特定异常需要额外进行处理的。
处理特定异常
那么就可以在GlobalExceptionHandler这个类中添加一个处理方法。
在@ExceptionHandler中指定需要处理的特定异常。
@ExceptionHandler(BadSqlGrammarException.class)
@ResponseBody
public R error(BadSqlGrammarException e){
e.printStackTrace();
return R.setResult(ResultCodeEnum.BAD_SQL_GRAMMAR);
}
统一日志处理
通过日志可以查看程序的运行过程,运行信息,异常信息等
目的
- 将日志记录在文件中,方便运维和开发做错误排查
- 文件日志需要做滚动输出(输出到更多的日志文件中),避免单日志体积过大,拖垮服务器。
- 可以方便的在开发环境和生产环境中切换输出方式,例如在控制台和日志文件中灵活输出。
日志级别
分为FATAL、ERROR、WARN、INFO、DEBUG。
默认情况下,spring boot从控制台打印出来的日志级别只有INFO及以上级别,可以配置日志级别。
# 设置日志级别
logging:
level:
root: ERROR
这种方式能将ERROR级别以及以上级别的日志打印在控制台上。
Logback日志
Springboot内部使用Logback作为日志实现的框架。
配置logback日志
删除application.yml中的日志配置
安装idea彩色日志插件:grep console(高版本idea会自带)
resource中创建logback-spring.xml(这是默认日志文件的名字)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<property name="log.path" value="D:/project/edu/project" />
<!--控制台日志格式:彩色日志-->
<!-- 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)"/>
<!--文件日志格式-->
<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} |%-5level |%thread |%file:%line |%logger |%msg%n" />
<!--编码-->
<property name="ENCODING"
value="UTF-8" />
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!--日志级别-->
<level>DEBUG</level>
</filter>
<encoder>
<!--日志格式-->
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!--日志字符集-->
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!--输出到文件-->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志过滤器:此日志文件只记录INFO级别的-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</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>
</appender>
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志过滤器:此日志文件只记录WARN级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</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>
</appender>
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志过滤器:此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</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>
</appender>
<!--开发环境-->
<springProfile name="dev">
<!--可以灵活设置此处,从而控制日志的输出-->
<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="ERROR">
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
</configuration>
控制日志级别
通过在开发环境设置以下<root>节点的level属性的值,调节日志的级别。
<!--开发环境-->
<springProfile name="dev">
<!--可以灵活设置此处,从而控制日志的输出-->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
输出日志,需要在类上添加@Slf4j注解
@Slf4j
public class MyController {}
打印日志
public R listAll(){
log.info("info级别....................");
log.warn("warn级别....................");
}
错误日志处理
-
日志记录器记录错误日志
在GlobalExceptionHandler类上加注解@Slf4j,将异常输出语句改为。
//e.printStackTrace(); log.error(e.getMessage()); -
为了保证日志的对战信息能够被输出,修改异常输出语句。
引入工具类
import org.apache.commons.lang3.exception.ExceptionUtils;修改异常输出语句
//e.printStackTrace(); //log.error(e.getMessage()); log.error(ExceptionUtils.getStackTrace(e));