Spring的全局(统一)异常处理

一,为什么要有全局异常处理

听到“全局异常处理”这个名字之后,我楞了三秒,虽然不知道它具体是什么,具体要怎么做,但是通过名字种的“异常处理”让我感觉到它大概可能是在编程中处理异常(当然异常我是懂的)的一种方式,此时此刻让我想起了平时处理异常常用的”try、catch、finally、throw、throws“这么几个东西;因为听到的原话是“Spring的全局异常处理”,此时此刻,我感觉它可能是Spring为程序开发人员提供的一种更方便、友好、简单......的处理异常的方式吧。

再结合”全局“这个定语,难道它可以让所有的异常在全局的位置一下子处理了?而不是像try...catch似的一个分布在代码中一个异常位置处理一次(当然,这句是看了全局异常之后才学到的,为了文章的理解需要先怼上来,嘿嘿)。

1)try...catch的弊端

①处理繁琐

编写程序的过程中,不可避免的需要在各种地方处理各种异常,所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块与处理业务的代码搅合在一起,不仅有大量的冗余代码,而且还影响代码的可读性。

②解决不了一异常

try...catch捕获不了参数异常,(--------------------------代码示例)

2)定义类似BaseController的基类

一个正儿八经简简单单的Controller去继承一个处理异常的类?

二,异常处理的三种方式

1,实现HandlerExceptionResolver接口

2,@ExceptionHandler

3,@ControllerAdvice+@ExceptionHandler

三,@ExceptionHandler+@ControllerAdvice的全局异常处理方式(诞生于Spring3.2)

ExceptionHandler,英译汉:异常处理器,实际作用:如果在某个Controller类中定义一个异常处理方法,并在方法上添加该注解,当出现指定的异常时,会执行该处理异常的方法。

此时,就需要为每个Controller类都定义一个这样的异常处理方法,但异常的种类很多,如果需要将不同的异常分类处理,就要为每种异常定义一个异常处理方法,于是:每个Controller类都有对每种异常处理的方法——大量的代码冗余、复杂的编程以及困难的维护(如果需要新增一种异常的处理,就需要为每个Controller类添加一个对该异常处理的方法。

@ControllerAdvice闪亮登场!

该注解(@ControllerAdvice)可以把异常处理器(被@ExceptionHandler注解的方法)应用到所有的Controller,而不是单单的一个Controller类。

全局异常处理的原理:在独立的一个类中,定义一套对各种异常的处理机制,然后用@ControllerAdvice注解该类,统一对不同位置的不同异常进行处理。

四,代码实践

(1)操作步骤

①在包exception中创建处理异常的类(处理异常的类只能扫描到同一层级以及下一级中的文件,如果将该类放在web包中,将只能处理web包下的异常),这时便可以处理和exception包同一级的web下的异常了:

②在controller的异常

③设置统一处理异常的类

//通过使用@ControllerAdvice定义统一的异常处理类,而不是每个Controller种逐个定义
@ControllerAdvice
public class ErrorControllerAdvice {
    //注解:出现异常会来到这个方法处理
    //参数:捕获控制器出现的异常,可传入集合捕获多种类型的异常
    @ExceptionHandler(RuntimeException.class)
    public void handlerError(RuntimeException ex, HandlerMethod hm){
        System.out.println("统一异常处理");
        System.out.println(ex.getMessage());//异常信息
        System.out.println(hm.getBean().getClass());//哪个类下
        System.out.println(hm.getMethod().getName());//在哪个方法的
    }
}

(2)代码分析

@ExceptionHandler

作用:用来定义针对某种异常的异常处理方法

参数:定义该异常处理器捕获控制器里面出现的哪些异常;可传入集合。

比如,传RuntimeException.class,该处理方法只会捕获RuntimeException异常进行处理。

从源码可指,参数为指定方法处理哪个异常,如果不设置,默认是捕获方法里面参数传的异常,可以通过数组传入多个异常

@ControllerAdvice:通过使用该注解定义同i的异常处理类,而不是在每个Controller中逐个通过注解@ExceptionHandler定义异常处理方法;

从RestControllerAdvice的源码可知,该注解的一个重要参数是value是basePackages的别名,设定该类要捕获哪些包的异常,是String数组类型。

方法参数

可以穿入web环境的对象,比如传入RuntimeException对象可拿到异常信息,传入HandlerMethod,表示当前访问的出现异常的控制器方法,从而可得到出现异常的类、方法名等;

(3)运行结果:

不处理异常前:

此时,异常被捕获,同时在控制台打印相应信息,不会在控制台打印长长的错误信息,同时前端不会显示错误信息。

此外,可将异常信息保存到日志,并重定向至另一个界面进行为用户显示,或进行其他的处理。

//通过使用@ControllerAdvice定义统一的异常处理类,而不是每个Controller种逐个定义
//@ControllerAdvice
public class ErrorControllerAdvice {
    @ExceptionHandler(Exception.class)
    public void handlerError2(Exception ex){
        try {
            FileOutputStream fos = new FileOutputStream("d:\\spingLog.log");
            PrintStream ps = new PrintStream(fos);
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = sdf.format(date)+"------------------------";
            ps.println();
            ps.print(time);
            //将错误喜喜写入到日志文件
            ex.printStackTrace(ps);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //return "";//可以重定向到一个页面
    }
}

日志文件:

有了个基本的理解,反正感觉还有点乱,对于深入的内容,以后再接再厉!

  • 18
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Spring框架中,可以通过全局异常处理机制来统一处理应用程序中的异常情况,避免异常信息直接暴露给用户,提高用户体验和系统的健壮性。以下是一个简单的示例来说明如何实现全局异常处理。 首先,创建一个自定义的全局异常处理器类,该类需要实现`HandlerExceptionResolver`接口。可以通过继承`AbstractHandlerExceptionResolver`类来简化实现。 ```java import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; public class GlobalExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 处理异常逻辑 ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("error"); // 设置错误页面 modelAndView.addObject("errorMsg", ex.getMessage()); // 将异常信息传递给错误页面 return modelAndView; } } ``` 接下来,需要在Spring配置文件中注册该全局异常处理器: ```xml <bean id="globalExceptionHandler" class="com.example.GlobalExceptionHandler" /> ``` 最后,可以在控制器中抛出异常,在全局异常处理器中进行统一处理: ```java @Controller public class UserController { @RequestMapping("/user/{id}") public String getUser(@PathVariable("id") int id) { // 模拟抛出异常 if (id <= 0) { throw new IllegalArgumentException("Invalid user ID"); } // ... } } ``` 当控制器方法中抛出异常时,全局异常处理器会捕获该异常并执行相应的处理逻辑。在上述示例中,异常会被处理并渲染到名为"error"的错误页面中。 这样,无论在哪个控制器方法中发生异常,都可以通过全局异常处理器进行统一异常处理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值