SpringBoot 参数检验Assert使用

Posted liuec1002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot 参数检验Assert使用相关的知识,希望对你有一定的参考价值。

前言

assert:断言是java的一个保留字,用来对程序进行调试,后接逻辑运算表达式,如下:

int a = 0, b = 1;
assert a == 0 && b == 0;
使用方法:javac编译源文件,再java -ea class文件名即可。
在springboot中可以使用spring提供的Assert类的方法对前端来的参数进行校验

Assert断言基本上替换传统的if判断,减少业务参数校验的代码行数,提高程序可读性。

@Validated、@Valid对比及详细用法

前面介绍了Validator框架,还需要Assert吗?
Validator只解决了参数自身的数据校验,解决不了参数和业务数据之间校验

举例:

 @PostMapping(value = "/test")

    public ResponseStandard test(@Validated @RequestBody User user) 
        //通过用户名 查询用户
        User user1 = getUser(user);
        Assert.notNull(user1, "用户不存在(Assert抛出)");
        return ResponseStandard.successResponse("成功");
    


    User  getUser(User user)
        return null;
    


此处user不为空,valiad校验通过,但通过用户名查询,本地用户不存在,为业务校验,抛出异常同时
Assert代码更优雅,更简洁,同样也能实现效果。

详细代码Assert 处理全局异常:

全局处理异常类


import com.andon.springbootdistributedlock.domain.ResponseStandard;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * 2021/11/10
 * <p>
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice //对Controller增强,并返回json格式字符串
public class GlobalExceptionHandler 

    /**
     * 捕获Exception异常,并自定义返回数据
     */
    @ExceptionHandler(Exception.class)
    public ResponseStandard<Object> exception(Exception e, HttpServletRequest request) 
        log.error("request error!! method: uri:", request.getMethod(), request.getRequestURI());
        log.error(getExceptionDetail(e));
        return ResponseStandard.builder().code(-1).message(request.getMethod() + " " + request.getRequestURI() + " " + e.getMessage()).build();
    

  

    /**
     * Assert异常
     */
    @ExceptionHandler(IllegalArgumentException.class, IllegalStateException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseStandard<Object> exception(IllegalArgumentException e,HttpServletRequest request) 
        log.error("request error!! method: uri:", request.getMethod(), request.getRequestURI());
        String message = getExceptionDetail(e);
        String message1 = e.getMessage();
        return ResponseStandard.failureResponse(e.getMessage(),100);
    



    /**
     * 获取代码报错详细位置信息
     */
    public String getExceptionDetail(Exception e) 
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(e.getClass()).append(System.getProperty("line.separator"));
        stringBuilder.append(e.getLocalizedMessage()).append(System.getProperty("line.separator"));
        StackTraceElement[] arr = e.getStackTrace();
        for (StackTraceElement stackTraceElement : arr) 
            stringBuilder.append(stackTraceElement.toString()).append(System.getProperty("line.separator"));
        
        return stringBuilder.toString();
    


返回结果类

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResponseStandard<T> implements Serializable 

    private int code;
    private String message;
    private T data;
    private int total;

    public static <T> ResponseStandard<T> successResponse(T t) 
        ResponseStandard<T> response = new ResponseStandard<>();
        response.setCode(0);
        response.setMessage("success!!");
        response.setData(t);
        response.setTotal(0);
        return response;
    

    public static <T> ResponseStandard<T> failureResponse(T t) 
        ResponseStandard<T> response = new ResponseStandard<>();
        response.setCode(-1);
        response.setMessage("failure!!");
        response.setData(t);
        response.setTotal(0);
        return response;
    

    public static <T> ResponseStandard<T> failureResponse(String msg,int  code) 
        ResponseStandard<T> response = new ResponseStandard<>();
        response.setCode(code);
        response.setMessage(msg);
        response.setData(null);
        response.setTotal(0);
        return response;
    

controller

/**
 * @author liu
 * @date 2022年05月25日 8:58
 */
@Slf4j
@RequestMapping(value = "/ex")
@RestController
public class TestExceptionController 


    @PostMapping(value = "/test")

    public ResponseStandard test(@Validated  @RequestBody User user) 
        //通过用户名 查询用户
        User user1 = getUser(user);
        Assert.notNull(user1, "用户不存在(Assert抛出)");
        return ResponseStandard.successResponse("成功");
    


    User  getUser(User user)
        return null;
    


@Data
public class User

@NotBlank(message = "名字为必填项")
String name;
@Length(min = 8, max = 12, message = "password长度必须位于8到12之间")
String psd;

异常抛出流程:

  1. //通过用户名 查询用户
    User user1 = getUser(user);结果为null
    2. Assert.notNull(user1, “用户不存在(Assert抛出)”); 点进源码:

      public static void notNull(@Nullable Object object, String message) 
     if (object == null) 
         throw new IllegalArgumentException(message);
     
    

    抛出IllegalArgumentException

  2. 全局异常拦截 ` /**

    • Assert异常
      */
      @ExceptionHandler(IllegalArgumentException.class, IllegalStateException.class)
      @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
      public ResponseStandard exception(IllegalArgumentException e,HttpServletRequest request)
      log.error(“request error!! method: uri:”, request.getMethod(), request.getRequestURI());
      String message = getExceptionDetail(e);
      String message1 = e.getMessage();
      return ResponseStandard.failureResponse(e.getMessage(),100);
      `
      ExceptionHandler 拦截IllegalArgumentException 异常 返回ResponseStandard

Assert都有哪些方法

对象和类型断言

函数说明
notNull()假设对象不null
isNull()检查对象为null
isInstanceOf()检查对象必须为另一个特定类型的实例
isAssignable()检查类型

文本断言

函数说明
hasLength()检查字符串不是空符串,意味着至少包含一个空白,可以使用hasLength()方法
hasText()增强检查条件,字符串至少包含一个非空白字符,可以使用hasText()方法
doesNotContain()检查参数不包含特定子串

逻辑断言

函数说明
isTrue()条件为假抛出IllegalArgumentException 异常
state()该方法与isTrue一样,但抛出IllegalStateException异常

Collection和map断言

函数说明
Collection应用notEmpty()Collection不是null并包含至少一个元素
map应用notEmpty()检查map不null,并至少包含一个entry(key,value键值对)

数组断言

函数说明
notEmpty()可以检查数组不null,且至少包括一个元素
noNullElements()确保数组不包含null元素

SpringBoot - 使用Assert校验让业务代码更简洁

文章目录


Pre

SpringBoot - 优雅的实现【参数校验】高级进阶

SpringBoot - 优雅的实现【自定义参数校验】高级进阶

SpringBoot - 优雅的实现【参数分组校验】高级进阶

SpringBoot - 使用Assert校验让业务代码更简洁


有了Validator框架,还要Assert干啥子

简而言之 Validator只解决了参数自身的数据校验,解决不了参数和业务数据之间校验

我们来看个例子


/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */

@RestController
@Slf4j 
@RequestMapping("/assert")
public class ArtisanController 

    @Autowired
    private ArtisanDao artisanDao;

    /**
     * Validator只解决了参数自身的数据校验,解决不了参数和业务数据之间校验
     *
     * @param
     * @return
     */
    @PostMapping("/testNoAssert")
    public void testNoAssert(@RequestParam("artisanId") String artisanId) 
        Artisan artisan = artisanDao.selectArtisanReturnNull(artisanId);

        if (artisan == null) 
            throw new IllegalArgumentException("用户不存在");
        

    


    

非空判断,大家都很熟悉哈


那用Assert怎么写呢?

    /**
     * Validator只解决了参数自身的数据校验,解决不了参数和业务数据之间校验
     *
     * @param
     * @return
     */
    @PostMapping("/testWithAssert")
    public void testWithAssert(@RequestParam("artisanId") String artisanId) 
        Artisan artisan = artisanDao.selectArtisanReturnNull(artisanId);

        Assert.notNull(artisan, "用户不存在(Assert抛出)");

    

是不是发现Assert代码更优雅,更简洁,同样也能实现效果 .

Assert断言基本上替换传统的if判断,减少业务参数校验的代码行数,提高程序可读性,点赞~~~

大家都在用,随便一找,不信你看

【返回结果】

我们看下

抛出的是 IllegalArgumentException,所以全局异常处理一下

    /**
     * Assert异常
     */
    @ExceptionHandler(IllegalArgumentException.class, IllegalStateException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData<String> exception(IllegalArgumentException e) 
        return ResponseData.fail(ResponseCode.ILLEGAL_ARGUMENT.getCode(), e.getMessage());
    

当然了,我这个返回结果是被全局异常处理了的,如果没有全局异常处理,返回的是原生的这种错误


org.springframework.util.Assert

我们看下Assert都有哪些方法

简单分下类

对象和类型断言

函数说明
notNull()假设对象不null
isNull()检查对象为null
isInstanceOf()检查对象必须为另一个特定类型的实例
isAssignable()检查类型

文本断言

函数说明
hasLength()检查字符串不是空符串,意味着至少包含一个空白,可以使用hasLength()方法
hasText()增强检查条件,字符串至少包含一个非空白字符,可以使用hasText()方法
doesNotContain()检查参数不包含特定子串

逻辑断言

函数说明
isTrue()条件为假抛出IllegalArgumentException 异常
state()该方法与isTrue一样,但抛出IllegalStateException异常

Collection和map断言

函数说明
Collection应用notEmpty()Collection不是null并包含至少一个元素
map应用notEmpty()检查map不null,并至少包含一个entry(key,value键值对)

数组断言

函数说明
notEmpty()可以检查数组不null,且至少包括一个元素
noNullElements()确保数组不包含null元素

源码

https://github.com/yangshangwei/boot2

以上是关于SpringBoot 参数检验Assert使用的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot - 使用Assert校验让业务代码更简洁

assert的使用断言

assert函数应用

SpringBoot 如何进行业务校验,老鸟们都这么玩的~

JUnit的断言 Assert

assert()函数用法