博客
关于我
Java,SpringBoot,全局异常处理,容器、404异常全局统一处理
阅读量:738 次
发布时间:2019-03-21

本文共 5985 字,大约阅读时间需要 19 分钟。

全局异常处理是Spring Boot应用中非常重要的一部分,能够统一处理各种异常,提升应用的健壮性和用户体验。本文将详细介绍Spring Boot全局异常处理的配置与实现,包括代码设计和优化。

全局异常处理概述

在Spring Boot应用中,通过@ControllerAdvice注解和配置文件application.yml,可以实现全局异常处理的统一配置。这种方法能够处理@Controller@RestController以及容器级别的异常,提升应用的异常处理能力。

异常处理逻辑设计

首先,我们需要定义一个通用的运行时异常BusinessException。该类应携带错误代码和错误信息,便于在全局处理器中构造返回结果。

package com.what21.demo.common;
import lombok.Data;
@Data
public class BusinessException extends RuntimeException {
private Integer code;
private String message;
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(Integer code, String message) {
super(code + ":" + message);
this.code = code;
this.message = message;
}
}

接下来,创建封装返回结果的R类:

package com.what21.demo.common;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
@Getter
@Setter
@ToString
public class R
implements Serializable {
private static final long serialVersionUID = 1L;
public static final String OK = "SUCCESS";
public static final String ERROR = "ERROR";
@Getter
@Setter
private String code;
@Getter
@Setter
private String msg;
@Getter
@Setter
private T data;
public static
R
ok() {
return instance(OK, null, null);
}
public static
R
ok(T data) {
return instance(OK, null, data);
}
public static
R
ok(T data, String msg) { return instance(OK, msg, data); } public static
R
okMsg(String msg) { return instance(OK, msg, null); } public static
R
error() { return instance(ERROR, null, null); } public static
R
error(T data) { return instance(ERROR, null, data); } public static
R
error(T data, String msg) { return instance(ERROR, msg, data); } public static
R
errMsg(String msg) { return instance(ERROR, msg, null); } public static
R
instance(String code, String msg, T data) { R
result = new R<>(); result.setCode(code); result.setMsg(msg); result.setData(data); return result; } }

最后,配置全局异常处理器:

package com.what21.demo.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import java.util.List;
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = {BusinessException.class})
@ResponseBody
public R businessExceptionHandler(BusinessException e) {
log.debug("处理业务异常,代码:{},信息:{}", e.getCode(), e.getMessage());
return R.instance(e.getCode().toString(), e.getMessage(), null);
}
@ExceptionHandler(value = {Exception.class})
@ResponseBody
public R exceptionHandler(Exception e) {
if (e instanceof NoHandlerFoundException) {
return R.instance("1001", e.getMessage(), null);
} else if (e instanceof IllegalArgumentException) {
return R.instance("1001", e.getMessage(), null);
} else if (e instanceof IllegalStateException) {
return R.instance("1001", e.getMessage(), null);
} else if (e instanceof BindException) {
BindException ex = (BindException) e;
List
allErrors = ex.getAllErrors();
ObjectError error = allErrors.get(0);
return R.instance("1001", error.getDefaultMessage(), null);
} else if (e instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
List
errors = ex.getBindingResult().getAllErrors();
if (!errors.isEmpty()) {
org.springframework.web.bind.BinderResult error = errors.get(0);
return R.instance("1001", error.getDefaultMessage(), null);
}
}
return R.instance("1001", e.getMessage(), null);
}
}

配置文件application.yml

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

测试案例

创建一个测试控制器:

package com.what21.demo.controller;
import com.what21.demo.common.BusinessException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class EchoController {
@GetMapping("/")
public String index(Model model) {
model.addAttribute("index", "首页");
return "index";
}
@RequestMapping(path = "/echo", method = {RequestMethod.GET})
@ResponseBody
public String echo() {
if (true) {
throw new BusinessException(1002, "业务异常信息");
}
return "hello";
}
}

测试结果分析

通过上述配置,可以实现对以下场景的异常处理:

  • 业务异常:任何抛出的BusinessException都会被businessExceptionHandler捕获,并返回一个JSON格式的错误结果。

  • 未映射的URL异常:当URL未找到时,NoHandlerFoundException会导致返回一个格式化的404错误。

  • 参数验证异常@Valid注解和校验器 Butt师傅异常会被处理为标准化的错误信息。

  • 通过R.instance方法,可以根据不同场景构造特定的返回结果,实现JSON格式的错误处理。例如,R.instance(ERROR, "错误代码", "错误信息")将返回一个{error: "错误信息"}的JSON对象。

    性能优化与扩展

  • 减少重复代码:可以创建一个自定义的异常处理结果构建器,减少R.instance方法的重复调用。

  • 分区处理异常:根据异常类型分区处理,实现更细致的错误信息构建。

  • 日志记录:通过Slf4j或其他日志框架记录异常处理日志,方便定位问题。

  • 统一错误页面:可以通过редirect到一个统一的错误页面,提升用户体验。

  • 定制返回结果:根据需要扩展R类,添加更多的处理逻辑,使其适应不同业务需求。

  • 通过以上配置和实现,可以大大简化异常处理逻辑,使代码更加整洁高效,提升应用的稳定性和用户体验。

    转载地址:http://zhprz.baihongyu.com/

    你可能感兴趣的文章
    Vue3.0 性能提升主要是通过哪几方面体现的?
    查看>>
    NLP 项目:维基百科文章爬虫和分类【01】 - 语料库阅读器
    查看>>
    NLP_什么是统计语言模型_条件概率的链式法则_n元统计语言模型_马尔科夫链_数据稀疏(出现了词库中没有的词)_统计语言模型的平滑策略---人工智能工作笔记0035
    查看>>
    NLP三大特征抽取器:CNN、RNN与Transformer全面解析
    查看>>
    NLP学习笔记:使用 Python 进行NLTK
    查看>>
    NLP度量指标BELU真的完美么?
    查看>>
    NLP的不同研究领域和最新发展的概述
    查看>>
    NLP的神经网络训练的新模式
    查看>>
    NLP采用Bert进行简单文本情感分类
    查看>>
    NLP问答系统:使用 Deepset SQUAD 和 SQuAD v2 度量评估
    查看>>
    NLP项目:维基百科文章爬虫和分类【02】 - 语料库转换管道
    查看>>
    NLP:使用 SciKit Learn 的文本矢量化方法
    查看>>
    nmap 使用方法详细介绍
    查看>>
    Nmap扫描教程之Nmap基础知识
    查看>>
    nmap指纹识别要点以及又快又准之方法
    查看>>
    Nmap渗透测试指南之指纹识别与探测、伺机而动
    查看>>
    Nmap端口扫描工具Windows安装和命令大全(非常详细)零基础入门到精通,收藏这篇就够了
    查看>>
    NMAP网络扫描工具的安装与使用
    查看>>
    NMF(非负矩阵分解)
    查看>>
    nmon_x86_64_centos7工具如何使用
    查看>>