SpringBoot中的异常处理与参数校验的方法实现

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

异常处理

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

public void saveUser() {

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

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

存在的问题:

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

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

SpringBoot中的异常捕获

直接上代码

@RestControllerAdvice
public class GlobalException {

  @ExceptionHandler(value = Exception.class) // 捕获的异常类型
  public Object globalException(Exception ex) {

    // 异常处理
    ex.printStackTrace();

    return "出现异常";
  }
}

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

@RestControllerAdvice
public 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,所以狠心一下,还是趁早改吧。

@Validated注解

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

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

单一参数的校验

直接看代码吧

@Validated
@RestController
public 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里面的内容。

@RestControllerAdvice
public class ExceptionCatch {
  /**
   * 单个参数异常处理
   *
   * @param ex
   * @return
   */
  @ExceptionHandler(value = ConstraintViolationException.class)
  public Object constraintViolationException(ConstraintViolationException ex) {

    // 获取具体的错误信息
    Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
    // 打印数据
    violations.forEach(e -> System.out.println(e.getMessage()));

    return "单个-请求参数错误";
  }
}

JavaBean参数校验(form-data)

JavaBean的写法

@Data
@NoArgsConstructor
@AllArgsConstructor
public 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<ObjectError> allErrors = bindingResult.getAllErrors();

  // 输出
  allErrors.forEach(e -> System.out.println(e.getDefaultMessage()));

  return "请求参数错误";
}

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

JavaBean参数校验(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<ObjectError> allErrors = bindingResult.getAllErrors();

  // 输出
  allErrors.forEach(e -> System.out.println(e.getDefaultMessage()));

  return "请求参数错误-json";
}

最后的话

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

到此这篇关于SpringBoot中的异常处理与参数校验的方法实现的文章就介绍到这了,更多相关SpringBoot 异常处理与参数校验内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring boot进行参数校验的方法实例详解

    Spring boot开发web项目有时候我们需要对controller层传过来的参数进行一些基本的校验,比如非空.整数值的范围.字符串的长度.日期.邮箱等等.Spring支持JSR-303 Bean Validation API,可以方便的进行校验. 使用注解进行校验 先定义一个form的封装对象 class RequestForm { @Size(min = 1, max = 5) private String name; public String getName() { return n

  • 详解如何在Spring Boot项目使用参数校验

    开发web项目有时候我们需要对controller层传过来的参数进行一些基本的校验,比如非空,非null,整数值的范围,字符串的个数,日期,邮箱等等.最常见的就是我们直接写代码校验,这样以后比较繁琐,而且不够灵活. Bean Validation 1.0(JSR-303)是一个校验规范,在spring Boot项目由于自带了hibernate validator 5(http://hibernate.org/validator/)实现,所以我们可以非常方便的使用这个特性 . 核心的pom依赖:

  • springboot全局异常处理详解

    一.单个controller范围的异常处理 package com.xxx.secondboot.web; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import

  • SpringBoot错误处理机制以及自定义异常处理详解

    上篇文章我们讲解了使用Hibernate Validation来校验数据,当校验完数据后,如果发生错误我们需要给客户返回一个错误信息,因此这节我们来讲解一下SpringBoot默认的错误处理机制以及如何自定义异常来处理请求错误. 一.SpringBoot默认的错误处理机制 我们在发送一个请求的时候,如果发生404 SpringBoot会怎么处理呢?我们来发送一个不存在的请求来验证一下看看页面结果.如下所示: 当服务器内部发生错误的时候,页面会返回什么呢? @GetMapping("/user/{

  • SpringBoot如何优雅的处理全局异常

    前言 本篇文章主要介绍的是SpringBoot项目进行全局异常的处理. SpringBoot全局异常准备 说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码. 开发准备 环境要求 JDK:1.8 SpringBoot:1.5.17.RELEASE 首先还是Maven的相关依赖: <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.

  • SpringBoot初始教程之统一异常处理详解

    1.介绍 在日常开发中发生了异常,往往是需要通过一个统一的异常处理处理所有异常,来保证客户端能够收到友好的提示.SpringBoot在页面发生异常的时候会自动把请求转到/error,SpringBoot内置了一个BasicErrorController对异常进行统一的处理,当然也可以自定义这个路径 application.yaml server: port: 8080 error: path: /custom/error BasicErrorController提供两种返回错误一种是页面返回.当

  • 详解Springboot自定义异常处理

    背景 Springboot 默认把异常的处理集中到一个ModelAndView中了,但项目的实际过程中,这样做,并不能满足我们的要求.具体的自定义异常的处理,参看以下 具体实现 如果仔细看完spring boot的异常处理详解,并且研究过源码后,我觉得具体的实现可以不用看了... 重写定义错误页面的url,默认只有一个/error @Bean public EmbeddedServletContainerCustomizer containerCustomizer(){ return new E

  • Spring Boot实现通用的接口参数校验

    本文介绍基于 Spring Boot 和 JDK8 编写一个 AOP ,结合自定义注解实现通用的接口参数校验. 缘由 目前参数校验常用的方法是在实体类上添加注解,但对于不同的方法,所应用的校验规则也是不一样的,例如有一个 AccountVO 实体: public class AccountVO { private String name; // 姓名 private Integer age; // 年龄 } 假设存在这样一个业务:用户注册时需要填写姓名和年龄,用户登陆时只需要填写姓名就可以了.那

  • SpringBoot添加Email发送功能及常见异常详解

    1.完整的邮件发送代码 1.1.依赖包 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-support</artifactId> <version>2.0.8</version> <exclusions> <exclusion> <groupId>javax.servlet</groupI

  • Spring Boot全局异常处理解析

    本文为大家分享了Spring Boot全局异常处理,供大家参考,具体内容如下 1.后台处理异常 a.引入thymeleaf依赖 <!-- thymeleaf模板插件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>

  • Spring Boot统一异常处理详解

    Spring Boot中默认带了error的映射,但是这个错误页面显示给用户并不是很友好. 统一异常处理 通过使用@ControllerAdvice定义统一异常处理的类,而不是在每个Controller中逐个定义. @ExceptionHandler用来定义函数针对的函数类型,最后将Exception对象和请求URL映射到URL中. @ControllerAdvice class ExceptionTranslator { public static final String DEFAULT_E

  • Spring Boot 参数校验的具体实现方式

    1.背景介绍 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还挺工整的,只是看起来不是很优雅而已. 接下来,用Validation来改写这段 2.Spring Boot文档中的Validation 在Spring Boot的官网中,关于Validation只是简单的提了一句,如下 其实,Spring Validator和Hibernate Validator是两套Validator,可以混着用,这里我们用Hibernate Validator 3.

随机推荐