SpringBoot2 全局异常处理

Posted Archibald Witwicky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot2 全局异常处理相关的知识,希望对你有一定的参考价值。

参考这篇文章里面的几种异常形式:

全局异常处理是个比较重要的功能,一般在项目里都会用到。 
大概把一次请求分成三个阶段,来分别进行全局的异常处理。 
一:在进入Controller之前,譬如请求一个不存在的地址,404错误。 
二:在执行@RequestMapping时,进入逻辑处理阶段前。譬如传的参数类型错误。 
三:以上都正常时,在controller里执行逻辑代码时出的异常。譬如NullPointerException。 
http://blog.csdn.net/tianyaleixiaowu/article/details/70145251

 

直接将编写的全局异常处理类放入项目中,配置@Controller将类载入spring中即可使用,不需要任何配置。

以下是我写的异常处理类:

package com.archibladwitwicke.springboot2.chapter03.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Controller
public class GlobalErrorController extends AbstractErrorController {
    private static final String ERROR_PATH = "/error";
    private Log log = LogFactory.getLog(GlobalErrorController.class);

    @Autowired
    ObjectMapper objectMapper;

    public GlobalErrorController() {
        super(new DefaultErrorAttributes());
    }

    @RequestMapping(ERROR_PATH)
    public ModelAndView getErrorPath(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
                request, false));
        Throwable cause = getCause(request);
        int status = (Integer) model.get("status");
        //错误信息
        String message = (String) model.get("message");
        //友好提示
        String errorMessage = getErrorMessage(cause);

        String requestPath = (String) model.get("path");


        //后台打印日志信息方方便查错
        log.info(status + ":" + message, cause);
        log.info("requestPath---" + ":" + requestPath);

        //后台打印日志信息方方便查错
        log.info(message, cause);
        response.setStatus(status);
        if (!isJsonRequest(request, model)) {
            ModelAndView view = new ModelAndView("/error.btl");
            view.addAllObjects(model);
            view.addObject("status", status);
            view.addObject("errorMessage", errorMessage);
            view.addObject("cause", cause);
            return view;

        } else {
            Map<String, Object> error = new HashMap<>();
            error.put("success", false);
            error.put("errorMessage", getErrorMessage(cause));
            error.put("message", message);
            writeJson(response, error);
            return null;
        }


    }

    private boolean isJsonRequest(HttpServletRequest request, Map<String, Object> model) {
        // 修复bug,在此类中,使用request无法获取requestPath
        String requestPath = (String) model.get("path");
        if (requestPath.endsWith(".json")) {
            return true;
        } else {
            return (request.getHeader("accept").contains("application/json") || (request.getHeader("X-Requested-With") != null
                    && request.getHeader("X-Requested-With").contains("XMLHttpRequest")));
        }
    }

    private void writeJson(HttpServletResponse response, Map<?, ?> error) {
        response.setContentType("application/json;charset=utf-8");
        try {
            response.getWriter().write(objectMapper.writeValueAsString(error));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getErrorMessage(Throwable ex) {
        /*不给前端显示详细错误*/
        return "服务器错误,请联系管理员";
    }

    private Throwable getCause(HttpServletRequest request) {
        Throwable error = (Throwable) request.getAttribute("javax.servlet.error.exception");
        if (error != null) {
            while (error instanceof ServletException && error.getCause() != null) {
                error = ((ServletException) error).getCause();
            }
        }
        return error;
    }

    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }
}

  

可以根据项目具体修改这个方法,将判断ajax请求的种类进行完善,其余的部分可以不用修改:

private boolean isJsonRequest(HttpServletRequest request, Map<String, Object> model) {
        // 修复bug,在此类中,使用request无法获取requestPath
        String requestPath = (String) model.get("path");
        if (requestPath.endsWith(".json")) {
            return true;
        } else {
            return (request.getHeader("accept").contains("application/json") || (request.getHeader("X-Requested-With") != null
                    && request.getHeader("X-Requested-With").contains("XMLHttpRequest")));
        }
    }

  

此异常类可以对上述三种异常情况进行拦截处理,显示自定义的异常处理页面或异常处理数据。

 






以上是关于SpringBoot2 全局异常处理的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot2.0 基础案例(03):配置系统全局异常映射处理

SpringBoot2.3.12.RELEASE优雅的全局异常处理(模板一)

SpringBoot2.3.12.RELEASE优雅的全局异常处理(模板一)

springBoot2.x 全局捕获异常

Spring Boot 2 Webflux的全局异常处理

异常处理