SpringBoot2 全局异常处理

Stella981
• 阅读 393

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

全局异常处理是个比较重要的功能,一般在项目里都会用到。 
大概把一次请求分成三个阶段,来分别进行全局的异常处理。 
一:在进入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")));
        }
    }

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

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Spring Boot 2.x(七):全局异常处理
前言异常的处理在我们的日常开发中是一个绕不过去的坎,在SpringBoot项目中如何优雅的去处理异常,正是我们这一节课需要研究的方向。异常的分类在一个SpringBoot项目中,我们可以把异常分为两种,第一种是请求到达Controller层之前,第二种是到达Controller层之后项目代码中发生的错误。而第一种又可
Wesley13 Wesley13
2年前
03.Android崩溃Crash库之ExceptionHandler分析
目录总结00.异常处理几个常用api01.UncaughtExceptionHandler02.Java线程处理异常分析03.Android中线程处理异常分析04.为何使用setDefaultUncaughtExceptionHandler前沿上一篇整体介绍了crash崩溃
Stella981 Stella981
2年前
Spring Boot @ControllerAdvice+@ExceptionHandler处理controller异常
需求:  1.springboot 项目restful 风格统一放回json  2.不在controller写trycatch代码块简洁controller层  3.对异常做统一处理,同时处理@Validated校验器注解的异常方法:  @ControllerAdvice注解定义全局异常处理类@ControllerAdvice
Wesley13 Wesley13
2年前
初探 Objective
作者:Cyandev,iOS和MacOS开发者,目前就职于字节跳动0x00前言异常处理是许多高级语言都具有的特性,它可以直接中断当前函数并将控制权转交给能够处理异常的函数。不同语言在异常处理的实现上各不相同,本文主要来分析一下ObjectiveC和C这两个语言。为什么要把ObjectiveC和
Stella981 Stella981
2年前
Spring Boot 与 Kotlin Web应用的统一异常处理
做Web应用,请求处理过程中发生错误是非常常见的。SpringBoot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容。选择一个之前实现过的Web应用(chapter1151)为基础,启动该应用,访问一个不存在的URL,或是修改处理内容,直接抛出异常,如:
Stella981 Stella981
2年前
SpringBoot2 学习10 Controller接收参数的方式
地址传值@PathVariable获取路径参数。即url/{id}这种形式。?传值@RequestParam获取查询参数。即url?name这种形式用注解@RequestParam绑定请求参数到方法入参当请求参数username不存在时会有异常发生,可以通过设置属性requiredfalse解决,例如:@R
Easter79 Easter79
2年前
SpringBoot2 学习10 Controller接收参数的方式
地址传值@PathVariable获取路径参数。即url/{id}这种形式。?传值@RequestParam获取查询参数。即url?name这种形式用注解@RequestParam绑定请求参数到方法入参当请求参数username不存在时会有异常发生,可以通过设置属性requiredfalse解决,例如:@R
Easter79 Easter79
2年前
SpringBoot2 全局异常处理
参考这篇文章里面的几种异常形式:全局异常处理是个比较重要的功能,一般在项目里都会用到。 大概把一次请求分成三个阶段,来分别进行全局的异常处理。 一:在进入Controller之前,譬如请求一个不存在的地址,404错误。 二:在执行@RequestMapping时,进入逻辑处理阶段前。譬如传的参数类型错误。