Java 异常处理、日志
一、异常
1.Throwable
Java异常类型的顶层父类,Throwable又派生出Error类和Exception类
Error(错误)
NoClassDefFoundError: 找不到 class 定义异常。
StackOverflowError: 深递归导致栈被耗尽而抛出的异常。
OutOfMemoryError: 内存溢出异常。
Exception
运行时异常(RuntimeException):
NullPropagation:空指针异常
ClassCastException:类型强制转换异常
IllegalArgumentException:传递非法参数异常
IndexOutOfBoundsException:下标越界异常
NumberFormatException:数字格式异常
非运行时异常:
ClassNotFoundException:找不到指定 class 的异常
IOException:IO 操作异常
2.异常处理
try{
/**
* try块中主要放置可能会产生异常的代码块。try块里的代码出现异常,系统生成一个异常对象提交给运行环境,此过程为抛出(throw)异常。
* Java环境收到异常对象时,会寻找合适的catch块,如果找不到,java运行环境就会终止,java程序将退出。
*/
}catch(SQLException SQLexception){
/** 每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。
* catch块中放置当出现相应的异常类型时,程序需要执行的代码。当try中语句可能发生多个异常的时候可以由多个catch。
*/
}catch(Exception exception){
//...
}finally{
/** finally块通常是可选的。
* 无论异常是否发生,异常是否匹配被处理,finally都会执行。
* finally中存放一定会执行的代码,异常机制保证finally代码总是会被执行。
* 当遇到try或catch中return或throw之类可以终止当前方法的代码时,jvm会先去执行finally中的语句,finally中的语句执行完毕后才会返回来执行try/catch中的return,throw语句。
* 如果finally中有return或throw,那么将执行这些语句,不会在执行try/catch中的return或throw语句。
* 只有System.exit()方法让finally块不执行
* finally块中一般写的是关闭资源之类的代码。
*/
}
Exception的方法: toString(): 返回异常发生时的简要描述. getMessage(): 返回该异常的详细描述. printStackTrace(): 将该异常的跟踪栈信息输出到标准错误输出(异常链). printStackTrace(PrintStream s): 将该异常的跟踪栈信息输出到指定的输出流. getStackTrace(): 返回该异常的跟踪栈信息.
3.throws 、throw
throws:声明异常
public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN{
//foo内部可以抛出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 类的异常,或者他们的子类的异常对象。
}
throw:手动抛出具体的异常对象
throw new Exception;
二、全局异常处理
1.引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.3</version>
</dependency>
2.代码
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @author JunSouth
* @desc 全局异常处理类
*/
@RestControllerAdvice
public class JunGlobalExceptionHandler {
/**
* 全局处理 Exception 类型的异常。
*/
@ExceptionHandler(Exception.class)
public String processException(Exception e){
System.out.println("进入全局处理Exception方法");
System.out.println(getExceptionLocation(e));
e.printStackTrace();
System.out.println("结束全局处理Exception方法");
return "参数非法";
}
/**
* 全局处理 NullPointerException 类型的异常。
*/
@ExceptionHandler(NullPointerException.class)
public void processNullPointerException(NullPointerException e){
System.out.println("进入全局处理NullPointerException方法");
System.out.println(getExceptionLocation(e));
e.printStackTrace();
System.out.println("结束全局处理NullPointerException方法");
}
/**
* 全局处理 IllegalArgumentException 类型的异常。
*/
@ExceptionHandler(IllegalArgumentException.class)
public void processIllegalArgumentException(IllegalArgumentException e){
System.out.println("进入全局处理IllegalArgumentException方法");
System.out.println(getExceptionLocation(e));
e.printStackTrace();
System.out.println("结束全局处理IllegalArgumentException方法");
}
/**
* 全局处理 RuntimeException 类型的异常。
*/
@ExceptionHandler(RuntimeException.class)
public String processRuntimeException(RuntimeException e){
System.out.println("进入全局处理RuntimeException方法");
System.out.println(getExceptionLocation(e));
e.printStackTrace();
System.out.println("结束全局处理RuntimeException方法");
return "参数非法";
}
/**
* 获取异常发生的位置, 可用于打印日志。
*/
private String getExceptionLocation(Exception e){
StackTraceElement[] stackTrace = e.getStackTrace();
StackTraceElement stack = stackTrace[0];
String string = "%s.%s#%s.%s";
String format = String.format(string, stack.getClassName(), stack.getMethodName(), stack.getFileName(),
stack.getLineNumber());
return format;
}
}
三、log4j2 日志
日志级别 FATAL > ERROR > WARN > INFO > DEBUG > TRACE
引入依赖:
<!-- 排除 SpringBoot自带logging -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 log4j2 jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>3.0.3</version>
</dependency>
<!-- Lombok情况下使用日志框架 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
配置门面:log4j2.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- <configuration status="OFF" packages="com.xyebank.hzx.core.log4j2"> -->
<configuration status="OFF">
<properties>
<!-- 当前日志文件路径 -->
<property name="fileSavePath" value="/home/logs/sweep/sweep(${hostName}).log"/>
<property name="errorFileSavePath" value="/home/logs/sweep/sweep(${hostName})-error.log"/>
<!-- 历史日志文件路径 -->
<property name="fileBackSavePath" value="/home/backlogs/sweep"/>
<!-- 日志级别 -->
<property name="logLevel" value="debug"/>
<property name="layoutPattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS}---[%-5level]---[%-32X{traceId}]---[%-16.16thread]---[%c{64}] : %msg%n"/>
</properties>
<!-- 日志主配置 -->
<appenders>
<!-- 控制台 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- <SensitiveDataPatternLayout pattern="${layoutPattern}" /> -->
<PatternLayout pattern="${layoutPattern}"/>
</Console>
<!-- 文件 -->
<RollingRandomAccessFile name="RollingRandomAccessFile" fileName="${fileSavePath}"
filePattern="${fileBackSavePath}-%d{yyyy-MM-dd}.%i.log.zip">
<!-- <SensitiveDataPatternLayout pattern="${layoutPattern}" /> -->
<PatternLayout pattern="${layoutPattern}"/>
<Policies>
<SizeBasedTriggeringPolicy size="200MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingRandomAccessFile>
<!-- 错误日志 -->
<RollingRandomAccessFile name="ERROR" fileName="${errorFileSavePath}"
filePattern="${fileBackSavePath}-error-%d{yyyy-MM-dd}.%i.log.zip">
<!-- <SensitiveDataPatternLayout pattern="${layoutPattern}" /> -->
<PatternLayout pattern="${layoutPattern}"/>
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<Policies>
<SizeBasedTriggeringPolicy size="200MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingRandomAccessFile>
</appenders>
<!--过滤掉部分组件的其余错误信息-->
<loggers>
<!-- <AsyncLogger name="org.apache.zookeeper" level="error" additivity="false">-->
<!-- <appender-ref ref="RollingRandomAccessFile" />-->
<!-- <appender-ref ref="ERROR" />-->
<!-- <appender-ref ref="Console" />-->
<!-- </AsyncLogger>-->
<!-- <AsyncLogger name="com.alibaba.dubbo" level="error" additivity="false">-->
<!-- <appender-ref ref="RollingRandomAccessFile" />-->
<!-- <appender-ref ref="ERROR" />-->
<!-- <appender-ref ref="Console" />-->
<!-- </AsyncLogger>-->
<!-- <AsyncLogger name="org.I0Itec.zkclient" level="error" additivity="false">-->
<!-- <appender-ref ref="RollingRandomAccessFile" />-->
<!-- <appender-ref ref="ERROR" />-->
<!-- <appender-ref ref="Console" />-->
<!-- </AsyncLogger>-->
<!-- <AsyncLogger name="org.mongodb.driver.cluster" level="error" additivity="false">-->
<!-- <appender-ref ref="RollingRandomAccessFile" />-->
<!-- <appender-ref ref="ERROR" />-->
<!-- <appender-ref ref="Console" />-->
<!-- </AsyncLogger>-->
<!-- <AsyncRoot level="${logLevel}">-->
<!-- <appender-ref ref="RollingRandomAccessFile" />-->
<!-- <appender-ref ref="ERROR" />-->
<!-- <appender-ref ref="Console" />-->
<!-- </AsyncRoot>-->
<Root level="${logLevel}">
<appender-ref ref="RollingRandomAccessFile"/>
<appender-ref ref="ERROR"/>
<appender-ref ref="Console"/>
</Root>
</loggers>
</configuration>
代码:
private Logger log = LoggerFactory.getLogger(Test01.class);
public String testLog(String msg) {
log.info("这是info信息:{}", msg);
log.debug("这是debug信息:{}", msg);
log.warn("这是warn信息:{}", msg);
log.error("这是error信息:{}", msg);
return "success";
}