美文网首页
spring boot下的统一异常处理

spring boot下的统一异常处理

作者: 金融非耐斯 | 来源:发表于2020-05-13 16:58 被阅读0次

今天我们来看一下,异常的统一处理.分为三个步骤:
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);
                }
            }
        };
    }
}

相关文章

网友评论

      本文标题:spring boot下的统一异常处理

      本文链接:https://www.haomeiwen.com/subject/qgqpnhtx.html