Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
重学SpringBoot系列之统一全局异常处理
答:因为用户不认识ConnectionTimeOutException类似这种异常是什么东西,但是转换为自定义异常就要求程序员对运行时异常进行一个翻译,比如:自定义异常里面应该有message字段,后端程序员应该明确的在message字段里面用面向用户的友好语言,说明服务端发生了什么。
大忽悠爱学习
2021/12/07
1.1K0
重学SpringBoot系列之统一全局异常处理
Spring Boot统一异常处理
先定义接口返回数据结构,code为0表示操作成功,非0表示异常。其中data只有在处理成功才会返回,其他情况不会返回,或者那些不需要返回数据的接口(更新、删除…)
用户7353950
2022/06/23
5140
Spring Boot统一异常处理
springboot全局异常处理
腾云先锋(TDP,Tencent Cloud Developer Pioneer)是腾讯云GTS官方组建并运营的技术开发者群体。这里有最专业的开发者&客户,能与产品人员亲密接触,专有的问题&需求反馈渠道,有一群志同道合的兄弟姐妹。来加入属于我们开发者的社群吧!
无敌小菜鸟
2022/02/20
1K0
springboot全局异常处理
快速学习-SpringMVC 中的异常处理
系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
cwl_java
2020/04/08
4320
SSM项目全局异常处理器开发
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
sunonzj
2022/06/21
3930
SSM项目全局异常处理器开发
Spring MVC统一异常处理 - `@ExceptionHandler`
在Web应用程序中,错误和异常是不可避免的。Spring MVC框架提供了@ExceptionHandler注解,用于捕获和处理控制器中抛出的异常。通过统一异常处理,可以有效地对应用程序中的异常进行管理和处理,提高用户体验和代码的可维护性。本文将深入探讨@ExceptionHandler的用法和原理,并结合实际项目场景,介绍如何在Spring MVC应用中实现统一异常处理的最佳实践。
王也518
2023/12/20
1.8K0
SpringBoot Web篇(一)
参考默认的视图解析器org.springframework.boot.autoconfigure.web.servlet.error.DefaultErrorViewResolver源码,取出部分代码片段如下:
Johnson木木
2019/11/13
5610
spring Aop实现身份验证和springboot异常统一处理
一般,如果用户没有登录的话,用户只可以查看商品,但是其他的,比如支付等是不能够进行操作的,这个时候,我们就需要用到用户拦截, 或者说身份验证了。
好好学java
2018/11/23
2.1K0
springmvc异常处理
系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。 系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理 1 编写异常类和错误页面
暴躁的程序猿
2022/03/23
1720
springmvc异常处理
3分钟快速上手springBoot全局异常处理
后端请求响应的数据格式都是有个统一的格式返回如Result,中有code,message,data。而若service、controller抛出异常则会导致不是统一格式的返回而是以下格式:
进击的代码
2023/12/10
3900
Java后端开发你应该知道的全局异常处理
在开发Web应用程序时,异常处理是一项非常重要的任务。异常处理可以提高程序的健壮性和稳定性。Java后端开发人员可以设计一个统一的全局异常处理方案来解决异常处理的问题,避免代码冗余,提高开发效率。在本文中,我们将介绍如何设计Java后端的全局异常处理方案。
闻说社
2023/05/04
1.6K0
Web层框架对网站中所有异常的统一处理
  一个网站的异常信息作为专业的人士,是不会轻易暴露给用户的,因为那样狠不安全,显得你漏是一回事,只要还是考虑到网站的数据安全问题,下面给大家分享一下一些常见的web层框架是如何处理统一的异常。    之前都是在Struts2的配置文件中配置拦截器来统一处理系统中所有的异常,给大家带点伪代码吧,好歹曾经用过,呵呵。 配置文件配置信息如下: 1   <package name="base" extends="struts-default"> 2 <!-- 异常处理 --> 3
赵小忠
2018/01/24
6430
SpringBoot 2.x 进阶 之 Web
接着上一篇,SpringBoot2.x 教你快速入门,本篇内容我们来学习 SpringBoot2.X 进阶 Web 方面开发常用的一些知识点。
AI码真香
2022/09/13
4580
SpringBoot 2.x  进阶 之 Web
SpringMVC教程5[数据回写和异常处理及JSON操作]
在需要回传的对象前添加@ModelAttribute(“bb”)注解,在界面中就可以通过bb前缀来获取回写信息。
用户4919348
2019/04/02
9040
SpringMVC教程5[数据回写和异常处理及JSON操作]
Spring Boot:优雅地处理全局异常以及格式化输出
在Spring Boot应用程序中,全局异常处理是一种非常重要的功能。它可以帮助我们捕获未处理的异常,进行统一处理,并返回给客户端一个友好的错误信息。本文将介绍如何使用Spring Boot优雅地处理全局异常,并提供一些实用的代码示例。
Front_Yue
2024/07/24
2.1K0
Spring Boot:优雅地处理全局异常以及格式化输出
全局异常处理器
自定义异常类: package com.shi.ssm.exception; /* * 自定义异常类 */ public class CustomException extends Except
用户5927264
2019/07/31
5840
SpringMVC之拦截器和异常处理
Spring MVC中的拦截器(Interceptor),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行​权限验证​、记录​请求信息的日志​、​判断用户是否登录​等。要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。
张哥编程
2024/12/13
1860
SpringMVC之拦截器和异常处理
探索 Spring Boot 高级应(四)用:Thymeleaf、全局异常处理与 AOP
大家好,我是默语,一个专注于分享技术干货的博主。这篇博客将深入探讨Spring Boot的高级应用,涵盖Thymeleaf模板引擎的集成、全局异常处理以及AOP切面的实现。通过丰富的代码案例和详细的讲解,希望能够帮助大家全面掌握这些高级技术,提高项目的开发效率和代码质量。关键词包括Spring Boot集成Thymeleaf、全局异常处理、Spring Boot AOP等。
默 语
2024/11/20
1820
SpringMVC学习笔记(五) --- 异常处理、图片上传、Json数据交互、RESTful支持、拦截器
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
挽风
2021/04/13
7620
SpringMVC学习笔记(五) --- 异常处理、图片上传、Json数据交互、RESTful支持、拦截器
Spring Boot 快速入门系列(VII)—— 全局异常处理篇
《Spring Boot 快速入门系列》上一节「接口规范篇」讲完了,小伙伴们是否已经掌握了基本的接口编写规范(后面会有一篇专门演示在线接口文档内容)。
IT技术小咖
2019/10/08
4680
Spring Boot 快速入门系列(VII)—— 全局异常处理篇
相关推荐
重学SpringBoot系列之统一全局异常处理
更多 >
LV.4
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验