Spring MVC 异常处理

这篇具有很好参考价值的文章主要介绍了Spring MVC 异常处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

统一处理某一类异常,能够减少代码的重复度和复杂度,有利于代码的维护。

Spring 统一异常处理有 4 种方式,分别为:

  • 使用 @ ExceptionHandler 注解

  • 实现 HandlerExceptionResolver 接口

  • 使用 @controlleradvice 注解

  • 使用 @Restcontrolleradvice注解

1.1 使用 @ ExceptionHandler 注解

使用@ExceptionHandler注解作用在方法上面,参数是具体的异常类型。

一旦系统抛出这种类型的异常时,会引导到该方法来处理。

但是它的缺陷很明显,处理异常的方法和出错的方法(或者异常最终抛出来的地方)必须在同一个controller,不能全局控制。

 @GetMapping("/gooderr")
    public Good test3(Good good){
        int i=5/0;
        return good;
    }

//如果不加这个 就会报500页面错误
@ExceptionHandler(Exception.class)
public ModelAndView myException(Exception e) {
    ModelAndView error = new ModelAndView("error");
    error.addObject("error", e.getMessage());
    return error;
}

编写一个error.jsp文件

<%@page pageEncoding="UTF-8" language="java" contentType="text/html;UTF-8" %>
<html>
<body>
<h1>这是错误页面</h1>
<p>${error}</p>
</body>
</html>

1.2 实现 HandlerExceptionResolver 接口

springmvc提供一个HandlerExceptionResolver接口,自定义全局异常处理器必须要实现这个接口,如下:

创建一个包:

handlerexr包下创建

@Component
public class HandlerResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(
            HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse,
                             Object o, Exception e) {
        ModelAndView mv=new ModelAndView();
        mv.addObject("msg",e.getMessage());
        mv.setViewName("error");
        return mv;
    }
}

测试运行:http://localhost:8080/gooderr

分类异常处理:创建三个异常页面 复制三个 分别是空指针Arithmetic计算异常全局异常

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h2>测试成功,欢迎来到我的世界</h2>
    <p>空指针异常:${msg}</p>
    <img src="../img/q1.jpg">
</body>
</html>

先验证是否正确:http://localhost:8080/gooderr

异常验证controller:

@GetMapping("/gooderr")
    @ResponseBody
    public Good test2(Good good) throws BizException {
        if(good.getNum()==1){
            int i=5/0;
        }else if (good.getNum()==2){
            String name=null;
            name.equals("abc");
        }
        return good;
    }

访问地址:http://localhost:8080/gooderr?num=1 计算异常

http://localhost:8080/gooderr?num=2 空指针异常

内容输出:

@Component
public class HandlerResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(
            HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse,
                             Object o, Exception e) {
        ModelAndView mv=new ModelAndView();
        if(e instanceof ArithmeticException){
            mv.setViewName("Arithmetic");
           mv.addObject("msg",e.getMessage());
        }
        if(e instanceof NullPointerException){
            mv.setViewName("nullpoint");
        }
        mv.addObject("msg",e.toString());
/*
        mv.addObject("msg",e.getMessage());
        mv.setViewName("error");*/
        return mv;
    }
}

直接测试

1.3 使用 @ControllerAdvice+ @ ExceptionHandler 注解 (重点)

@ExceptionHandler 可以返回 ModelAndView 定制异常视图。

@ControllerAdvice 是一个增强的 Controller,@ExceptionHandler 可以拦截特定的异常,因此可以更精确的配置异常处理逻辑。

创建一个类advice中: MyExceptionAdvice

@ControllerAdvice
public class MyExceptionAdvice {
    @ExceptionHandler(NullPointerException.class)
    public ModelAndView processException(NullPointerException ex){
        ModelAndView mv = new ModelAndView("nullpoint");
        mv.addObject("msg",ex.toString());
        return mv;
    }

    @ExceptionHandler(ArithmeticException.class)
    public ModelAndView processException2(ArithmeticException ex){
        ModelAndView mv = new ModelAndView("arith");
        mv.addObject("msg",ex.toString());
        return mv;
    }
}

测试运行:

简写方式:

@ExceptionHandler(Exception.class)
    public ModelAndView processException(Exception e){
      
        ModelAndView mv=new ModelAndView();
        if(e instanceof ArithmeticException){
            mv.setViewName("arith");
            mv.addObject("msg",e.getMessage());
        }
        if(e instanceof NullPointerException){
            mv.setViewName("nullpoint");
             mv.addObject("msg",e.toString());
        }
        // mv.addObject("msg",e.toString());
       
        return mv;
    }

但是使用第一种方式还是比较清晰的:

自定义异常类:自己编写一个异常类:

public class BizException extends Exception{
    private int code;

    public BizException(String msg){
        super(msg);
    }
    public BizException(int code,String msg){
        super(msg);
        this.code=code;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
}

在MyExceptionAdvice中加一个方法:

 @ExceptionHandler(BizException.class)
    public ModelAndView processException2(BizException e){
        ModelAndView mv=new ModelAndView();
        mv.addObject("msg",e.getCode()+"-->"+e.toString());
        mv.setViewName("biz");
        return mv;
    }

建一个Biz的异常jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h2>测试成功,欢迎来到我的世界</h2>
    <p>自己定义的异常:${msg}</p>
</body>
</html>

controller中修改:

 @GetMapping("/gooderr2")
    @ResponseBody
    public Good test3(Good good) throws BizException {
        if(good.getNum()==1){
            int i=5/0;
        }else if (good.getNum()==2){
            String name=null;
            name.equals("abc");
        }else if(good.getNum()==3){
            throw  new BizException(301,"我看错你了");
        }else if(good.getNum()==4){
            throw  new BizException(401,"我看错你了");
        }
        return good;
    }

1.4 针对RestController 统一处理

@RestControllerAdvice
public class MyRestContollerAvice {

    @ExceptionHandler( Exception.class)
    public Object   error(Exception ex){
        Map map = new HashMap();
        map.put("code",1);
        map.put("message",ex.getMessage());
        return  map;
    }

}

1.5 扩展 统一返回值

建统一返回值类:

@Data
public class ResponseDTO {
    private int code;
    private String message;
    private Object data;

    public static ResponseDTO success(Object data){
        ResponseDTO dto=new ResponseDTO();
        dto.setData(data);
        return dto;
    }
    public static ResponseDTO error(int code,String msg){
        ResponseDTO dto=new ResponseDTO();
        dto.setCode(code);
        dto.setMessage(msg);
        return dto;
    }

}

统一异常处理

@RestControllerAdvice
@Slf4j
public class MyResponseAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
    
    @ExceptionHandler
    public Object processException(Exception ex){
        ex.printStackTrace();
        if(ex instanceof BizException){
            return   ResponseDTO.error(((BizException)ex).getCode(),ex.getMessage());
        }
        //其它异常
      return   ResponseDTO.error(999,ex.getMessage());
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        Object responseDTO = null;
         responseDTO =  ResponseDTO.success(body);
        
         //针对String返回值,我们做了下特殊处理,因为我们硬生生的给人家套了个外壳,StringHttpMessageConverter无能为力,所以我们自己把它转换成string就可以了
        if (selectedConverterType == StringHttpMessageConverter.class){
          return JSONUtil.toJsonStr(responseDTO);
        }
        return responseDTO;
    }
}

整体代码:文章来源地址https://www.toymoban.com/news/detail-549294.html

package com.by.advice;

@RestControllerAdvice
public class MyRestControllerAdvice  implements ResponseBodyAdvice<Object>{
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * beforeBodyWrite 在controller返回之前
     *      执行MethodParameter 获取方法参数中的类型
     * @param body 响应体内容
     * @param methodParameter 获取方法参数中的类型
     * @param mediaType 媒体类型:决定浏览器将以什么形式、什么编码对资源进行解析
     * @param selectedConverter 报文信息转换器。
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverter,
                                  ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        if(body instanceof ResponseDTO){
            return body;
        }
        ResponseDTO success = ResponseDTO.success(body);
        //针对String返回值 我们做特殊的处理
        if(selectedConverter== StringHttpMessageConverter.class){
            return JSONUtil.toJsonStr(success);
        }else {
            return success;
        }
    }

   /* @ExceptionHandler(Exception.class)
    public Object error( Exception e){
        ResponseDTO dto=new ResponseDTO();
        if(e instanceof BizException){
            BizException biz= (BizException) e;
            dto.setCode(biz.getCode());
        }else{
            dto.setCode(666);
        }
        dto.setMessage(e.getMessage());
        return dto;
    }*/
   /* @ExceptionHandler(BindException.class)
    public String processException(BindException e){
        BindingResult result = e.getBindingResult();
        StringBuilder sb=new StringBuilder();
        List<ObjectError> allError=result.getAllErrors();
        for (ObjectError error : allError) {
            sb.append(error.getDefaultMessage());
        }
        return sb.toString();
    }*/

    @ExceptionHandler(Exception.class)
    public Object error( Exception e){
        int code=666;
        if(e instanceof BizException){
            BizException biz= (BizException) e;
            code=biz.getCode();
        }
        if(e instanceof MethodArgumentNotValidException){
            StringBuilder sb = new StringBuilder();
            List<ObjectError> allErrors = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors();
            for(ObjectError error : allErrors){
                sb.append(error.getDefaultMessage());
            }
            return   ResponseDTO.error(888,sb.toString());
        }
        return   ResponseDTO.error(code,e.getMessage());
    }
}

到了这里,关于Spring MVC 异常处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [第二章—Spring MVC的高级技术] 2.3 处理异常

    各位小猿,程序员小猿开发笔记,希望大家共同进步。 引言 我是谁——异常处理。 来自那——所有功能正常运行,但出现错误 怎么办——如何处理异常和响应客户端 我是谁——Spring框架中的一个注解 用在哪——应用在控制器类或方法上 什么用——用于在控制器方法中指定

    2024年01月22日
    浏览(51)
  • 解密Spring MVC异常处理:从局部到全局,打造稳固系统的关键步骤

    😀前言 在现代软件开发中,异常处理是不可或缺的一部分,它能够有效地提高系统的稳定性和健壮性。在Spring MVC框架中,异常处理机制起着至关重要的作用,它允许开发者在程序运行过程中捕获、处理和报告异常,从而保障用户体验和系统可靠性。本文将带您深入探索Spr

    2024年02月10日
    浏览(44)
  • Spring Mvc:初识SpringMvc

    编译软件:IntelliJ IDEA 2019.2.4 x64 操作系统:win10 x64 位 家庭版 Maven版本:apache-maven-3.6.3 Mybatis版本:3.5.6 SpringMvc版本:5.3.1 ①SpringMVC是Spring的一种 子框架 ,它是Spring为【 展现层 | 表示层 | 表述层 | 控制层 】提供的 基于MVC设计理念 的优秀的Web框架,是目前最主流的MVC框架。

    2024年02月13日
    浏览(55)
  • Spring MVC 之MVC 体系结构、什么是SpringMVC

    三层架构 我们的开发架构⼀般都是基于两种形式,⼀种是 C/S 架构,也就是客户端/服务器;另⼀种是 B/S 架构,也就是浏览器服务器。在 JavaEE 开发中,⼏乎全都是基于 B/S 架构的开发。那么在 B/S 架构中,系统标准的三层架构包括:表现层、业务层、持久层。 三层架构中,每

    2024年02月09日
    浏览(51)
  • Spring MVC学习随笔-Ajax集成(JSON格式返回数据)、拦截器(MyInterceptor)、全局异常处理(GlobalExceptionResolver)

    学习视频:【编程不良人】继spring之后快速入门springmvc,面对SpringMVC不用慌 引入相关依赖 开发控制器 日期格式修正 可以正常响应 拦截器 :Interceptor 拦截 中断 类似于javaweb中的Filter,不过没有Filter那么强大 作用 Spring MVC的拦截器是一种用于在请求处理过程中进行预处理和后处

    2024年02月05日
    浏览(52)
  • 【SpringMVC】Spring Web MVC入门(一)

    前面我们了解了什么是Spring,那么今天我将为大家分享一种在日常网站开发中使用非常广泛的框架——Spring Web MVC。 先来看看官方解释。 Spring Web MVC是Spring Framework提供的Web组件,它是一个MVC设计模式的框架,主要用于开发灵活、松散耦合的Web应用程序。它提供了模型-视图-控

    2024年02月05日
    浏览(44)
  • (第十一天)初识SpringMVC SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录

    今天我们要来学习一下SSM框架的最后一个框架SpringMVC 一、初认SpringMVC 基本概念: ​ Spring MVC(Model-View-Controller)是一个用于构建Java Web应用程序的开源框架,它提供了一种基于MVC架构的方式来开发Web应用 。 ​ SpringMVC是Spring Framework的一部分,它是一种基于模型-视图-控制器(

    2024年02月07日
    浏览(72)
  • 【SpringMVC】基于 Spring 的 Web 层MVC 框架

    🎄欢迎来到@边境矢梦°的csdn博文🎄 🎄本文主要梳理SpringMVC : 基于 Spring 的 Web 层MVC 框架 🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以关注一下 🫰🫰🫰 ,下次更新不迷路🎆 Ps: 月亮越亮说明知识点越重要 (重要性或者难度越大

    2024年02月08日
    浏览(42)
  • SpringMVC-2-Spring MVC拦截器详解:从入门到精通

    能够编写拦截器并配置拦截器 1.1 拦截器概念和作用 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行 作用: 在指定的方法调用前后执行预先设定的代码 阻止原始方法的执行 总结:增强 核心原理:AOP思想 1.2 拦截器和过滤器的区别

    2024年02月12日
    浏览(50)
  • SpringMVC-1-解密Spring MVC:构建优雅、灵活的Web应用的秘诀

    能够编写SpringMVC入门案例 了解SpringMVC原理 思考:SpringMVC框架有什么优点? SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 优点 使用简单,开发便捷(相比于Servlet) 天然的与Spring框架集成(如IOC容器、AOP等) 请求处理简化:支持用户请求数据自动映射封装 响应处理简化:

    2024年02月12日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包