SpringBoot中的异常处理与参数校验_2

简介:   兄弟们好,这次来跟老铁交流两个问题,异常和参数校验,在说参数校验之前我们先来说异常处理吧,因为后面参数的校验会牵扯到异常处理这块的内容。  说到异常处理,我不知道大家有没有写过或者遇到过如下的写法。

  兄弟们好,这次来跟老铁交流两个问题,异常和参数校验,在说参数校验之前我们先来说异常处理吧,因为后面参数的校验会牵扯到异常处理这块的内容。

  说到异常处理,我不知道大家有没有写过或者遇到过如下的写法。

  public void saveUser() { try { // 所有的业务内容,目测几百行 }catch (Exception e) { e.printStackTrace(); }}

  如果出现上述的代码,里面包含了大量的业务代码,如果是你写的,赶紧改掉,不是你写的找写的,吐槽赶紧改掉。

  1、会遇到性能瓶颈;2、很难定位问题;3、try嵌套过多可读性很差;

  不管什么原因出现了上述代码,那么最好还是改一下,如果非要在业务代码中try,那么也应该只在可能出现异常的地方使用try,而不是try整个业务代码。

  直接上代码

  @RestControllerAdvicepublic class GlobalException { @ExceptionHandler(value=Exception.class) // 捕获的异常类型 public Object globalException(Exception ex) { // 异常处理 ex.printStackTrace(); return "出现异常"; }}

  那么在SpringBoot中我们就可以通过这样的一个配置可以获取到项目中出现异常的地方,我们可以在这个方法中可以获取出现异常的类的详细信息,那么是不是所有的异常我们全部使用Exception来处理呢?那么肯定是不合适的。

  我们模拟一个by zero的异常,然后再配置一个处理ArithmeticException异常的处理器,代码如下:

  @RestControllerAdvicepublic class GlobalException { @ExceptionHandler(value=Exception.class) // 捕获的异常类型 public Object globalException(Exception ex) { ex.printStackTrace(); return "出现异常"; } @ExceptionHandler(value=ArithmeticException.class) public Object arithmeticException(ArithmeticException ex) { ex.printStackTrace(); return "by zero异常"; }}

  如果这个时候出现by zero异常,走ArithmeticException异常处理,原因就是因为如果有更小范围的异常处理类,那么会走小范围的异常处理器。不会走globalException更大的异常处理类。

  这样处理之后,我们就不需要在项目中去写那么多的try了,是不是方便了很多。

  除了使用这些已经存在的异常外,其实我们还可以自定义我们的异常,比如我们常用的用户未登录异常、参数错误异常等等。但是考虑到这篇文章的篇幅问题,这次就先不写了,有兴趣的朋友可以直接下面留言,人多了我尽快更新。

  这里跟大家分享一个踩过的坑,不能再Filter过滤器中抛出异常,如果通过在过滤器中抛出异常,然后通过异常处理类来处理,那么是不可能的,因为处理器是捕获不到Filter抛出的异常的。

  老规矩,先来看一段代码

  @RequestMapping(value="/save/user")public Object saveUser(UserPO userPO) { if (userPO.getAge()==null) { return "请求参数错误"; } if (userPO.getSex()==null) { return "请求参数错误"; } if (userPO.getUsername()==null) { return "请求参数错误"; } // ... return "SUCCESS";}

  应该见过这种校验参数的吧,说实话我写过。越写感觉越low,所以狠心一下,还是趁早改吧。

  这个注解其实是Spring提供的,如果你的二手项目不是SpringBoot项目,需要引一下需要的pom文件,如果是,那么就不用管了,SpringBoot已经帮我们引入了。

  网上看了好多的博客,许多都说的不是很全,大部分都是说JavaBean参数的校验,但是我们项目中有些接口可能就涉及一个参数,根本不需要写一个JavaBean,对于单一参数的校验好多博客还是没说的,那么我们这次就一次性讲清楚。

  直接看代码吧

  @Validated@RestControllerpublic class BookController { @RequestMapping(value="/book/info", method=RequestMethod.GET) public Object getBookInfo(@NotBlank(message="书籍ID不能为空") String bookId) { return "SUCCESS"; }}

  这里要跟大家特别说明下,如果是单一参数的校验,那么我们必须要在类上面添加@Validated注解,不然我们整个单个参数校验是不会生效的,可以看到我们在校验参数bookId的时候,使用了@NotBlank那么顾名思义,就是这个参数不能为null,在调用了trim()方法之后也不能是空字符。

  如果参数不满足要求,那么会抛出

  ConstraintViolationException异常,这个异常只有在单一参数校验的时候抛出,如果你的参数是JavaBean,那么就不是这个异常了。

  既然我们知道了它会抛出异常,并且我们也知道是什么异常类型,那么久超级简单了,我们可以直接使用上面刚学的异常处理类来处理我们的异常。

  我找个里面写的比较简单,如果你想写的复杂一点,其实也是可以的,但是作为后端来说,我觉得没必要,因为我们不能给前端提示太过明显的错误提示,防止别人恶意攻击我们,就像用户名密码错误,不能明确的告诉用户到底是用户名错误还是密码错误,只能提示用户名或密码错误。

  如果大家非要把详细的错误信息打出来,要看到到底是哪个参数校验不通过,也可以通过下面的方式将具体的参数错误信息打印出来。输出的错误结果其实就是上面message里面的内容。

  @RestControllerAdvicepublic class ExceptionCatch { /* 单个参数异常处理 @param ex @return / @ExceptionHandler(value=ConstraintViolationException.class) public Object constraintViolationException(ConstraintViolationException ex) { // 获取具体的错误信息 Set> violations=ex.getConstraintViolations(); // 打印数据 violations.forEach(e -> System.out.println(e.getMessage())); return "单个-请求参数错误"; }}

  JavaBean的写法

  @Data@NoArgsConstructor@AllArgsConstructorpublic class UserPO { @NotBlank(message="用户名不能为空") private String username; @NotNull(message="年龄不能为空") @Min(value=1, message="年龄最小为1") @Max(value=200, message="年龄最大为200") private Integer age; @NotBlank(message="性别不能为空") private String sex;}

  Controller写法

  @RequestMapping(value="/save/user")public Object saveUser(@Validated UserPO userPO) { // ... return "SUCCESS";}

  跟单一参数校验不一样的是JavaBean的校验方式需要将@Validated写在方法参数,而不是类上。如果出现了参数校验不通过,同样的也会抛出一个异常,BindException。

  /* 一般参数校验绑定异常处理 @param ex @return /@ExceptionHandler(value=BindException.class)public Object bindException(BindException ex) { BindingResult bindingResult=ex.getBindingResult(); // 获取所有的错误信息 List allErrors=bindingResult.getAllErrors(); // 输出 allErrors.forEach(e -> System.out.println(e.getDefaultMessage())); return "请求参数错误";}

  注意:大家要注意post请求有两种方式,一种是基于form-data格式的数据传递,另外一种就是基于json格式的数据传递,两种传递方式引发的异常也是不一样的,所以我们还要单独处理基于json的参数校验异常处理。

  我们先来看下Controller接收方式

  @RequestMapping(value="/save/user")public Object saveUser(@Validated @RequestBody UserPO userPO) { // ... return "SUCCESS";}

  对应的参数异常处理

  /* JSON参数校验绑定异常处理 @param ex @return /@ExceptionHandler(value=MethodArgumentNotValidException.class)public Object methodArgumentNotValidException(MethodArgumentNotValidException ex) { BindingResult bindingResult=ex.getBindingResult(); // 获取所有的错误信息 List allErrors=bindingResult.getAllErrors(); // 输出 allErrors.forEach(e -> System.out.println(e.getDefaultMessage())); return "请求参数错误-json";}

  那么到这里,我们本篇文章就结束了,主要介绍了两部分内容,异常的处理和参数的校验。虽然很简单,但是我个人感觉还是挺常用的技能。所以与大家进行分享,如果对你有点帮助,就来点个赞吧。如果有什么不明白的也欢迎下方留言,一起来交流。

目录
相关文章
|
6月前
|
监控 数据可视化 数据挖掘
Python Rich库使用指南:打造更美观的命令行应用
Rich库是Python的终端美化利器,支持彩色文本、智能表格、动态进度条和语法高亮,大幅提升命令行应用的可视化效果与用户体验。
526 0
|
8月前
|
前端开发 Java 数据库连接
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
|
Java Spring
SpringBoot 实战 不同参数调用不同实现
本文介绍了如何在实际工作中根据不同的入参调用不同的实现,采用`map+enum`的方式实现优雅且严谨的解决方案。通过Spring Boot框架中的工厂模式或策略模式,避免了使用冗长的`if...else...`语句。文中详细展示了定义接口、实现类、枚举类以及控制器调用的代码示例,确保用户输入的合法性并简化了代码逻辑。
500 1
SpringBoot 实战 不同参数调用不同实现
|
缓存 Shell 开发工具
[oeasy]python064_命令行工作流的总结_vim_shell_python
本文总结了命令行工作流中的关键工具和操作,包括vim、shell和Python。主要内容如下: 1. **上次回顾**:完成了输入输出的代码编写,并再次练习了vim的使用。 2. **shell基础**:介绍了shell环境及其基本命令,如`pwd`、`cd`、`ll -l`等。 3. **Python游乐场**:通过`python3`命令进入Python交互环境,可以进行简单计算和函数调用,常用函数有`help`、`ord`、`chr`等。 4. **vim编辑器**:详细讲解了vim的三种模式(正常模式、插入模式、底行命令模式)及其切换方法,以及常用的底行命令如`:w`、`:q`、`
261 15
|
Windows Python
【10月更文挑战第2天】「Mac上学Python 2」入门篇2 - 开发环境命令行操作与文件管理
本篇将详细介绍Windows和Mac系统中的常用命令行操作与文件管理,帮助用户掌握如何通过终端或命令提示符进行文件管理和操作开发环境。内容涵盖路径切换、文件与文件夹的创建、删除、查看文件内容等基本操作,这些技能是后续Python开发的基础。
403 6
【10月更文挑战第2天】「Mac上学Python 2」入门篇2 - 开发环境命令行操作与文件管理
|
JSON 前端开发 Java
Spring MVC——获取参数和响应
本文介绍了如何在Spring框架中通过不同的注解和方法获取URL参数、上传文件、处理cookie和session、以及响应不同类型的数据。具体内容包括使用`@PathVariable`获取URL中的参数,使用`MultipartFile`上传文件,通过`HttpServletRequest`和`@CookieValue`获取cookie,通过`HttpSession`和`@SessionAttribute`获取session,以及如何返回静态页面、HTML代码片段、JSON数据,并设置HTTP状态码和响应头。
312 1
Spring MVC——获取参数和响应
|
缓存 前端开发 Java
springboot 的单体服务 字典参数转译
本文介绍了如何在Spring Boot项目中使用缓存来管理字典参数,并确保前后端数据一致性。首先,通过`@EnableCaching`启用缓存功能,接着创建一个自定义的字典缓存类`DicCache`。然后,通过配置类将`DicCache`添加到`cacheManager`中。此外,对字典服务进行改造,使用`@CachePut`和`@CacheEvict`注解保证数据一致性。最后,实现自定义注解`@DicSerializer`和序列化处理类`DictSerializerHandel`,用于在序列化过程中自动转换字典值。通过这种方式,可最小化代码改动并提高系统性能。
503 6
springboot 的单体服务 字典参数转译
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
190 2
|
前端开发 Java Spring
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
470 2
|
JSON Java 数据格式
springboot 参数统一处理
springboot 参数统一处理
234 2

推荐镜像

更多