前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Sprinboot中使用AOP实现异常处理

Sprinboot中使用AOP实现异常处理

作者头像
用户1483438
修改于 2021-11-16 13:19:12
修改于 2021-11-16 13:19:12
1.5K00
代码可运行
举报
文章被收录于专栏:大数据共享大数据共享
运行总次数:0
代码可运行

一、异常处理的乱象例举

乱象一:捕获异常后只输出到控制台

前端js-ajax代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$.ajax({
    type: "GET",
    url: "/user/add",
    dataType: "json",
    success: function(data){
        alert("添加成功");
    }
});

后端业务代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try {
    // do something
} catch (XyyyyException e) {
    e.printStackTrace();
}

问题:

  1. 后端直接将异常捕获,而且只做了日志打印。用户体验非常差,一旦后台出错,用户没有任何感知,页面无状态,。
  2. 如果没有人去经常关注日志,不会有人发现系统出现异常

乱象二:混乱的返回方式

前端代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$.ajax({
    type: "GET",
    url: "/goods/add",
    dataType: "json",
    success: function(data) {
        if (data.flag) {
            alert("添加成功");
        } else {
            alert(data.message);
        }
    },
    error: function(data){
        alert("添加失败");
    }
});

后端代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RequestMapping("/goods/add")
@ResponseBody
public Map add(Goods goods) {
    Map map = new HashMap();
    try {
        // do something
        map.put(flag, true);
    } catch (Exception e) {
        e.printStackTrace();
        map.put("flag", false);
        map.put("message", e.getMessage());
    }
    reutrn map;
}

问题:

  1. 每个人返回的数据有每个人自己的规范,你叫flag他叫isOK,你的成功code是0,它的成功code是0000。这样导致后端书写了大量的异常返回逻辑代码,前端也随之每一个请求一套异常处理逻辑。很多重复代码。
  2. 如果是前端后端一个人开发还勉强能用,如果前后端分离,就是系统灾难。

参考:juejin.im/post/5c3ea9…

二、该如何设计异常处理

面向相关方友好

  1. 后端开发人员职责单一,只需要将异常捕获并转换为自定义异常一直对外抛出。不需要去想页面跳转404,以及异常响应的数据结构的设计。
  2. 面向前端人员友好,后端返回给前端的数据应该有统一的数据结构,统一的规范。不能一个人一个响应的数据结构。而在此过程中不需要后端开发人员做更多的工作,交给全局异常处理器去处理“异常”到“响应数据结构”的转换。
  3. 面向用户友好,用户能够清楚的知道异常产生的原因。这就要求自定义异常,全局统一处理,ajax接口请求响应统一的异常数据结构,页面模板请求统一跳转到404页面。
  4. 面向运维友好,将异常信息合理规范的持久化,以便查询。

为什么要将系统运行时异常捕获,转换为自定义异常抛出? 答:因为用户不认识 ConnectionTimeOutException类似这种异常是什么东西,但是转换为自定义异常就要求程序员对运行时异常进行一个翻译,比如:自定义异常里面应该有message字段,后端程序员应该明确的在message字段里面用面向用户的友好语言,说明发生了什么。

三、开发规范

  1. Controller、Service、DAO层拦截异常转换为自定义异常,不允许将异常私自截留。必须对外抛出。
  2. 统一数据响应代码,使用httpstatusode,不要自定义。自定义不方便记忆。200请求成功,400用户输入错误导致的异常,500系统内部异常,999未知异常。
  3. 自定义异常里面有message属性,一定用友好的语言描述异常,并赋值给message.
  4. 不允许对父类Excetion统一catch,要分小类catch,这样能够清楚地将异常转换为自定义异常传递给前端。

四、页面类异常处理

我们做页面模板时,Controller发生异常我们该怎么办?应该统一跳转到404页面。

面临的问题:程序员抛出自定义异常CustomException,全局异常处理截获之后返回@ResponseBody AjaxResponse,不是ModelAndView,所以我们无法跳转到error.html页面,那我们该如何做页面的全局的异常处理? 答:

  1. 用面向切面的方式,将CustomException转换为ModelAndViewException。
  2. 全局异常处理器拦截ModelAndViewException,返回ModelAndView,即error.html页面
  3. 切入点是带@ModelView注解的Controller层方法

使用这种方法处理页面类异常,程序员只需要在页面跳转的Controller上加@ModelView注解即可

错误的写法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@GetMapping("/freemarker")
public String index(Model model) {
    try{
        List<ArticleVO> articles = articleRestService.getAll();
        model.addAttribute("articles", articles);
    }catch (Exception e){
        return "error";
    }
    return "fremarkertemp";
}

正确的写法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@ModelView
@GetMapping("/freemarker")
public String index(Model model) {
    List<ArticleVO> articles = articleRestService.getAll();
    model.addAttribute("articles", articles);
    return "fremarkertemp";
}

五、用面向切面的方法处理页面全局异常

因为用到了面向切面编程,所以引入maven依赖包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

新定义一个异常类ModelViewException

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ModelViewException extends RuntimeException{

    //异常错误编码
    private int code ;
    //异常信息
    private String message;

    public static ModelViewException transfer(CustomException e) {
        return new ModelViewException(e.getCode(),e.getMessage());
    }

    private ModelViewException(int code, String message){
        this.code = code;
        this.message = message;
    }

    int getCode() {
        return code;
    }

    @Override
    public String getMessage() {
        return message;
    }

}

ModelView 注解,只起到标注的作用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})//只能在方法上使用此注解
public @interface ModelView {

}

以@ModelView注解为切入点,面向切面编程,将CustomException转换为ModelViewException抛出。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Aspect
@Component
@Slf4j
public class ModelViewAspect {

    //设置切入点:这里直接拦截被@ModelView注解的方法
    @Pointcut("@annotation(club.krislin.exception.ModelView)")
    public void pointcut() { }

    /**
     * 当有ModelView的注解的方法抛出异常的时候,做如下的处理
     */
    @AfterThrowing(pointcut="pointcut()",throwing="e")
    public void afterThrowable(Throwable e) {
        log.error("切面发生了异常:", e);
        if(e instanceof  CustomException){
            throw ModelViewException.transfer((CustomException) e);
        }
    }
}

全局异常处理器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@ExceptionHandler(ModelViewException.class)
    public ModelAndView viewExceptionHandler(HttpServletRequest req, ModelViewException e) {
        ModelAndView modelAndView = new ModelAndView();

        //将异常信息设置如modelAndView
        modelAndView.addObject("exception", e);
        modelAndView.addObject("url", req.getRequestURL());
        modelAndView.setViewName("error");

        //返回ModelAndView
        return modelAndView;
    }

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
蚁群算法(ACO)最短路径规划(MATLAB)
蚁群算法最早是由Marco Dorigo等人在1991年提出,他们在研究新型算法的过程中,发现蚁群在寻找食物时,通过分泌一种称为信息素的生物激素交流觅食信息从而能快速的找到目标,据此提出了基于信息正反馈原理的蚁群算法。
里克贝斯
2021/05/21
2.6K0
蚁群算法(ACO)最短路径规划(MATLAB)
基于蚁群算法的机械臂打孔路径规划
问题描述   该问题来源于参加某知名外企的校招面试。根据面试官描述,一块木板有数百个小孔(坐标已知),现在需要通过机械臂在木板上钻孔,要求对打孔路径进行规划,力求使打孔总路径最短,这对于提高机械臂打孔的生产效能、降低生产成本具有重要的意义。 数学模型建立 问题分析   机械臂打孔生产效能主要取决于以下三个方面: 单个孔的钻孔作业时间,这是由生产工艺所决定的,不在优化范围内,本文假定对于同一孔型钻孔的作业时间是相同的。 打孔机在加工作业时,钻头的行进时间。 针对不同孔型加工作业时间,刀具的转换时间。   在机
waylon
2018/03/08
1.7K0
基于蚁群算法的机械臂打孔路径规划
蚁群算法(ACO)旅行商问题(TSP)路径规划MATLAB实现
蚁群算法(ant colony optimization)最早是由Marco Dorigo等人在1991年提出,他们在研究新型算法的过程中,发现蚁群在寻找食物时,通过分泌一种称为信息素的生物激素交流觅食信息从而能快速的找到目标,据此提出了基于信息正反馈原理的蚁群算法。
里克贝斯
2021/05/21
2.4K0
蚁群算法(ACO)旅行商问题(TSP)路径规划MATLAB实现
10分钟搞懂蚁群算法
蚂蚁几乎没有视力,但他们却能够在黑暗的世界中找到食物,而且能够找到一条从洞穴到食物的最短路径。它们是如何做到的呢? 蚂蚁寻找食物的过程 单只蚂蚁的行为及其简单,行为数量在10种以内,但成千上万只蚂蚁组成的蚁群却能拥有巨大的智慧,这离不开它们信息传递的方式——信息素。 蚂蚁在行走过程中会释放一种称为“信息素”的物质,用来标识自己的行走路径。在寻找食物的过程中,根据信息素的浓度选择行走的方向,并最终到达食物所在的地方。 信息素会随着时间的推移而逐渐挥发。 在一开始的时候,由于地面上没有信息素,因此蚂蚁们的行走
大闲人柴毛毛
2018/03/29
8.6K7
10分钟搞懂蚁群算法
菜鸟的数学建模之路(一):最短路径算法「建议收藏」
最短路径算法主要有两种,Dijkstra算法和floyd算法,当时在学习这两种算法时经常弄混了,关于这两种算法,记得当时是在交警平台设置的那一道题目上了解到的,就去查很多资料,花了不少时间才基本了解了这两种算法的基本用法,在总结的时候,我更多的是用代码的方式去做的总结,当时想的是等到要用的时候,直接改一下数据,运行代码,得到想要的最短路径就可以了。记得我们老师说过数学建模的知识没必要过于深入的去学习,只要在要用的时候,能想起有这个知识存在,知道大概是用来干嘛,并且能拿过来用就行了(大概就是这个意思)。
全栈程序员站长
2022/09/05
9170
数学建模----单源最短路径模型建立和求解
就是在Matlab里面,我们经常使用%作为标记,一个百分号就是普通的注释,两个百分号就是表示的对于这个编辑器的文本分割,把这个代码分割成为不同的部分,这个其实是有快捷键的,但是我之前尝试过,不是很好记,我觉得这个输入两个百分号之后,使用这个enter之后就可以自动实现这个区域的划分,还是很方便的;
阑梦清川
2025/02/24
880
数学建模----单源最短路径模型建立和求解
干货 | 十分钟快速搞懂什么是蚁群算法(Ant Colony Algorithm, ACA)(附代码)
     小编接下来这套 素质三连 攻略三连 会帮你十分钟快速搞定蚁群算法是什么、怎么用、注意啥,从零开始突破次元壁!!!
短短的路走走停停
2019/07/17
5.5K0
干货 | 十分钟快速搞懂什么是蚁群算法(Ant Colony Algorithm, ACA)(附代码)
干货|蚁群算法求解带时间窗的车辆路径规划问题详解(附Java代码)
当然,玩耍过后也不能忘记学习。本着~造福人类~的心态,小编又开始干活,为大家带来 有 · 趣 的干货算法内容了!
短短的路走走停停
2020/02/25
2.1K0
蚁群算法详解
如何寻找一条合适的路径,几乎是一个永恒的话题。每个人、每天都会遇到。大到全国列车的运行规划,小到每个人的手机导航。其中一部分是关于“如何寻找两个位置间的最短距离”的,这一部分有较为成熟的理论与确切的解法,还有与之匹配的各种算法。
智能算法
2020/09/24
6.9K0
蚁群算法详解
数学建模--图论与最短路径
在数学建模中,图论及其算法在解决最短路径问题上具有重要应用。图论是研究图及其性质的学科,而图中的节点和边代表了现实世界中的各种元素及其相互关系。
用户11315985
2024/10/16
1830
BS1036-基于java+路径规划+CS架构实现的A星算法求解最短路径问题演示程序
本基于java+路径规划+CS架构实现的A星算法求解最短路径问题演示程序,系统采用多层C/S软件架构,采用java 编程语言开发技术实现A*算法求解地图中的最短路径问题,实时获取计算用户在地图中设置的障碍点信息,计算可以完成路径规划的最短路径,提供完分析最短路径长度,重置地图,查看程序运行报告等功能,并且在程序运行界面提供完善的规则说明等。
计算机程序优异哥
2022/12/05
6140
【C++】BFS解决边权唯一的最短路径问题
很明显,实际情况的道路更加复杂,两个地点之间的距离不能全是1,所以边权为1的最短路问题是比较特殊,简单的最短路问题
啊QQQQQ
2024/11/19
1510
【C++】BFS解决边权唯一的最短路径问题
最短路径(Floyd算法,弗洛伊德算法,多源最短路径)
算法思想:一开始各顶点之间的最短路径,就是邻接矩阵值,每一次加入一个顶点,然后判断该顶点加入后,其余起点通过该顶点到达其余顶点能否得到比之前更短的最短路径,如果找到了就进行最短路径和权值和的更新
大忽悠爱学习
2021/04/01
2.3K0
最短路径(Floyd算法,弗洛伊德算法,多源最短路径)
数学建模暑期集训22:图论最短路径问题——Dijkstra算法和Floyd算法
Dijkstra是图论中经典的算法,可以计算图中一点到其它任意一点的最短路径。 学过数据结构的应该都接触过,因此具体的演示这里不再赘述。 完整的演示可以参看 图论最短距离(Shortest Path)算法动画演示-Dijkstra(迪杰斯特拉)和Floyd(弗洛伊德) 算法的缺点:不能处理带负权重的图。
zstar
2022/06/14
7090
数学建模暑期集训22:图论最短路径问题——Dijkstra算法和Floyd算法
【BFS最短路问题】迷宫中离入口最近的出口
​ 给你一个 m x n 的迷宫矩阵 maze (下标从 0 开始),矩阵中有空格子(用 '.' 表示)和墙(用 '+' 表示)。同时给你迷宫的入口 entrance ,用 entrance = [entrancerow, entrancecol] 表示你一开始所在格子的行和列。
利刃大大
2025/03/03
1150
【BFS最短路问题】迷宫中离入口最近的出口
路径规划算法
随着机器人技术、智能控制技术、硬件传感器的发展,机器人在工业生产、军事国防以及日常生活等领域得到了广泛的应用。而作为机器人行业的重要研究领域之一,移动机器人行业近年来也到了迅速的发展。移动机器人中的路径规划便是重要的研究方向。移动机器人的路径规划方法主要分为传统的路径规划算法、基于采样的路径规划算法、智能仿生算法。传统的路径规划算法主要有A*算法、Dijkstra算法、D*算法、人工势场法,基于采样的路径规划算法有PRM算法、RRT算法,智能仿生路径规划算法有神经网络算法、蚁群算法、遗传算法等。
六四零
2021/11/12
2.3K0
【算法】动态规划 ⑥ ( 骑士的最短路径 II | 问题分析 | 代码示例 )
在 国际象棋 中 , 骑士 类似 与 象棋 中的 马 , 走 " 日 " 字 格子 ;
韩曙亮
2023/03/30
6390
【算法】动态规划 ⑥ ( 骑士的最短路径 II | 问题分析 | 代码示例 )
干货|十分钟快速get蚁群算法(附代码)
之前分享了TSP的动态规划解法,本期来介绍它的另一种解法——蚁群算法。 什么?不知道?次元壁?高大上? 小编接下来这套 素质三连 攻略三连 会帮你十分钟快速搞定蚁群算法是什么、怎么用、注意啥,从零开始突破次元壁!!! * 内容提要: *什么是蚁群算法 *蚁群算法演练 *算法补充笔记 什么是蚁群算法? 蚁群系统(Ant System(AS)或Ant Colony System(ACS))是由意大利学者Dorigo、Maniezzo等人于20世纪90年代首先提出来的。他们在研究蚂蚁觅
用户1621951
2018/04/19
25.7K1
干货|十分钟快速get蚁群算法(附代码)
我是怎么使用最短路径算法解决动态联动问题的
本文介绍了如何利用联动配置实现多模块之间的解耦,以及如何使用配置项来控制模块的行为,达到模块间相互独立的目的。同时,文章还介绍了一种简化版的联动配置方法,通过将配置项以json格式存储在模块配置文件中,实现快速配置。
用户1168362
2018/01/05
1.7K0
我是怎么使用最短路径算法解决动态联动问题的
列文伯格算法_最短路径matlab程序
  本篇文章到这里就结束了,欢迎大家继续阅读本系列文章的后续文章,本文介绍的内容的完整代码的MATLAB文件我会放到附件里,听说在上传的时候设为粉丝可下载是不需要花费积分的,大家看一下需不需要积分,若还是需要积分,在评论区留言,我直接传给你
全栈程序员站长
2022/11/08
9360
列文伯格算法_最短路径matlab程序
推荐阅读
相关推荐
蚁群算法(ACO)最短路径规划(MATLAB)
更多 >
LV.1
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验