web九大组件之---HandlerExceptionResolver异常处理器使用详解【享学Spring MVC】(下)

简介: web九大组件之---HandlerExceptionResolver异常处理器使用详解【享学Spring MVC】(下)

使用示例


简单的演示一下使用的Demo:


@Controller
@RequestMapping
public class HelloController {
    @ResponseBody
    @GetMapping("/test/exception")
    public int testException(@RequestParam(required = false, defaultValue = "1") Integer value) {
        if (value == 100) {
            // 状态码设置为501 方便识别
            throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "服务端发生异常啦");
        }
        return 10 / value;
    }
}

访问以及结果的截图如下:


image.png


异常处理过程分析:


  • value值传0,处理器(HandlerMethod)会抛出计算异常:ArithmeticException(/ by zero)。此异常交给默认注册上去的三个异常处理器进行处理,发现:没有一个HandlerExceptionResolver可以处理这种异常类型,所以经过DispatcherServlet#processHandlerException处理后得到的ModelAndView为null(无异常视图),因此最终的结果是:执行完afterCompletion()方法后,throw ex交给web容器去处理。这就是我们如上截图看到的结果页面,连异常代码都有,极度的不友好有木有。


若value值换位100,这样异常类型能能被处理器处理的,结果如何呢?看下截图:


image.png


异常处理过程分析:


  • 此异常经过ResponseStatusExceptionResolver处理后得到一个ModelAndView,但exMv.isEmpty() = true的,因此异常不会throw出来而是return null。所以最终因为ModelAndView是空的但异常也没throw出来,最终就是把response返回喽(已经设置好返回状态码和错误消息的response),显然这种方式虽然比上面稍好(没有错误代码了),但对用户来说也是不友好的。


备注:本文并不演示最为强大、复杂的ExceptionHandlerExceptionResolver,也就是不演示@ExceptionHandler方式,因为它的详解在此处专文讲解


自定义HandlerExceptionResolver处理异常


上面两个案例都是使用Spring MVC内置的异常处理器,显然用户体验均非常不友好。所以在实际生产环境,必须是需要自己来处理异常(页面)的,下面采用自定义HandlerExceptionResolver方式给出Demo案例,仅供参考:


1、自定义异常处理类并配置上去(本例以匿名内部类方式处理):

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        // 自定义异常处理器一般请放在首位
        exceptionResolvers.add(0, new AbstractHandlerExceptionResolver() {
            @Override
            protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
                // 若是自定义的业务异常,那就返回到单页面异常页面
                if (ex instanceof BusinessException) {
                    return new ModelAndView("/business.jsp");
                } else { // 否则统一到统一的错误页面
                    return new ModelAndView("/error.jsp");
                }
            }
        });
    }
}


2、对应的准备两个错误页面


image.png


3、请求示例截图如下(value=0 or 100):


image.png


image.png


相关阅读


@ExceptionHandler or HandlerExceptionResolver?如何优雅处理全局异常?【享学Spring MVC】


总结


我书写本文的目的主要是让大家"善待异常"和重视异常的处理,我认为一个好的程序员应该对异常的处理都是相对妥当的,而不是坐而不理。我相信你在工作中一定遇到过异常处理不妥当而到处吐槽你的团队的现象,那么看了本文后,动起来吧,重视起来吧,处理起来吧,而不是只剩下抱怨了…


不客气的说一句话:微服务的难点在于它的治理,若你统一了技术栈,规范了各种情况的处理(比如远程调用、异常处理、状态码返回、熔断处理等),它将会让你的开发效率、监控、报警问题、定位成本大大减少。所以从某种程度上,它是服务开发、服务治理非常非常重要的一环,所以"代码架构师"真的是非常重要的,而不是什么都只做事后补救,事前预防或许来得更有效。


当然,本文介绍的方案还是不够的,因为更为重要的@ExceptionHandler方式我放在了下一篇文章单独讲解。在当下Rest流行的生产环境下,使用更加强大、更方便的@ExceptionHandler方式是首选。对于它的解释说明和使用Demo,出门右拐可以给你惊喜。同时此时你是否疑问过这个问题:若异常处理器里面抛出了异常,将会怎样呢?答案也一样的出门右拐吧~



相关文章
|
7月前
|
JSON 前端开发 Java
Spring MVC 核心组件与请求处理机制详解
本文解析了 Spring MVC 的核心组件及请求流程,核心组件包括 DispatcherServlet(中央调度)、HandlerMapping(URL 匹配处理器)、HandlerAdapter(执行处理器)、Handler(业务方法)、ViewResolver(视图解析),其中仅 Handler 需开发者实现。 详细描述了请求执行的 7 步流程:请求到达 DispatcherServlet 后,经映射器、适配器找到并执行处理器,再通过视图解析器渲染视图(前后端分离下视图解析可省略)。 介绍了拦截器的使用(实现 HandlerInterceptor 接口 + 配置类)及与过滤器的区别
677 0
|
7月前
|
JSON Java 数据库
第08课:Spring Boot中的全局异常处理
第08课:Spring Boot中的全局异常处理
931 0
|
11月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——处理系统异常
本文介绍了在Spring Boot项目中如何通过创建`GlobalExceptionHandler`类来全局处理系统异常。通过使用`@ControllerAdvice`注解,可以拦截项目中的各种异常,并结合`@ExceptionHandler`注解针对特定异常(如参数缺失、空指针等)进行定制化处理。文中详细展示了处理参数缺失异常和空指针异常的示例代码,并说明了通过拦截`Exception`父类实现统一异常处理的方法。虽然拦截`Exception`可一劳永逸,但为便于问题排查,建议优先处理常见异常,最后再兜底处理未知异常,确保返回给调用方的信息友好且明确。
1379 0
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——处理系统异常
|
11月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——拦截自定义异常
本文介绍了在实际项目中如何拦截自定义异常。首先,通过定义异常信息枚举类 `BusinessMsgEnum`,统一管理业务异常的代码和消息。接着,创建自定义业务异常类 `BusinessErrorException`,并在其构造方法中传入枚举类以实现异常信息的封装。最后,利用 `GlobalExceptionHandler` 拦截并处理自定义异常,返回标准的 JSON 响应格式。文章还提供了示例代码和测试方法,展示了全局异常处理在 Spring Boot 项目中的应用价值。
550 0
|
11月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——定义返回的统一 json 结构
本课主要讲解Spring Boot中的全局异常处理方法。在项目开发中,各层操作难免会遇到各种异常,若逐一处理将导致代码耦合度高、维护困难。因此,需将异常处理从业务逻辑中分离,实现统一管理与友好反馈。本文通过定义一个简化的JsonResult类(含状态码code和消息msg),结合全局异常拦截器,展示如何封装并返回标准化的JSON响应,从而提升代码质量和用户体验。
300 0
|
开发框架 Java UED
如何使用 Spring Boot 实现异常处理
如何使用 Spring Boot 实现异常处理
584 2
|
Dubbo Java 应用服务中间件
深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案
本文深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案。通过检查GraalVM版本兼容性、配置反射列表、使用代理类、检查配置文件、禁用不支持的功能、查看日志文件、使用GraalVM诊断工具和调整GraalVM配置等步骤,帮助开发者快速定位并解决问题,确保服务的正常运行。
609 1
|
Java 关系型数据库 数据库连接
SpringBoot项目使用yml文件链接数据库异常
【10月更文挑战第3天】Spring Boot项目中数据库连接问题可能源于配置错误或依赖缺失。YAML配置文件的格式不正确,如缩进错误,会导致解析失败;而数据库驱动不匹配、连接字符串或认证信息错误同样引发连接异常。解决方法包括检查并修正YAML格式,确认配置属性无误,以及添加正确的数据库驱动依赖。利用日志记录和异常信息分析可辅助问题排查。
1383 11
|
前端开发 JavaScript 开发者
Web组件:一种新的前端开发范式
【10月更文挑战第9天】Web组件:一种新的前端开发范式
479 2
|
Java API Spring
springBoot:注解&封装类&异常类&登录实现类 (八)
本文介绍了Spring Boot项目中的一些关键代码片段,包括使用`@PathVariable`绑定路径参数、创建封装类Result和异常处理类GlobalException、定义常量接口Constants、自定义异常ServiceException以及实现用户登录功能。通过这些代码,展示了如何构建RESTful API,处理请求参数,统一返回结果格式,以及全局异常处理等核心功能。
195 1