【SpringMVC】JSON注解&全局异常处理机制(二)

简介: 【SpringMVC】JSON注解&全局异常处理机制(二)

二、异常处理

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

在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护 ,全局异常处理是指在应用程序中对所有异常进行捕获和处理,而不是仅仅对特定的异常进行处理。

以下是一些原因说明为什么要全局异常处理:

  1. 统一处理异常:全局异常处理可以确保在应用程序的所有部分都使用相同的异常处理逻辑,从而使代码更加一致和易于维护。
  2. 简化代码:通过将异常处理逻辑集中在一个地方,可以减少代码冗余,并使代码更易于阅读和维护。
  3. 提高安全性:全局异常处理可以帮助防止未处理的异常导致的潜在安全问题,例如泄露敏感信息或允许攻击者执行恶意代码。
  4. 更好的用户体验:通过全局异常处理,应用程序可以在出现异常时给出更有用和友好的错误消息,从而提高用户体验。

综上所述,全局异常处理可以使应用程序更加健壮、一致、易于维护和安全,同时提供更好的用户体验。

小贴士:运行时异常和编译时异常的区别?

  1. 编译时异常(Checked Exception): 编译时异常是在编译阶段被检查出来的异常,必须进行处理,否则编译器会报错。常见的编译时异常有IOException、SQLException等。处理方式可以使用try-catch语句块来捕获和处理这些异常。
  2. 运行时异常(Runtime Exception): 运行时异常是在程序运行期间抛出的异常,如果不进行处理,程序会崩溃。常见的运行时异常有NullPointerException、ArrayIndexOutOfBoundsException等。这些异常通常是由程序逻辑错误引起的,因此无法在编译时进行检测。

2.2.异常处理思路

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

具体来说,异常处理的思路包括以下几个方面:

  1. 确定异常类型:在进行异常处理之前,需要先确定可能会出现哪些异常情况,以及这些异常情况对应的异常类型。
  2. 添加异常处理代码:在程序中添加相应的异常处理代码,用于捕获可能出现的异常,并进行相应的处理。
  3. 处理异常:根据不同的异常类型,采取不同的处理方式。例如,对于运行时异常,可以采取打印错误信息等方式进行处理;对于受检异常,则需要在方法声明中添加throws关键字,并在调用该方法时进行try-catch处理。
  4. 优化异常处理:在实际应用中,需要根据具体情况对异常处理进行优化。例如,可以使用多线程机制来提高程序的性能;或者使用日志系统来记录程序运行过程中出现的异常情况等。

2.3.SpringMVC异常分类

SpringMVC中的异常处理方式有三种:

  • 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
  • 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器;
  • 使用@ControllerAdvice + @ExceptionHandler

 

2.4.案例实战

2.4.1.异常处理方式①

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

spring-mvc.xml

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

error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>系统繁忙</title>
</head>
<body>
${ex}<br>
<img src="${pageContext.request.contextPath }/static/1.jpg" style="height: 1000px;width: 1550px;">
</body>
</html>

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

我们没有配置这段代码之前,以下的页面是我们不想看到的,看看配置后是怎么样的吧?

配置异常处理:

明显后面做了异常处理的看起来更为舒服。

2.4.2.异常处理方式②

创建一个名为exception的包将我们的GlobalException类放入其中。

GlobalException.java

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);
    }
}

创建一个名为Component的包将我们的GlobalExceptionHandler类放入其中。

GlobalExceptionHandler.java

@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("ex",globalException.getMessage());
            mv.addObject("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            mv.addObject("ex",runtimeException.getMessage());
            mv.addObject("msg","运行时异常....");
        }else{
            mv.addObject("ex",e.getMessage());
            mv.addObject("msg","其他异常....");
        }
        return mv;
    }
}

1.通过instanceof判断异常类型

2.通过设置mv.setView(new MappingJackson2JsonView())方式返回JSON数据

这时候我们来访问以下http://localhost:8080/xwzyssm/stu/json/jsonStr

因为异常处理会根据我们的异常问题进行判断map保存输出到前端,所以在JSP页面上用EL表达式捕捉msg信息就可以知道问题是什么更为直观。

2.4.3.异常处理方式③

GlobalExceptionResolver.java

@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("ex",globalException.getMessage());
            map.put("msg","全局异常....");
        }else if (e instanceof RuntimeException){
            RuntimeException runtimeException = (RuntimeException) e;
            map.put("ex",runtimeException.getMessage());
            map.put("msg","运行时异常....");
        }else {
            map.put("ex",e.getMessage());
            map.put("msg","其它异常....");
        }
        return map;
    }
}

这种方式是将我们的错误信息进行map保存然后转换为JSON格式输出在页面上。

这时候我们来访问以下 http://localhost:8080/xwzyssm/stu/json/jsonStr

2.5.响应封装类

通过我刚刚的解释想必大家对异常处理有了一定的理解,但是大家有没有发现,异常处理类中反复的需要定义Map,随后.put添加数据,我们能否对以上代码进行优化呢?能!!下面请欣赏小编所需的R工具类。

R.java

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;
    }
}

GlobalExceptionResolver.java

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

 这时候我们来访问以下 http://localhost:8080/xwzyssm/stu/json/jsonStr

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖


相关文章
|
1月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
1月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
53 2
|
2月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
1月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
111 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
2月前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
1月前
|
XML 存储 前端开发
手动开发-实现SpringMVC底层机制--小试牛刀
手动开发-实现SpringMVC底层机制--小试牛刀
14 0
|
3月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
3月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
|
3月前
|
前端开发 应用服务中间件 数据库
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查
这篇文章通过一个具体的项目案例,详细讲解了如何使用SpringMVC、Thymeleaf、Bootstrap以及RESTful风格接口来实现员工信息的增删改查功能。文章提供了项目结构、配置文件、控制器、数据访问对象、实体类和前端页面的完整源码,并展示了实现效果的截图。项目的目的是锻炼使用RESTful风格的接口开发,虽然数据是假数据并未连接数据库,但提供了一个很好的实践机会。文章最后强调了这一章节主要是为了练习RESTful,其他方面暂不考虑。
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查
|
3月前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
88 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧