后台框架-统一异常管理

2024-09-02 00:52

本文主要是介绍后台框架-统一异常管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

搭建后台框架全局异常管理是一个很重要的部分,好在SpringBoot提供了很好的处理方法

使用@ControllerAdvice

@ControllerAdvice是Spring MVC中的一个全局异常处理注解,它允许在一个地方集中处理所有控制器抛出的异常。通过使用@ControllerAdvice,可以避免在每个控制器中重复编写异常处理逻辑,从而使代码更加简洁和易于维护。

基本用法

要使用@ControllerAdvice,创建一个类,并在该类上添加@ControllerAdvice注解。然后,在该类中定义多个@ExceptionHandler方法,每个方法处理一种特定的异常类型。

示例代码

package org.example.web.web;import org.example.web.model.R;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice
public class GlobalExceptionHandler {/*** 处理全局异常* @param e* @return*/@ExceptionHandler(value = Exception.class)@ResponseBodypublic Object exceptionHandler(Exception e){// 运行时异常if(e instanceof RuntimeException){RuntimeException ex = (RuntimeException) e;return R.error(500, ex.getMessage());}return R.error(999, e.getMessage());}
}

继承BasicErrorController

BasicErrorController是Spring Boot中用于处理错误页面的默认控制器。当应用程序发生错误时,Spring Boot会自动调用BasicErrorController来处理错误,并返回相应的错误页面。

基本用法

BasicErrorController处理两个主要点:
/error:处理所有类型的错误。
/error/{code}:处理特定HTTP状态码的错误。
默认情况下,BasicErrorController会返回一个简单的HTML错误页面,显示错误的状态码和消息。你可以通过自定义BasicErrorController来改变这种行为。

示例代码

package org.example.web.web;import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.example.web.model.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;@Slf4j
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class CustomErrorController extends BasicErrorController {@Value("${server.error.path:${error.path:/error}}")private String path;public CustomErrorController(ServerProperties serverProperties) {super(new DefaultErrorAttributes(), serverProperties.getError());}/*** 覆盖默认的JSON响应*/@Overridepublic ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {HttpStatus status = getStatus(request);Map<String, Object> map = new HashMap<>(16);Map<String, Object> originalMsgMap = getErrorAttributes(request, ErrorAttributeOptions.defaults());String path = (String) originalMsgMap.get("path");String error = (String) originalMsgMap.get("error");String message = (String) originalMsgMap.get("message");StringJoiner joiner = new StringJoiner(",", "[", "]");joiner.add(path).add(error).add(message);map.put("code", status.value());map.put("message", joiner.toString());return new ResponseEntity<Map<String, Object>>(map, status);}/*** 覆盖默认的HTML响应*/@Overridepublic ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {// 请求的状态HttpStatus status = getStatus(request);response.setStatus(getStatus(request).value());Map<String, Object> model = getErrorAttributes(request, ErrorAttributeOptions.defaults());ModelAndView modelAndView = resolveErrorView(request, response, status, model);// 指定自定义的视图log.error("{} - {} - {}", request.getRequestURI(), status.value(), JSON.toJSONString(model));if (status.value() == 404) {return (modelAndView == null ? new ModelAndView("err/404", model) : modelAndView);} else if (status.value() == 500) {return (modelAndView == null ? new ModelAndView("err/500", model) : modelAndView);} else {return (modelAndView == null ? new ModelAndView("err/other", model) : modelAndView);}}
}

静态错误页面

/src/main/resources/templates/err/404.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh">
<head><title th:text="${'ERROR - ' + status}"></title><meta charset="UTF-8"/><meta name="viewport" content="width:device-width,initial-scale=1" /><meta http-equiv="X-UA-Compatible" content="IE=Edge" /><link th:href="@{/css/style.css}" rel="stylesheet" />
</head>
<body>ERROR-<span th:text="${status}"></span>-<span th:text="${error}"></span>
</body>
</html>

/src/main/resources/templates/err/500.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh">
<head><title th:text="${'ERROR - ' + status}"></title><meta charset="UTF-8"/><meta name="viewport" content="width:device-width,initial-scale=1" /><meta http-equiv="X-UA-Compatible" content="IE=Edge" /><link th:href="@{/css/style.css}" rel="stylesheet" />
</head>
<body>ERROR-<span th:text="${status}"></span>-<span th:text="${error}"></span>
</body>
</html>

ResultResponseAdvice

package org.example.web.web;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.web.model.R;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import java.util.Map;/*** 对controller 层中 ResponseBody 注解方法,进行增强拦截*/
@ControllerAdvice
public class ResultResponseAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {// 返回true表示对所有Controller的返回值进行处理return true;}/*** 如果开启,就会对返回结果进行处理*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {// 设置响应类型为jsonresponse.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);if (body instanceof R) {// 如果body返回的是ResultMsg类型的对象,不进行增强处理response.setStatusCode(HttpStatus.valueOf(((R<?>) body).getCode()));return body;}if (body instanceof String) {// 如果body返回的是String类型的对象,单独处理return toJson(body);}if (body instanceof Map) {Map<String, Object> map = (Map<String, Object>) body;if (map.containsKey("code") && map.containsKey("message")) {int code = Integer.parseInt(map.get("code").toString());response.setStatusCode(HttpStatus.valueOf(code));if (code == 200) {return R.ok(map.get("message").toString());} else {return R.error((int)map.get("code"), map.get("message").toString());}} else {return R.ok(map);}}return R.ok(body);}private Object toJson(Object body) {try {return new ObjectMapper().writeValueAsString(R.ok(body));} catch (JsonProcessingException e) {throw new RuntimeException("无法转发json格式", e);}}
}

最后效果

访问一个不存在的页面时:
在这里插入图片描述
访问一个不存在的接口时:
在这里插入图片描述
访问一个抛错误的接口时:

    @RequestMapping("/test")@ResponseBodypublic User test() {throw new RuntimeException("User not found");}

在这里插入图片描述

源代码

访问后台框架-统一异常处理源码

这篇关于后台框架-统一异常管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128536

相关文章

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服

SpringBoot使用minio进行文件管理的流程步骤

《SpringBoot使用minio进行文件管理的流程步骤》MinIO是一个高性能的对象存储系统,兼容AmazonS3API,该软件设计用于处理非结构化数据,如图片、视频、日志文件以及备份数据等,本文... 目录一、拉取minio镜像二、创建配置文件和上传文件的目录三、启动容器四、浏览器登录 minio五、

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景

IDEA中的Kafka管理神器详解

《IDEA中的Kafka管理神器详解》这款基于IDEA插件实现的Kafka管理工具,能够在本地IDE环境中直接运行,简化了设置流程,为开发者提供了更加紧密集成、高效且直观的Kafka操作体验... 目录免安装:IDEA中的Kafka管理神器!简介安装必要的插件创建 Kafka 连接第一步:创建连接第二步:选

Spring中Bean有关NullPointerException异常的原因分析

《Spring中Bean有关NullPointerException异常的原因分析》在Spring中使用@Autowired注解注入的bean不能在静态上下文中访问,否则会导致NullPointerE... 目录Spring中Bean有关NullPointerException异常的原因问题描述解决方案总结

MyBatis框架实现一个简单的数据查询操作

《MyBatis框架实现一个简单的数据查询操作》本文介绍了MyBatis框架下进行数据查询操作的详细步骤,括创建实体类、编写SQL标签、配置Mapper、开启驼峰命名映射以及执行SQL语句等,感兴趣的... 基于在前面几章我们已经学习了对MyBATis进行环境配置,并利用SqlSessionFactory核

Python中的异步:async 和 await以及操作中的事件循环、回调和异常

《Python中的异步:async和await以及操作中的事件循环、回调和异常》在现代编程中,异步操作在处理I/O密集型任务时,可以显著提高程序的性能和响应速度,Python提供了asyn... 目录引言什么是异步操作?python 中的异步编程基础async 和 await 关键字asyncio 模块理论

详解Python中通用工具类与异常处理

《详解Python中通用工具类与异常处理》在Python开发中,编写可重用的工具类和通用的异常处理机制是提高代码质量和开发效率的关键,本文将介绍如何将特定的异常类改写为更通用的ValidationEx... 目录1. 通用异常类:ValidationException2. 通用工具类:Utils3. 示例文

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关