java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringMVC异常处理

SpringMVC异常处理的三种方式小结

作者:云村小威

本文主要介绍了SpringMVC异常处理的三种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 什么是异常

见字如意,就是编码时所报的错误。异常主要分为两种:编译时异常和运行时异常RuntimeException。前者在编码时如不符合规范代码就会报红,是肉眼也看到的错,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

在Spring MVC中,异常处理是指对在请求处理过程中可能发生的异常情况进行捕获、处理和响应的机制。它能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。

2. 为什么要全局异常处理

在开发中,不管是dao层、service层还是controller层,都有可能抛出异常。使用全局异常处理有以下几个优点:

总的来说,全局异常处理能够提高系统的可维护性、容错性和安全性,提供更好的用户体验,方便系统的监控和问题排查。在开发应用程序时,合理利用全局异常处理机制可以有效地处理异常情况,保证应用程序的稳定。

3. SpringMVC异常分类

在Spring MVC中,异常可以分为两类:应用程序异常和系统异常

应用程序异常:应用程序异常是指由应用程序自身业务逻辑引发的异常,通常是预期的异常情况。这些异常可以根据具体业务需求进行分类,例如用户输入验证失败、资源未找到、权限不足等。应用程序异常可以通过自定义异常类来表示,可以添加自定义的异常信息,以便更好地理解异常原因和处理异常。

系统异常:系统异常是指由系统运行环境或外部因素引发的异常,通常是非预期的异常情况。这些异常可能包括数据库连接失败、网络连接异常、服务器内部错误等。系统异常是无法通过应用程序自身的逻辑来解决的,需要通过合适的异常处理机制来捕获和处理。

在Spring MVC中,可以通过合理的异常分类和处理机制来对应用程序异常和系统异常进行区分和处理。通常,应用程序异常可以通过 @ExceptionHandler 注解或自定义的异常处理器来处理,而系统异常可以通过全局异常处理器( HandlerExceptionResolver 接口的实现)来捕获和处理。这样可以实现对不同类型异常的精细处理,提高系统的可靠性和用户体验。

4. 异常处理思路

系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

总结来说,异常处理的思路是根据异常类型进行分类,确定异常处理的范围和层级,定义自定义异常类,捕获和处理异常,并根据具体情况进行异常处理逻辑和异常信息展示。通过合理的异常处理,可以提高系统的可靠性。

5. 三种异常处理方式示例

在演示下面之前我们现在没有进行异常处理事如何报错的:

1. 随便在那个方法或者controller手动写一个错误信息

2. 运行该路径

这就是没有经过任何异常处理的错误信息,如果将这个界面回显给客户当然是不可观的,请继续往下看。

① 配置 SimpleMappingExceptionResolver 处理器

SpringMVC中自带了一个异常处理器叫SimpleMappingExceptionResolver,该处理器实现了HandlerExceptionResolver 接口,全局异常处理器都需要实现该接口。

1. spring-mvc.xml:

    <!-- springmvc提供的简单异常处理器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 定义默认的异常处理页面 -->
        <property name="defaultErrorView" value="error"/>
        <!-- 定义异常处理页面用来获取异常信息的变量名,也可不定义,默认名为exception -->
        <property name="exceptionAttribute" value="xw"/>
        <!-- 定义需要特殊处理的异常,这是重要点 -->
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.RuntimeException">error</prop>
            </props>
            <!-- 还可以定义其他的自定义异常 -->
        </property>
    </bean>

注:页面跳转由SpringMVC来接管了,所以此处的定义默认的异常处理页面都应该配置成逻辑视图名。

2. 创建error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--错误信息--%>
${xw}<br>
<img src="static/imgs/R.jpg">
</body>
</html>

配置异常处理后的界面:

② 实现 HandlerExceptionResolver 接口

1. 创建一个名为GlobalException的自定义异常类,它继承自RuntimeException类。

在Java中,自定义异常类通常需要继承自Exception类或其子类。RuntimeException是Exception的一个子类,它表示在程序执行过程中可能会发生的异常情况。通过继承RuntimeException类,GlobalException可以被视为一个非受检异常(unchecked exception),即在方法签名中不需要显式声明或捕获。

GlobalException类提供了多个构造函数,用于创建不同类型的异常对象。每个构造函数都调用了父类RuntimeException的相应构造函数,以便将异常信息传递给父类进行处理。

package com.ycxw.exception;
public class GlobalException extends RuntimeException {
    public GlobalException() {
    }
    public GlobalException(String message) {
        super(message);
    }
    public GlobalException(String message, Throwable cause) {
        super(message, cause);
    }
    public GlobalException(Throwable cause) {
        super(cause);
    }
    public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

通过提供不同的构造函数,GlobalException类可以在不同的情况下创建异常对象,并传递相关的异常信息和原因。

自定义异常类的好处在于可以根据应用程序的需求,定义特定类型的异常,以便更好地描述和处理不同的异常情况。在代码中,当某个方法或操作发生异常时,可以抛出GlobalException对象,并在上层进行相应的异常处理逻辑。

2. 定义了一个名为GlobalExceptionHandler的类,并实现了HandlerExceptionResolver接口。同时,使用@Component注解将该类标记为一个Spring组件,以便在应用程序中进行自动扫描和注册。

@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            mv.addObject("xw",globalException.getMessage());
            mv.addObject("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            mv.addObject("xw",runtimeException.getMessage());
            mv.addObject("msg","运行时异常....");
        }
        return mv;
    }
}

通过实现HandlerExceptionResolver接口并定义resolveException方法,可以自定义全局异常处理逻辑,并在应用程序中统一处理异常情况。这样可以提供更好的用户体验,并减少代码中重复的异常处理代码。

利用上一个报错信息:

3. 抛出一个全局错误信息

③ 使用@ControllerAdvice+@ExceptionHandler实现全局异常

定义了一个名为GlobalExceptionResolver的类,并使用@ControllerAdvice注解将其标记为一个全局异常处理器。

package com.ycxw.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionResolver {
// 返回错误json数据
    @ResponseBody
    @ExceptionHandler
    public Map handler(Exception e){
        Map map = new HashMap();
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            map.put("xw",globalException.getMessage());
            map.put("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            map.put("xw",runtimeException.getMessage());
            map.put("msg","运行时异常....");
        }else {
            map.put("xw",e.getMessage());
            map.put("msg","其它异常....");
        }
        return map;
    }
}

通过使用@ControllerAdvice注解和@ExceptionHandler注解,可以自定义全局异常处理逻辑,并将异常信息以JSON格式返回给客户端。这样可以提供更好的错误处理和异常信息展示方式。

6. 响应封装类

响应封装类的作用是将响应数据进行统一的封装和格式化,以便在应用程序中进行统一的处理和返回给客户端。

总之,响应封装类的作用是提供一个统一的响应数据格式,简化客户端的处理逻辑,提供额外的功能如异常处理和多语言支持,并提高应用程序的可维护性和可扩展性。

例如: 

package com.ycxw.utils;
import java.util.HashMap;
public class R extends HashMap {
    public R data(String key, Object value) {
        this.put(key, value);
        return this;
    }
    public static R ok(int code, String msg) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg);
        return r;
    }
    public static R error(int code, String msg) {
        R r = new R();
        r.data("success", false).data("code", code).data("msg", msg);
        return r;
    }
    public static R ok(int code, String msg,Object data) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg).data("data", data);
        return r;
    }
    public static R ok(int code, String msg, long count, Object data) {
        R r = new R();
        r.data("success", true).data("code", code).data("msg", msg).data("count", count).data("data", data);
        return r;
    }
}

编写统一响应方法:

    // 响应封装类
    @ResponseBody
    @ExceptionHandler
    public R handler(Exception e){
        if (e instanceof GlobalException){
            GlobalException globalException = (GlobalException) e;
            return R.ok(505,"全局异常....",globalException.getMessage());
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            return R.ok(505,"运行时异常....",runtimeException.getMessage());
        }else {
            return R.ok(505,"其他异常....",e.getMessage());
        }
    }

运行测试:

到此这篇关于SpringMVC异常处理的三种方式小结的文章就介绍到这了,更多相关SpringMVC异常处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

您可能感兴趣的文章:
阅读全文