今天我们来看一下,异常的统一处理.分为三个步骤:
1.如何统一拦截
2.拦截什么样的异常
3.拦截后做什么
1.如何统一拦截
拦截的方式很多,我用的是ControllerAdvice,配合ExceptionHandler一起来拦截处理.
@Order(-1)
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(MyException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public Result webException(MyException e){
log.info("这里可以写你要处理异常的逻辑!");
if(log.isDebugEnabled()){
log.error(e.getMessage());
}
return new Result().setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage(e.getMessage());
}
@ExceptionHandler(AuthenticationException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public String unAuth(AuthenticationException e){
if(log.isDebugEnabled()){
log.error(e.getMessage());
}
return "/login";
}
}
2. 拦截什么样的异常
我们要拦截什么样的异常,可以到上面的ExceptionHandler(*Exception.class),这就是把所有抛出的异常统一拦截,你可以根据不同的异常定义多个.
public class MyException extends RuntimeException{
private int code;
private String message;
public MyException(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
3.拦截后做什么?
通常错误我们会记录在文件日志或数据库中,以便后期分析错误原因,本次我们把错误日志放在数据库中.
涉及以下几个类:
- 日志类型 LogType
- 日志工厂 LogFactory
LogType
public enum LogType {
LOGIN("登录日志"),
EXCEPTION("异常日志"),
BUSSINESS("业务日志");
String message;
LogType(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
LogFactory
public class LogFactory {
//操作日志
public static OperationLog createOperationLog(LogType logType, Integer userId, String bussinessName, String clazzName, String methodName, String msg, LogStatus succeed) {
OperationLog operationLog = new OperationLog();
operationLog.setLogtype(logType.getMessage());
operationLog.setLogname(bussinessName);
operationLog.setUserid(userId);
operationLog.setClassname(clazzName);
operationLog.setMethod(methodName);
operationLog.setCreatetime(new Date());
operationLog.setSucceed(succeed.getMessage());
operationLog.setMessage(msg);
return operationLog;
}
public static LoginLog createLoginLog(LogType logType, Integer userId, String msg, String device,String ip) {
LoginLog loginLog = new LoginLog();
loginLog.setLogname(logType.getMessage());
loginLog.setDevice(device);
loginLog.setUserid(userId);
loginLog.setCreatetime(new Date());
loginLog.setSucceed(LogStatus.SUCCESS.getMessage());
loginLog.setIp(ip);
loginLog.setMessage(msg);
return loginLog;
}
}
在系统开发中,日志不应当影响业务逻辑,所以我们把引入多线程定时任务ScheduleThreadPoolExecutor
-
LogManager
```
public class LogManager {private final int OPERATE_DELAY_TIME = 10;
private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
public static LogManager logManager = new LogManager();
public static LogManager me(){
return logManager;
}public void executeLog(TimerTask task){
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
}
``` -
LogTaskFactory
@Slf4j
public class LogTaskFactory {
//利用ApplicationContext获取mapper实例
private static LoginLogMapper loginLogMapper = Db.getMapper(LoginLogMapper.class);
private static OperationLogMapper operationLogMapper = Db.getMapper(OperationLogMapper.class);
public static TimerTask loginLog(final Integer userId,final String device, final String ip){
return new TimerTask() {
@Override
public void run() {
try {
LoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null,device, ip);
loginLogMapper.insert(loginLog);
}catch (Exception e){
log.error("登陆异常!");
}
}
};
}
//schedule线程的子任务
public static TimerTask bussinessLog(final Integer userId, final String bussinessName, final String clazzName, final String methodName, final String msg) {
return new TimerTask() {
@Override
public void run() {
OperationLog operationLog = LogFactory.createOperationLog(
LogType.BUSSINESS, userId, bussinessName, clazzName, methodName, msg, LogStatus.SUCCESS);
try {
operationLogMapper.insert(operationLog);
} catch (Exception e) {
log.error("创建业务日志异常!", e);
}
}
};
}
}
网友评论