计算机系统应用教程网站

网站首页 > 技术文章 正文

Springboot validation校验请求参数

btikc 2024-10-13 01:50:46 技术文章 23 ℃ 0 评论

导读

我们开发项目的时候,如何判断请求过来的参数非空,长度大小等情况,是不是在代码里面写非空判断,校验长度,如下代码。


如果这个UserVO这个对象有10个字段都要做非空判断,那么这个代码就会变成很多且非常不优雅,那么我们就要想办法解决这个,因此spring为我们提供了validation框架,在springboot框架使用更加简单,validation框架都是已经整合到springboot中了。

新建一个springboot-validation项目

依赖包如下:

 <!-- 1、依赖springboot包 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/>
    </parent>

    <dependencies>
        <!-- 2、springboot web包,已经整合好了validation框架 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- lombok框架 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

新建一个ResponseVO类

该类是统一返回Json格式封装类,例如要统一返回格式:

{
  "code":"200",         //状态码
  "msg":"操作成功",   //消息
  "data":null             //数据
}

类如下:

/**
 * 统一响应VO
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseVO<T> {
    /**
     * 状态码
     */
    String code;
    /**
     * 状态信息
     */
    String msg;
    /**
     * 返回数据对象
     */
    T data;

    /**
     * 定义一个静态方法,返回成功状态码
     * @return 响应对象
     */
    public static ResponseVO success(){
        return new ResponseVO("200","操作成功",null);
    }

    /**
     * 定义一个静态方法,返回失败状态码,以及指定失败信息
     * @param msg 失败信息
     * @return 响应对象
     */
    public static ResponseVO fail(String msg){
        return new ResponseVO("999",msg,null);
    }
}

新建一个UserVO类

该类就用到了validation框架注解

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Data
public class UserVO {

    @NotBlank(message = "用户名不能为空")
    String userName;

    @NotBlank(message = "密码不能为空")
    @Size(min = 6,message = "密码长度最小六位")
    String password;

    @NotNull(message = "年龄不能为空")
    Integer age;

}

相关注解说明:

@AssertFalse

新建UserController类

@Controller
@Slf4j
public class UserController {

    /**
     * 新增用户对象
     */
    @GetMapping("addUser")
    @ResponseBody
    public ResponseVO addUser(@Validated UserVO userVO){
        log.info("新增用户对象={}",userVO);
        //返回成功状态码
        return ResponseVO.success();
    }
}

@Validated 是必须注解,就是把UserVO对象用validation框架校验参数,当提交数据的时候,会自动校验UserVO里面属性非空注解。

新建SpringBootValidApp启动类

@SpringBootApplication
public class SpringBootValidApp {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootValidApp.class,args);
    }
}

启动服务成功后,浏览器访问地址,设置请求参数空值测试

http://127.0.0.1:8080/addUser?userName=&password=&age=

发现控制台出现以下异常,说明校验生效了

2020-10-23 14:38:49.123  WARN 39904 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 4 errors
Field error in object 'userVO' on field 'password': rejected value []; codes [NotBlank.userVO.password,NotBlank.password,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.password,password]; arguments []; default message [password]]; default message [密码不能为空]
Field error in object 'userVO' on field 'password': rejected value []; codes [Size.userVO.password,Size.password,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.password,password]; arguments []; default message [password],2147483647,6]; default message [密码长度最小六位]
Field error in object 'userVO' on field 'userName': rejected value []; codes [NotBlank.userVO.userName,NotBlank.userName,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.userName,userName]; arguments []; default message [userName]]; default message [用户名不能为空]
Field error in object 'userVO' on field 'age': rejected value [null]; codes [NotNull.userVO.age,NotNull.age,NotNull.java.lang.Integer,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userVO.age,age]; arguments []; default message [age]]; default message [年龄不能为空]]

浏览器页面显示错误信息

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri Oct 23 14:38:49 CST 2020
There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='userVO'. Error count: 4

现在只是看到了校验失败信息,那么如何把错误信息返回到页面当中呢?这个是我们下面要解决的问题

新建一个全局异常类

该异常类核心用到了一个注解:@RestControllerAdvice,该数据就是监听Controller类如果有异常的时候,通知一下,然后使用:@ExceptionHandler,来处理特定异常,从而根据异常对象,解析异常信息,封装成:ResponseVO,返回到客户端。

/**
 * 全局公共异常帮助类
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

	/**
	 *  Get 非body请求 ,用BindException
	 *  @RequestBody @Valid 用MethodArgumentNotValidException
	 *  校验参数异常,显示输出具体字段错误列表
	 */
	@ExceptionHandler(value= {BindException.class,MethodArgumentNotValidException.class})
	public Object validatorbindException(Throwable e,HttpServletRequest req){
		String uri=req.getRequestURI();
		log.error("请求URI={},校验参数不通过",uri);

		BindingResult bindingResult=null;
		if(e instanceof BindException) {
			bindingResult=((BindException)e).getBindingResult();
		}else if(e instanceof MethodArgumentNotValidException) {
			bindingResult=((MethodArgumentNotValidException)e).getBindingResult();
		}
		StringBuilder msg=new StringBuilder("");
		try {
			if(bindingResult.hasErrors()) {
				List<FieldError> fieldErrors=bindingResult.getFieldErrors();
				for (FieldError fieldError:fieldErrors) {
					msg.append(", ").append(fieldError.getDefaultMessage());
					log.error("请求URI={},字段={},校验信息={}",uri,fieldError.getField(),fieldError.getDefaultMessage());
				}
				msg.deleteCharAt(0);
			}
		} catch (Throwable  tx) {
			log.error("转换校验参数异常",tx);
		}
		return  ResponseVO.fail(msg.toString());
	}
}

重新启动服务,重新做以上非空访问测试,页面显示如下信息,证明异常返回页面处理成功

{
  "code":"999",
  "msg":" 密码长度最小六位, 用户名不能为空, 年龄不能为空, 密码不能为空",
   "data":null
}

测试正常数据请求

访问地址:
http://127.0.0.1:8080/addUser?userName=xiaoming&password=123456&age=12
测试结果:
{
  "code":"200",
  "msg":"操作成功",
   "data":null
}

总结

Sringboot validation校验请求参数,大大简化了在代码里面做非空判断,大大的提高了工作效率,即优雅又漂亮的代码,从此再也不用加班了,你Get到了吗?如果有疑问,欢迎大家讨论或者与我沟通。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表