6.从零搭建WebApi接口开发框架-公共异常拦截

实际开发中,需要对各种异常进行处理,并记录日志,常见的异常包括以下几种:

  • 系统错误,最常见的,系统未处理的
  • 404,请求url不存在
  • 参数错误,请求的参数不符合校验规则

在springBoot中采用controllerAdvice来进行公共异常的拦截。先设置系统的日志,用于记录异常信息。

logback设置



    
    
        
            %d{yyyy-MM-dd HH:mm:ss} - %m%n
            
            UTF-8
        
    

    
    
        ${LOG_PATH}/sys.log
        true
        
            ${LOG_PATH}/%d{yyyyMMdd}/sys-%d{yyyyMMdd}.log
            
            365
        
        
            true
            utf-8
            [%d{yyyyMMdd HH:mm:ss}] - %m%n
        
    
    
        ${LOG_PATH}/dao.log
        true
        
            ${LOG_PATH}/%d{yyyyMMdd}/dao-%d{yyyyMMdd}.log
            
            365
        
        
            true
            utf-8
            [%d{yyyyMMdd HH:mm:ss}] [%-5level] [%-30logger{0}][%-3L]
                [SeqId:%X{SeqId}] - %m%n
            
        
    
    
        ${LOG_PATH}/service.log
        true
        
            ${LOG_PATH}/%d{yyyyMMdd}/service-%d{yyyyMMdd}.log
            
            365
        
        
            true
            utf-8
            [%d{yyyyMMdd HH:mm:ss}] - %m%n
        
    
    
        ${LOG_PATH}/controller.log
        true
        
            ${LOG_PATH}/%d{yyyyMMdd}/controller-%d{yyyyMMdd}.log
            
            365
        
        
            true
            utf-8
            [%d{yyyyMMdd HH:mm:ss}]- %m%n
        
    

    
        ${LOG_PATH}/operation.log
        true
        
            ${LOG_PATH}/%d{yyyyMMdd}/operation-%d{yyyyMMdd}.log
            
            365
        
        
            true
            utf-8
            %m%n
        
    
    
        ${LOG_PATH}/performance.log
        true
        
            ${LOG_PATH}/%d{yyyyMMdd}/performance-%d{yyyyMMdd}.log
            
            365
        
        
            true
            utf-8
            [%d{yyyyMMdd HH:mm:ss}] - %m%n
        
    
    
    
        
        
    
    
        
        
    
    
        
        
    
    
        
        
    
    
        
        
    
    
        
        
    

    
    
        
        
    
    

和正常的logback日志日志没有什么不同,把日志分为以下几类:

  • sys:记录工程启动和停止的日志
  • controller:记录controller层的异常
  • service:service层异常,主要是用AOP来记录
  • dao:dao层的异常,主要是用AOP来记录
  • performace:系统性能监测记录,也是用AOP来记录
  • operation:操作记录,主要记录接口请求记录

controllerAdvice

@ControllerAdvice
public class ApiControllerAdvice {
    /**
     * 定义日志处理
     */
    private static Logger logger = LoggerFactory.getLogger("controllerLog");

    /**
     * 系统异常处理,比如:404,500
     *
     * @param request  request
     * @param response response
     * @param e        异常
     * @return JsonResult结构
     * @throws Exception 异常
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public JsonResult defaultErrorHandler(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception {
        logger.error("系统异常", e);
        logException(request);
        if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return new JsonResult(false, GlobalReturnCode.SYSTEM_PATH_NOEXIST);
        } else {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return new JsonResult(false, GlobalReturnCode.SYSTEM_ERROR);
        }
    }

    /**
     * 取得header的所有属性
     *
     * @param headers 请求的headers
     * @param request request
     * @return 把header拼成字符串
     */
    private String getHeaderValue(Enumeration headers, HttpServletRequest request) {
        String str = "";
        while (headers.hasMoreElements()) {
            String header = headers.nextElement();
            str += header + "=" + request.getHeader(header) + "&";
        }
        return str;
    }

    /**
     * 打印所有异常信息
     *
     * @param request request
     */
    private void logException(HttpServletRequest request) {
        try {
            logger.error("请求路径:" + request.getServletPath());
            logger.error("请求参数:" + request.getParameterMap().toString());
            logger.error("请求header:" + getHeaderValue(request.getHeaderNames(), request));
            logger.error("请求body:" + StringUtil.getBodyString(request.getReader()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这里先记录404错误和500错误,如果接口请求有异常,直接返回对应的json串

404错误
为了使springBoot能拦截404错误,需要在application.yml中增加如下配置:

spring:
  mvc:
    throw-exception-if-no-handler-found: true
  resources:
    add-mappings: false

如果不加上面配置,404是无法获取拦截的。
如果没有配置异常拦截,直接请求springboot会返回如下错误:


6.从零搭建WebApi接口开发框架-公共异常拦截_第1张图片
404默认返回.png

配置后返回如下信息:


6.从零搭建WebApi接口开发框架-公共异常拦截_第2张图片
配置后返回.png

500错误

为了整体拦截系统异常,需要定制返回的500错误,避免返回异常给调用端。如下图所示:


6.从零搭建WebApi接口开发框架-公共异常拦截_第3张图片
系统异常.png

这里讲完了如何拦截404和500错误,下一节会讲解拦截参数非法错误。

源码下载

本例子详细源码

你可能感兴趣的:(6.从零搭建WebApi接口开发框架-公共异常拦截)