Spring REST:异常处理卷。 2

这是有关使用Spring进行REST异常处理的系列的第二篇文章。 在我以前的文章中,我描述了如何在REST服务中组织最简单的异常处理。 这次,我将更进一步,我将向您展示何时最好@ControllerAdvice级别使用异常处理Spring异常处理

介绍

在开始本文的技术部分之前,我需要考虑一种情况,那就是我们最好在@ControllerAdvice级别上使用异常处理。
通常,一个控制器负责与一种类型的实体相关的整个逻辑。 就是说,如果我有一些EntityController类,它将包含与实体有关的所有CRUD(创建,读取,更新,删除)操作,如果需要的话,还可能包含一些额外的逻辑。 让我们检查三个操作:读取,更新,删除。

读取操作会根据ID(我们将其作为参数传递给它)返回一些特定的实体。 如果实体不存在,则读取操作将返回null。 更新/删除操作分别更新/删除特定实体。 这两个操作中的每一个都包含读取操作,因为在更新/删除实体之前,我们需要确保其存在于系统中。

在更新/删除操作过程中未找到实体时,应用程序将抛出EntityNotFoundException异常。 在这种情况下,异常处理将非常简单。 该应用程序必须将信息返回给客户端:

  • 响应标题:404
  • 导致异常的链接
  • 错误消息:没有ID为N的实体

对于此类异常,这是最简单的响应结构。 因此,无论您在一个应用程序中有多少个不同的实体类,因为您可以用相同的方式处理类似类型的异常(例如,没有此类实体)。 @ControllerAdvice批注使这成为可能。

@ControllerAdvice级别的异常处理

本文的实际部分将基于上一教程的申请表。

首先,我需要在message.properties文件中添加一条错误消息:

error.no.smartphone.id = There is no Smartphone with id:

之后,让我们看一下本文主题中对我们来说有趣的控制器方法。

...@RequestMapping(value="/edit/{id}", method=RequestMethod.GET)public ModelAndView editSmartphonePage(@PathVariable int id) {ModelAndView mav = new ModelAndView("phones/edit-phone");Smartphone smartphone = smartphoneService.get(id);mav.addObject("sPhone", smartphone);return mav;}@RequestMapping(value="/edit/{id}", method=RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.APPLICATION_JSON_VALUE)@ResponseBodypublic Smartphone editSmartphone(@PathVariable int id, @Valid @RequestBody Smartphone smartphone) {smartphone.setId(id);return smartphoneService.update(smartphone);}
...@RequestMapping(value="/delete/{id}", method=RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.APPLICATION_JSON_VALUE)@ResponseBodypublic Smartphone deleteSmartphone(@PathVariable int id) {return smartphoneService.delete(id);}
...

这些方法包括SmartphoneService的调用。 而且SmartphoneService的实现包含可以引发SmartphoneNotFoundException的方法

@Service
@Transactional(rollbackFor = { SmartphoneNotFoundException.class })
public class SmartphoneServiceImpl implements SmartphoneService {@Autowiredprivate SmartphoneRepository smartphoneRepository;@Overridepublic Smartphone create(Smartphone sp) {return smartphoneRepository.save(sp);}@Overridepublic Smartphone get(Integer id) {Smartphone sp = null;if (id instanceof Integer)sp = smartphoneRepository.findOne(id);if (sp != null)return sp;throw new SmartphoneNotFoundException(id);}@Overridepublic List getAll() {return smartphoneRepository.findAll();}@Overridepublic Smartphone update(Smartphone sp) {Smartphone sPhoneToUpdate = get(sp.getId());sPhoneToUpdate.update(sp);return sPhoneToUpdate;}@Overridepublic Smartphone delete(Integer id) {Smartphone sPhone = get(id);smartphoneRepository.delete(id);return sPhone;}}

这是SmartphoneNotFoundException的代码:

public class SmartphoneNotFoundException extends RuntimeException {private static final long serialVersionUID = -2859292084648724403L;private final int smartphoneId;public SmartphoneNotFoundException(int id) {smartphoneId = id;}public int getSmartphoneId() {return smartphoneId;}}

最后,我可以移至@ControllerAdvice

@ControllerAdvice
public class RestExceptionProcessor {@Autowiredprivate MessageSource messageSource;@ExceptionHandler(SmartphoneNotFoundException.class)@ResponseStatus(value=HttpStatus.NOT_FOUND)@ResponseBodypublic ErrorInfo smartphoneNotFound(HttpServletRequest req, SmartphoneNotFoundException ex) {Locale locale = LocaleContextHolder.getLocale();String errorMessage = messageSource.getMessage("error.no.smartphone.id", null, locale);errorMessage += ex.getSmartphoneId();String errorURL = req.getRequestURL().toString();return new ErrorInfo(errorURL, errorMessage);}}

异常处理程序方法返回ErrorInfo对象。 您可以在上一则有关@Controller级别的异常处理的文章中了解有关它的更多信息。

这样,我们只需将额外的异常类添加到@ExceptionHandler批注中,就可以在一个地方收集所有类似的异常。 这种方法使整个应用程序内的代码维护更加容易。

示例说明:

Spring异常处理ControllerAdvice-1

注意:我发出了id值为356的请求,但是数据库中没有任何记录与此ID值相对应。 这种情况导致异常。

参考: Spring REST:异常处理卷。 2来自我们的JCG合作伙伴 Alexey Zvolinskiy,在Fruzenshtein的笔记博客中。

翻译自: https://www.javacodegeeks.com/2013/11/spring-rest-exception-handling-vol-2.html

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

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

相关文章

python 装饰器有哪些_python装饰器有什么用

简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。 一般而言,我们要想拓展原来函数代码&…

linux中查看相关日志记录,linux重启查看日志及历史记录 查询原因

linux系统文件通常在/var/log中下面是对下面常出现的文件进行解释/var/log/message ---------------------------------------系统启动后的信息和错误日志/var/log/secure ------------------------------------------与安全相关的日志信息/var/log/maillog ------------------…

04,认证、权限、频率

认证组件 Django原生的authentic组件为我们的用户注册与登录提供了认证功能,十分的简介与强大。同样DRF也为我们提供了认证组件,一起来看看DRF里面的认证组件是怎么为我们工作的!models.py# 定义一个用户表和一个保存用户Token的表 class Use…

jq获取input选取的文件名_tushare获取交易数据并可视化分析

获取数据是金融量化分析的第一步,找不到可靠、准确的数据,量化分析就无从谈起。随着信息技术的不断发展,数据获取渠道也越来越多,尤其是Python网络爬虫,近几年愈来愈火。然而,很多人毕竟精力有限&#xff0…

原来游戏技术行业最大的秘密竟然是...

欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云发表于云社区专栏 本篇文章主要是分享游戏业务面临的安全风险场景,以及基于这些场景的特点,我们应该如何做好对应的防护。 【一、背景:游戏行业DDoS攻击…

指定Gradle构建属性

属性是用于轻松自定义Gradle构建和Gradle环境的宝贵工具。 我将在本文中演示一些用于指定Gradle构建中使用的属性的方法。 Gradle支持项目属性和系统属性 。 这篇文章中有趣的是两者之间的主要区别是如何访问它们。 通过常规Java / Groovy系统属性访问方法访问系统属性时&…

python数字转中文字符_Python实现中文数字转换为阿拉伯数字的方法示例

本文实例讲述了Python实现中文数字转换为阿拉伯数字的方法。分享给大家供大家参考,具体如下: 一、需求 今天写了三千二百行代码。 今天写了3200行代码。 两行意思相同,只是表达方式不太能够,统一掉。 二、原理 数字的特征是 数字 …

高级cmd攻击命令_一步一步学习DVWA渗透测试(Command Injection命令行注入)-第七次课...

各位小伙伴,今天我们继续学习Command Injection,翻译为中文就是命令行注入。是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。在OWASP TOP 10中一种存在注入漏洞,最常见的就是SQL和命令行注入。PHP开发的…

IDEA插件之 CodeGlance

在编辑代码最右侧,显示一块代码小地图 这款插件使用效果图如下,个人感觉还是有点用处,滚动条太小,有这个地图,拖动起来更加方便一点 原文地址:http://tengj.top/2017/02/22/idea1-1/转载于:https://www.cnblogs.com/al…

移动端图片上传方法

移动端图片上传方法 实现效果 文件下载 http://files.cnblogs.com/files/sntetwt/移动端图片上传.rar 实现步骤 一、隐藏<input type"file" id"file" name"Filedata" style"display:none;" accept"image/*" /> 二、…

c语言最大公约数和最小公倍数_五年级奥数课堂之七:公因数和公倍数

乘积尾0的个数公因数和公倍数的基本概念公因数的释义给定若干个整数&#xff0c;如果有一个(些)数是它们共同的因数&#xff0c;那么这个(些)数就叫做它们的公因数。而全部公因数中最大的那个&#xff0c;称为这些整数的最大公因数。公约数与公倍数相反&#xff0c;就是既是A的…

设计模式(五)--工厂模式汇总

LZ想把简单工厂模式、工厂方法模式和抽象工厂模式整理到一篇博文当中&#xff0c;由浅入深&#xff0c;应该能方便理解和记忆&#xff0c;话不多说&#xff0c;进入正题。 一、简单工厂模式 定义&#xff1a;从设计模式的类型上来说&#xff0c;简单工厂模式是属于创建型模式&a…

如何估算内存消耗?

这个故事可以追溯到至少十年之前&#xff0c;当时我第一次接触PHB时遇到一个问题&#xff1a;“在生产部署中&#xff0c;我们需要购买多大服务器”。 我们正在构建的新的&#xff0c;闪亮的系统距离生产开始还有9个月的时间&#xff0c;显然该公司已承诺提供包括硬件在内的整个…

python爬取b站403_Python如何爬取b站热门视频并导入Excel

代码如下 #encoding:utf-8 import requests from lxml import etree import xlwt import os # 爬取b站热门视频信息 def spider(): video_list [] url "https://www.bilibili.com/ranking?spm_id_from333.851.b_7072696d61727950616765546162.3" html requests.g…

使用调试器进行事后跟踪

我最近一直在使用的大多数调试器的好功能是能够在断点上记录信息。 这对理解代码而无需修改是非常有用的&#xff0c;它涉及字节码修改。 让我们考虑一下这种非常琐碎且效率低下的函数实现&#xff0c;以返回斐波那契数列中的第n个数字。 public class Fib {public long fib(…

链表排序c++代码_[链表面试算法](一) 链表的删除-相关题型总结(6题)

在数据结构的最高层抽象里&#xff0c;只有两种结构&#xff0c;数组和链表。这两种结构&#xff0c;是所有其他数据结构实现的基础。队列和栈&#xff0c;可以用链表和数组来实现。图&#xff0c;可以用邻接表和邻接矩阵来实现&#xff0c;其中&#xff0c;邻接表就是链表&…

c语言如何空格键返回主菜单,C语言中scanf函数与空格回车的用法说明

众所周知&#xff0c;C语言中的scanf函数的作用是从标准输入设备(通常是键盘)读取输入值&#xff0c;并存储到参数列表中指针所指向的内存单元。下面从几个方面说一下一些稍微细节的东西。下面的实验都在vc6.0中通过。1、scanf的返回值scanf通常返回的是成功赋值(从标准输入设备…

Linear_algebra_03_矩阵

1. 矩阵的线性运算&#xff1a; 2.1 矩阵的乘法&#xff1a;Xik * Ykj Zij 2.2 矩阵乘法性质&#xff1a; 3.1 矩阵的幂次方运算 3.2 矩阵转置的运算律 3.3 方阵运算 4 分块矩阵的运算 5. 矩阵的初等变换 5.1 单位矩阵I经过一次初等变换所得到的矩阵称为初等矩阵. 5.2 初等矩…

js转json工具_菜鸟丨Egert3D微信小游戏发布与Unity工具使用

本次教程将会为大家介绍Egret3D工具导出Unity场景对象的使用&#xff0c;以及发布微信小游戏流程。让大家对Egret 3D有更加熟悉的了解。需求工具&#xff1a;1、Unity场景导出插件&#xff1b;2、微信开发者工具。导出插件的使用一、打开需要导出的Unity场景&#xff0c;并且把…

OI杂记

从今天开始记录一下为数不多天的OI历程 8.25 上 今天举行了难得的五校联考&#xff0c;模拟noip&#xff0c;题目的解压密码竟然是$aKnoIp2o18$&#xff0c;对你没有看错&#xff01;&#xff01;&#xff01; 7:50老师&#xff1f;啊啊啊啊&#xff0c;收不到题目啊&#xff0…