springboot全局异常处理

基于springboot的全局异常处理

1 编写ResultBuilder类

package com.test.domi.common.system;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ErrorProperties.IncludeStacktrace;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.StringWriter;

public class ResultBuilder implements HandlerExceptionResolver,Ordered {

    private static final Logger LOGGER = LoggerFactory.getLogger(ResultBuilder.class);
    private static final String ERROR_NAME = "fp.error";
    private ErrorProperties errorProperties;

    public ErrorProperties getErrorProperties() {
        return errorProperties;
    }

    public void setErrorProperties(ErrorProperties errorProperties) {
        this.errorProperties = errorProperties;
    }

    public ResultBuilder(ServerProperties serverProperties){
        LOGGER.info("serverProperties:{}",serverProperties.getError());
        this.errorProperties = serverProperties.getError();
    }

    public ResultInfo getErrorInfo(HttpServletRequest request){
        return  this.getErrorInfo(request,this.getError(request));
    }

    public ResultInfo getErrorInfo(HttpServletRequest request,Throwable error){
          ResultInfo resultInfo = new ResultInfo();
          resultInfo.setCode(Integer.toString(this.getHttpStatus(request).value()));
          resultInfo.setMessage(this.getHttpStatus(request).getReasonPhrase());
          resultInfo.setData((Object)null);
          return resultInfo;
    }

    public Throwable getError(HttpServletRequest request){
        Throwable error = (Throwable)request.getAttribute("fp.error");
        if (error == null) {
            error = (Throwable)request.getAttribute("javax.servlet.error.exception");
        }

        if (error != null) {
            while (error instanceof ServletException && ((Throwable) error).getCause() != null) {
                error = ((Throwable) error).getCause();
            }
        } else {
            String message = (String)request.getAttribute("javax.servlet.error.message");
            if (StringUtils.isNotEmpty(message)) {
                HttpStatus status = this.getHttpStatus(request);
                message = "Unknown Exception With" + status.value() + " " + status.getReasonPhrase();
            }

            error = new Exception(message);
        }

        return (Throwable)error;
    }

    public HttpStatus getHttpStatus(HttpServletRequest request){
        Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
        try {
            return statusCode != null?HttpStatus.valueOf(statusCode.intValue()):HttpStatus.INTERNAL_SERVER_ERROR;
        } catch (Exception var4) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }

    public String getStackTraceInfo(Throwable error,boolean isPrintStackTrace){
        if (!isPrintStackTrace) {
            return "omitted";
        } else {
            try {
                StringWriter stackTrace = new StringWriter();
                Throwable var4 = null;
                String var5;
                try {
                    error.printStackTrace(new PrintWriter(stackTrace));
                    stackTrace.flush();
                    var5 = stackTrace.toString();
                } catch (Throwable var15) {
                    var4 = var15;
                    throw var15;
                } finally {
                    if (stackTrace != null) {
                        if (var4 != null) {
                            try {
                                stackTrace.close();
                            } catch (Throwable var14) {
                                var4.addSuppressed(var14);
                            }
                        } else {
                            stackTrace.close();
                        }
                    }
                }

                return var5;
            } catch (Exception var17) {
                var17.printStackTrace();
                return "print stack trace error";
            }
        }
    }

    public boolean isInCludeStackTrace(HttpServletRequest request){
        IncludeStacktrace includeStacktrace = this.errorProperties.getIncludeStacktrace();
        if (includeStacktrace == IncludeStacktrace.ALWAYS) {
            return true;
        } else if (includeStacktrace != includeStacktrace.ON_TRACE_PARAM) {
            return  false;
        }else {
            String parameter = request.getParameter("trace");
            return parameter != null && !"false".equals(parameter.toLowerCase());
        }
    }


    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        httpServletRequest.setAttribute("fp.error", e);
        return null;
    }
}

2 编写ExceptionConfig类(传入ServerProperties ,实例化ResultBuilder。springboot中ErrorProperties类定义了异常自动映射路径@Value("${error.path:/error}")private String path = "/error"

package com.test.domi.config;

import com.test.domi.common.system.ResultBuilder;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import javax.annotation.Resource;

@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ExceptionConfig {
    @Resource
    private ServerProperties serverProperties;
    @Bean
    public ResultBuilder resultBuilder(){
        return  new ResultBuilder(serverProperties);
    }
}

ErrorProperties:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.boot.autoconfigure.web;

import org.springframework.beans.factory.annotation.Value;

public class ErrorProperties {
    @Value("${error.path:/error}")
    private String path = "/error";
    private ErrorProperties.IncludeStacktrace includeStacktrace;

    public ErrorProperties() {
        this.includeStacktrace = ErrorProperties.IncludeStacktrace.NEVER;
    }

    public String getPath() {
        return this.path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public ErrorProperties.IncludeStacktrace getIncludeStacktrace() {
        return this.includeStacktrace;
    }

    public void setIncludeStacktrace(ErrorProperties.IncludeStacktrace includeStacktrace) {
        this.includeStacktrace = includeStacktrace;
    }

    public static enum IncludeStacktrace {
        NEVER,
        ALWAYS,
        ON_TRACE_PARAM;

        private IncludeStacktrace() {
        }
    }
}

3 定义全局 异常Controller接管所有抛出的异常

package com.test.domi.controller;

import com.test.domi.common.system.ResultBuilder;
import com.test.domi.common.system.ResultInfo;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;


@Controller
@RequestMapping("${error.path:/error}") //来自ErrorProperties设置的默认异常路径
public class GlobalErrorController implements ErrorController {

    private final static String DEFAULT_ERROR_VIEW = "/error";

    private final static  org.slf4j.Logger LOGGER = LoggerFactory.getLogger(GlobalErrorController.class);

    @Resource
    private ResultBuilder resultBuilder;

    /**
     * 针对404的场景
     * @return
     */
    @Override
    public String getErrorPath(){
        return  resultBuilder.getErrorProperties().getPath();
    }

    /**
     * 如果请求头返回的类型是text/html,则返回到错误信息页面
     * @param request
     * @return
     */
    @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
    @ResponseBody
    public ModelAndView errorHtml(HttpServletRequest request) {
        return new ModelAndView(DEFAULT_ERROR_VIEW,"errorInfo",resultBuilder.getErrorInfo(request));
    }

    /**
     * 除了text/html的请求头信息,其它都返回json格式
     * @param request 请求对象
     * @return 错误信息字符串 在ResultInfo中封装错误信息
     */
    @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public ResultInfo error(HttpServletRequest request){
        return resultBuilder.getErrorInfo(request);
    }
}

配置完毕,后台的未被捕获的异常将从dao层到dervice层到controller层,然后被全局异常controller统一接管,封装之后返回给前台!

猜你喜欢

转载自www.cnblogs.com/domi22/p/9098192.html