全局异常处理解决方案

背景:

在项目开发中,习惯去设计一些自定义的异常类来处理各层的异常。比如:

  1. DAO层会有对应的DAOException.java
  2. Service层有对应的ServiceException.java
  3. Controller层有对应的ControllerException.java

当程序遇到不可忽视的错误时,会直接throw出这些异常,这就意味着需要一种全局异常处理机制来对这些异常进行统一管理(比如:返回给用户一个错误页面)
本文仅介绍了两种统一处理异常的方式:基于servlet的过滤器基于Spring的@ExceptionHandler方式


未处理服务器异常:
在这里插入图片描述


处理异常后:
在这里插入图片描述


自定义异常类:

  1. BaseException.java——所有自定义异常的父类
package com.nys.exceptions;

import com.nys.enums.ResultEnum;

/**
 * 基础异常类
 * @author nysheng
 */
public class BaseException extends RuntimeException {
    private Integer code=0;
    public BaseException(String msg) {
        super(msg);
    }
    public BaseException(Integer code,String msg){
        super(msg);
        this.code=code;
    }
    public BaseException(ResultEnum resultEnum){
        super(resultEnum.getMsg());
        this.code=resultEnum.getCode();
    }
    public Integer getCode(){
        return code;
    }
}
  1. DAOException.java——具体异常类
package com.nys.exceptions;

import com.nys.enums.ResultEnum;

/**
 * DAO层异常统一
 * @author nysheng
 */
public class DAOException extends BaseException {
    public DAOException(String msg) {
        super(msg);
    }
    public DAOException(Integer code,String msg){
        super(code,msg);
    }
    public DAOException(ResultEnum resultEnum){
        super(resultEnum.getCode(),resultEnum.getMsg());
    }
}

一、过滤器实现全局异常处理

这里采用的是注解@WebFilter方式添加的过滤器,并以Slf4j+Logback的方式进行日志记录。

package com.nys.filter;

import com.nys.bean.ApplicationConfig;
import com.nys.exceptions.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 全局异常拦截处理
 * @author nysheng
 */
@WebFilter("/*")
public class ExceptionFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse resp=(HttpServletResponse)servletResponse;
        HttpServletRequest req=(HttpServletRequest) servletRequest;
        try{
            filterChain.doFilter(req, resp);
        }catch (RuntimeException e){
            Logger logger = LoggerFactory.getLogger(ExceptionFilter.class);
            //判断是否为自定义异常
            Integer errorCode=0;
            if(e instanceof DAOException){
                //DAO层异常
                errorCode=1000;
            }else if(e instanceof ServiceException){
                //业务层异常
                errorCode=2000;
            }else if(e instanceof ControllerException){
                //控制层异常
                errorCode=3000;
            }
            logger.error("服务器出现异常,错误码:{},错误信息:{}",errorCode,e.getMessage());
            resp.sendRedirect(ApplicationConfig.REMOTE_REQUEST_ADDR+"/html/fail.html");
        }

    }
    @Override
    public void destroy() {}
}

二、Spring异常处理方式Handler

@ControllerAdvice+@ExceptionHandler,同样以Slf4j+Logback记录日志

package com.nys.exceptionshandler;

import com.nys.bean.ApplicationConfig;
import com.nys.exceptions.BaseException;
import com.nys.exceptions.DAOException;
import com.nys.exceptions.ServiceException;
import com.nys.exceptions.ServletException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

/**
 * 全局异常处理
 * @author nysheng
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler({DAOException.class,ServiceException.class, ServletException.class})
    public ModelAndView serviceExceptionHandler(BaseException e){
        Logger logger=LoggerFactory.getLogger(GlobalExceptionHandler.class);
        logger.error("服务器出现异常,错误码:{},错误信息:{}",e.getCode(),e.getMessage());
        return new ModelAndView("redirect:".concat(ApplicationConfig.REMOTE_REQUEST_ADDR).concat("/html/fail.html"));
    }
}

测试Controller:

@GetMapping("/test")
    public void test(){
        throw new DAOException(1,"Dao异常");
    }

日志:
在这里插入图片描述
在这里插入图片描述





版权声明:本文为qq_40780805原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。