SpringMVC之JSON数据返回异常处理机制

目录

前言

一、JSON数据返回

1.导入依赖

2.配置spring-mvc.xml

3.使用@ResponseBody注解

4.Jackson

4.1.介绍

4.2.常用注解

二、异常处理机制

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

2.异常处理思路

3.SpringMVC异常分类

4.综合案例

4.1.异常处理方式一

4.2.异常处理方式二

4.3异常处理方式三

5.响应封装类


前言

        Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过一套注解,我们可以快速的搭建一个Web应用。在本文中,我们将重点介绍如何在Spring MVC中返回JSON数据以及如何处理异常。

一、JSON数据返回

1.导入依赖

为了使@ResponseBody注解生效,我们需要配置一个Jackson消息转换器,用于将Java对象序列化为JSON字符串。需要在pom.xml文件中添加Jackson依赖:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.3</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.3</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.3</version>
</dependency> 

2.配置spring-mvc.xml

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><ref bean="mappingJackson2HttpMessageConverter"/></list></property>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><!--处理中文乱码以及避免IE执行AJAX时,返回JSON出现下载文件--><property name="supportedMediaTypes"><list><value>text/html;charset=UTF-8</value><value>text/json;charset=UTF-8</value><value>application/json;charset=UTF-8</value></list></property>
</bean>

3.使用@ResponseBody注解

        在SpringMVC中,我们可以使用@ResponseBody注解将Controller方法的返回值直接转换为JSON格式。这样,当客户端请求该方法时,将会收到一个JSON格式的响应。

package com.ctb.controller;import com.ctb.biz.UserBiz;
import com.ctb.model.User;
import com.ctb.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Controller
@RequestMapping("/user/json")
public class JsonController {@Autowiredprivate UserBiz userBiz;/*** 返回List<T> JSON数组* @param req* @param user* @return*/@ResponseBody@RequestMapping("/list")public List<User> list(HttpServletRequest req, User user){PageBean pageBean = new PageBean();pageBean.setRequest(req);List<User> lst = this.userBiz.listPager(user, pageBean);System.out.println(1 / 0);return lst;}/*** 返回T JSON对象* @param req* @param user* @return*/@ResponseBody@RequestMapping("/load")public User load(HttpServletRequest req, User user){if(user.getId() != null){List<User> lst = this.userBiz.listPager(user, null);return lst.get(0);}return null;}/*** 返回List<Map> JSON数组* @param req* @param user* @return*/@ResponseBody@RequestMapping("/mapList")public List<Map> mapList(HttpServletRequest req, User user){PageBean pageBean = new PageBean();pageBean.setRequest(req);List<Map> lst = this.userBiz.mapListPager(user, pageBean);return lst;}/*** 返回Map JSON对象* @param req* @param user* @return*/@ResponseBody@RequestMapping("/mapLoad")public Map mapLoad(HttpServletRequest req, User user){if(user.getId() != null){List<Map> lst = this.userBiz.mapListPager(user, null);return lst.get(0);}return null;}//混合@ResponseBody@RequestMapping("/all")public Map all(HttpServletRequest req, User user){PageBean pageBean = new PageBean();pageBean.setRequest(req);List<User> lst = this.userBiz.listPager(user, pageBean);Map map = new HashMap();map.put("lst",lst);map.put("pageBean",pageBean);return map;}@ResponseBody//@RequestMapping("/jsonStr")public String jsonStr(HttpServletRequest req, User user){return "userEdit";}}

注意:在使用此注解之后不会再走视图解析器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。分别为对象,数组,对象数组(混合)

 以下是部分方法运行结果

4.Jackson

4.1.介绍

Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。

特点

  • 容易使用,提供了高层次外观,简化常用的用例。

  • 无需创建映射,API提供了默认的映射大部分对象序列化。

  • 性能高,快速,低内存占用

  • 创建干净的json

  • 不依赖其他库

  • 代码开源

4.2.常用注解
注解说明
@JsonIgnore作用在字段或方法上,用来完全忽略被注解的字段和方法对应的属性
@JsonProperty作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名
@JsonIgnoreProperties作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉
@JsonUnwrapped作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象
@JsonFormat指定序列化日期/时间值时的格式

二、异常处理机制

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

我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。在开发中,不管是dao层、service层还是controller层,都有可能抛出异常,在springmvc中,能将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。

2.异常处理思路

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

3.SpringMVC异常分类

  • 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;

  • 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器;

  • 使用@ControllerAdvice + @ExceptionHandler

4.综合案例

4.1.异常处理方式一

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

<!-- 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> 

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

前端页面


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>错误界面</title>
</head>
<body>
错误信息界面。。。。。。
${ex}
</body>
</html>

4.2.异常处理方式二
  •  创建一个名为GlobalException的自定义异常类

这是一个名为GlobalException的Java类,它继承自RuntimeExceptionRuntimeException是Java中所有未检查异常的父类。这个类提供了多种构造方法,用于创建不同类型的异常对象。

package com.ctb.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);}
}
  • 创建一个名为GlobalExceptionHandler的类,并实现了HandlerExceptionResolver接口。
package com.ctb.component;import com.ctb.exception.GlobalException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o, Exception e) {ModelAndView mv = new ModelAndView();mv.setViewName("error");//error.jspif (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","运行时异常....");}return mv;}
}

它实现了HandlerExceptionResolver接口(异常处理解析器)。当应用程序中抛出异常时,这个处理器会被调用,返回一个ModelAndView对象,用于渲染错误页面。

代码解析:

  1. @Component注解表示这个类是一个Spring组件,Spring会自动扫描并管理这个类的实例。

  2. GlobalExceptionHandler类实现了HandlerExceptionResolver接口,该接口只有一个方法resolveException,Spring在处理异常时会调用这个方法。

  3. resolveException方法接收四个参数,分别是HttpServletRequest、HttpServletResponse、Object和Exception。HttpServletRequest和HttpServletResponse是HTTP请求和响应的对象,Object是当前处理的请求或响应的对象,Exception是发生的异常。

  4. resolveException方法中,首先创建了一个ModelAndView对象mv,然后设置了视图名称为"error",即错误页面。

  5. 接着判断异常的类型,如果是GlobalException类型,则获取其消息并添加到mv中,同时添加一条"全局异常...."的消息。如果是RuntimeException类型,则获取其消息并添加到mv中,同时添加一条"运行时异常...."的消息。

  6. 最后返回mv对象,Spring会根据这个对象渲染错误页面。

部分方法测试 

4.3异常处理方式三
  • ControllerAdvice:这是一个全局的异常处理器,可以捕获所有控制器中抛出的异常。通常我们会使用 @ControllerAdvice 注解来标记一个类为 ControllerAdvice,然后在该类中定义异常处理方法。

  • @ExceptionHandler:这是一个用于处理方法参数中抛出的指定类型的异常的注解。我们可以在方法上使用 @ExceptionHandler 注解来指定要处理的异常类型,以及处理方法的名称。

package com.ctb.component;import com.ctb.exception.GlobalException;
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 {//    跳转错误页面
//    @ExceptionHandler
//    public ModelAndView handler(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","运行时异常....");
//        }
//        return mv;
//    }// 返回错误json数据@ResponseBody@ExceptionHandlerpublic 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;}
}

代码解析

handler(Exception e)方法:

  • 使用@ResponseBody注解,表示将返回的对象作为响应体发送给客户端。
  • 使用@ExceptionHandler注解,表示该方法用于处理控制器中抛出的异常。
  • 创建一个HashMap对象,用于存储异常信息。
  • 判断异常类型,如果是GlobalException,则将异常信息添加到map中,并设置提示信息为"全局异常....";
  • 如果异常类型是RuntimeException,则将异常信息添加到map中,并设置提示信息为"运行时异常....";
  • 其他类型的异常,将异常信息添加到map中,并设置提示信息为"其它异常....";
  • 返回map对象。

部分方法测试 

 

 

5.响应封装类

  • 创建自定义异常类BusinessException

BusinessException自定义异常类将继承RuntimeException异常,该异常类用于处理在程序代码运行过程所产生的运行时业务异常信息。

  • 创建响应枚举类JsonResponseStatus

JsonResponseStatus响应枚举类用于自定义错误码。

  • 创建响应封装类JsonResponseBody

JsonResponseBody响应封装类用于以JSON的形式统一输出错误信息。

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

根据传入的异常对象进行类型判断,并返回相应的响应结果。

部分方法测试

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/83968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git提示:remote origin already exists

目录 问题场景 问题原因 问题解决 问题场景 在GitLab中新建仓库后&#xff0c;然后将本地项目提交提示&#xff1a;remote origin already exists. 问题原因 error: remote origin already exists. 错误&#xff1a;远程源点已存在&#xff08;翻译&#xff09; 出现该错误的…

AI AIgents时代-(四.)应用上手

HuggingGPT & MetaGPT . &#x1f7e2; HuggingGPT HuggingGPT是一个多模型调用的 Agent 框架&#xff0c;利用 ChatGPT 作为任务规划器&#xff0c;根据每个模型的描述来选择 HuggingFace 平台上可用的模型&#xff0c;最后根据模型的执行结果生成总结性的响应。 这个项…

软件测试 —— 答疑篇

什么是软件测试&#xff1a; 软件测试是不是就是找 bug &#xff1f; 软件测试就是证明软件不存在错误的过程 软件测试就是为了证明程序能够正确运行 刚新买来一部手机&#xff0c;我们要干什么&#xff1f; 一场考试 , 做完一遍题目之后 , 进行一遍检查 , 就是在 "…

【LeetCode热题100】--560.和为K的子数组

560.和为K的子数组 示例2的结果&#xff1a; 输入&#xff1a;nums [1,2,3] ,k3的时候 连续子数组有[1,2],[3]&#xff0c;一共有2个 利用枚举法&#xff1a; 枚举[0,…i]里所有的下标j来判断是否符合条件 class Solution {public int subarraySum(int[] nums, int k) {i…

不得不爱的AI艺术写真头像二维码生成小程序开发

最近什么最火&#xff1f;AI最火&#xff01; AI里什么最火&#xff1f;艺术写真生成和二维码美化最火。 一款小程序集合了高还原度的AI写真艺术照和二维码美化&#xff0c;你们说香还是不香&#xff1f; 并且加入了输入心愿就能生成独一无二的个性头像功能&#xff0c;直接…

uniapp 轮播列表左右滑动,滑动到中间放大

html <!-- 轮播 --><view class"heade"><swiper class"swiper" display-multiple-items3 circulartrue previous-margin1rpxnext-margin1rpx current0 change"swiperChange" ><block v-for"(item,index) in list"…

【面试经典150 | 数组】删除有序数组中的重复项 II

文章目录 写在前面Tag题目解读题目来源解题思路方法一&#xff1a;原地操作 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等…

淘宝拍立淘插件转链和商业化图片生成接口介绍,图片搜索商品接口,按图搜索接口,图片识别商品接口介绍

淘宝拍立淘是淘宝网推出的一种搜索方式&#xff0c;通过拍立淘&#xff0c;用户可以输入文字描述或上传图片来搜索商品。拍立淘通过与淘宝网进行数据接入和授权&#xff0c;使用淘宝提供的API获取商品信息和操作权限&#xff0c;拍立淘使用图像识别技术&#xff0c;通过深度学习…

在gazebo仿真环境中加载多个机器人

文章目录 前言一、基本概念1、xacro2、Gazebo 加载单个机器人模型 二、原先launch文件代码三、 修改launch文件加载多个机器人总结 前言 单个机器人的各项仿真实验都基本完成&#xff0c;也实现了远程控制&#xff0c;接下来主要对多机器人编队进行仿真实验&#xff0c;在进行…

Flutter与Native通信原理剖析与实践

通信原理 我们分几种场景来介绍Flutter和Native之间的通信。 Native发送数据给FlutterFlutter发送数据给NativeFlutter发送数据给Native&#xff0c;然后Native回传数据给Flutter Flutter与Native通信机制 在讲解Flutter与Native之间是如何传递数据之前&#xff0c;我们先了…

全新运营策略+针对性落地方案,尖庄·荣光成都战略高地市场打造范式“曝光”

执笔 | 姜 姜 编辑 | 萧 萧 9月19日&#xff0c;“百年尖庄 荣光征程”尖庄荣光上市会成都站在成都举行&#xff0c;现场超600位成都各区县优质经销商、终端商共同举杯尖庄荣光&#xff0c;品味香飘百年的匠心味道。 长江酒道注意到&#xff0c;此次发布会是川渝地区首场…

聊聊Spring中循环依赖与三级缓存

先看几个问题 什么事循环依赖&#xff1f;什么情况下循环依赖可以被处理&#xff1f;spring是如何解决循环依赖的&#xff1f; 什么是循环依赖&#xff1f; 简单理解就是实例 A 依赖实例 B 的同时 B 也依赖了 A Component public class A {// A 中依赖 BAutowiredprivate B b…

从零开始学习 Java:简单易懂的入门指南之Stream流(二十七)

Stream流 Stream流1.体验Stream流2.Stream流的常见生成方式3.Stream流中间操作方法4.Stream流终结操作方法5.Stream流的收集操作6.Stream流综合练习 Stream流 1.体验Stream流 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素把集合中…

Twitter账号优化:吸引更多关注与互动

创建Twitter账号并进行优化 优化你的 Twitter 个人数据有助于提高企业的可视性并促进与用户的互动。通过与其他社交媒体页面的相互协调&#xff0c;你还可以建立一个专业且一致的品牌形象。 创建一个标准的 Twitter 个人数据非常简单&#xff0c;但为了优化它适应您的业务需求…

C++项目中mysql的环境配置与连接

第一步创建好项目&#xff0c;选择X64架构 此次项目采用动态库在项目文件夹加入mysql的库分别为libmysql.dll和include 在包含目录中填入相对路径 添加附加依赖项 现在我们写一个开发环境验证代码&#xff0c;检查一下环境是否配置成功 运行代码前确保MYSQL服务打开 F7生成此时…

78. 子集

题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 思路&#xff1a; 如果把 子集问题、组合问题、分割问题都抽象为一棵树的话&#xff0c;那么组合问题和分割问题都是收集树的叶子节点&#xff0c;而子集问题是找树的所有节点…

flutter简单的本地草稿箱功能

需求1&#xff1a;发帖退出时提示是否保存草稿 需求2&#xff1a;每条草稿中可以保存多张图片(最多9张)或一条视频及三十来个其它参数 需求3&#xff1a;每条草稿都是可以被覆盖的、可以点击删除 需求4&#xff1a;草稿页面可以一键清空 需求5&#xff1a;草稿随app删除一起没掉…

利用免费的敏捷研发管理工具管理端到端敏捷研发流程

Leangoo领歌是Scrum中文网&#xff08;scrum.cn&#xff09;旗下的一款永久免费的敏捷研发管理工具。 Leangoo领歌覆盖了敏捷研发全流程&#xff0c;它提供端到端敏捷研发管理解决方案&#xff0c;包括小型团队敏捷开发&#xff0c;规模化敏捷SAFe&#xff0c;Scrum of Scrums…

D. Boris and His Amazing Haircut

Problem - D - Codeforces 问题描述&#xff1a;剪发&#xff0c;将数组a减为数组b&#xff0c;有m个剪刀&#xff0c;每个剪刀只可以用一次且可以在任意区间内剪发&#xff0c;将长度大于mi的减为mi。现在有m数组&#xff0c;数组元素是第i个剪刀可以剪到mi&#xff0c;问能否…

项目运行报错:error:0308010C:digital envelope routines::unsupported

node版本升到18之后&#xff0c;运行老项目报错 运行命令&#xff1a;npm run dev 解决办法&#xff1a; 第一步&#xff1a;在运行命令中补充set NODE_OPTIONS–openssl-legacy-provider & 第二步&#xff1a;如果依然报错&#xff0c;在终端中运行set NODE_OPTIONS–ope…