Springboot 参数校验@Valid @Validated(最新最全)

Springboot 参数校验@Valid @Validated(最新最全)

提示:统一参数校验,异常处理


前言

表单提交,后端做数据校验


一、统一参数校验(普通)

1.引入依赖

提示:实操过程发现,引入validation-api 不好使,需要引入hibernate-validator

依赖如下:

       <!-- 自定义注解
         <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>
         -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>

2.创建Control

如下:

package com.xjw.mytest.control;

import com.alibaba.fastjson.JSONObject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequestMapping("/user")
public class UserControl {

    @PostMapping("/add")
    public R add(@Valid @RequestBody UserDto data) {
        System.out.println("data is "+ JSONObject.toJSONString(data));
        return R.ok();
    }

}

2.创建Advice

如下:

package com.xjw.mytest.control;

import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice(basePackages = "com.xjw")
public class ExceptionControllerAdvice {

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleVaildException(MethodArgumentNotValidException e) {

        BindingResult bindingResult = e.getBindingResult();

        Map<String, String> errorMap = new HashMap<>();

        bindingResult.getFieldErrors().forEach(bean->{
            errorMap.put(bean.getField(), bean.getDefaultMessage());
        });

        return  R.error("400", "数据校验问题").put("data",errorMap);
    }

    @ExceptionHandler(value = Exception.class)
    public R handleVaildException(Exception e) {
        return  R.error("500", "系统内部错误");
    }
}

3.统一返回参数

如下:


package com.xjw.mytest.control;

import java.util.HashMap;
import java.util.Map;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

/**
 * 返回数据
 */
public class R extends HashMap<String, Object> {

	/** 未知异常 **/
	public static final String UN_KNOW_ERROR = "-1";
	
	public static final String SUCCESS_CODE = "200";// 成功
	
	public static final String ERROR_CODE = "500";// 失败


	public static final String MSG_SUCESS = "success";
	public static final String MSG_ERROR = "error";

	public static final String DATA = "data";
	public static final String DATAS = "datas";
	public static final String CODE = "code";
	public static final String MSG = "message";
	private static final long serialVersionUID = 1L;

	public <T> T getData(String key, TypeReference<T> typeReference) {
		Object data = get(key);
		String s = JSON.toJSONString(data);
		return JSON.parseObject(s, typeReference);
	}

	public <T> T getData(TypeReference<T> typeReference) {
		Object data = get(DATA);
		String s = JSON.toJSONString(data);
		return JSON.parseObject(s, typeReference);
	}

	public R setData(Object data) {
		put(DATA, data);
		return this;
	}
	
	public R setDatas(Object data) {
		put(DATAS, data);
		return this;
	}

	public R() {
		put(CODE, SUCCESS_CODE);
		put(MSG, MSG_SUCESS);
	}

	public static R error(String code) {
		return error(code, MSG_ERROR);
	}

	public static R error(String code, String msg) {
		R r = new R();
		r.put(CODE, code);
		r.put(MSG, msg);
		return r;
	}

	public static R ok(String msg) {
		R r = new R();
		r.put(CODE, SUCCESS_CODE);
		r.put(MSG, msg);
		return r;
	}

	public static R ok(Map<String, Object> map) {
		R r = new R();
		r.putAll(map);
		return r;
	}

	public static R ok() {
		R r = new R();
		r.put(CODE, SUCCESS_CODE);
		r.put(MSG, MSG_SUCESS);
		return r;
	}

	public R put(String key, Object value) {
		super.put(key, value);
		return this;
	}

	public Integer getCode() {
		return (Integer) this.get(CODE);
	}

	public String getmsg() {
		return (String) this.getOrDefault(MSG, "");
	}

	public String getcode() {
		return (String) this.getOrDefault(CODE, "");
	}

}

4.创建Dto

如下:

package com.xjw.mytest.control;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;

public class UserDto {

    private String id;
    @NotNull(message = "名称不能为空"})
    private String userName;
    @NotNull(message = "年龄不能为空")
    private Integer age;
    private Integer status;
 }

二、统一参数校验(分组)

提示:就是创建两个空接口

1.创建分组接口

代码如下(示例):

package com.xjw.mytest.control;

public interface AddGroup {
}

package com.xjw.mytest.control;

public interface UpdateGroup {
}


2.创建Control

提示:接口中的注解修改了,修改@Validated(value = {AddGroup.class})
代码如下(示例):

package com.xjw.mytest.control;

import com.alibaba.fastjson.JSONObject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequestMapping("/userGroup")
public class UserGroupControl {

    @PostMapping("/add")
    public R add(@Validated(value = {AddGroup.class}) @RequestBody UserDto data) {
        System.out.println("data is "+ JSONObject.toJSONString(data));
        return R.ok();
    }

    @PostMapping("/update")
    public R update(@Validated(value = {UpdateGroup.class}) @RequestBody UserDto data) {
        System.out.println("data is "+ JSONObject.toJSONString(data));
        return R.ok();
    }

}

3.修改Dto

提示:Dto中的注解修改了,增加了Control
代码如下(示例):

package com.xjw.mytest.control;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;

public class UserDto {

    @NotNull(message = "新增必须为空", groups = {AddGroup.class})
    @Null(message = "更新必须不为空", groups = {UpdateGroup.class})
    private String id;
    @NotNull(message = "名称不能为空", groups = {AddGroup.class, UpdateGroup.class})
    private String userName;
    @NotNull(message = "年龄不能为空",groups = {AddGroup.class, UpdateGroup.class})
    private Integer age;
    private Integer status;
}

二、统一参数校验(自定义注解)

提示:就是创建两个空接口

1.创建注解类

代码如下(示例):

package com.xjw.mytest.control;


import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {

    String message() default "{com.xjw.validation.listValue.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    int[] vals() default {};
}

2.创建校验器

提示:接口中的注解修改了,修改@Validated(value = {AddGroup.class})
代码如下(示例):

package com.xjw.mytest.control;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;

public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {

    private Set<Integer> set = new HashSet<>();

    //初始化方法(设置注解中的只,例如状态(1,2)此时就可以获取注解中的1,2)
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] vals = constraintAnnotation.vals();
        for (int val : vals){
            set.add(val);
        }
    }
    // 校验是否成功
    /**
     * value 就是提交上来的数据
     * @param value object to validate
     * @param context context in which the constraint is evaluated
     *
     * @return
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        return set.contains(value);
    }
}

3.添加配置文件

提示:文件名称ValidationMessages.properties ,路径resources下
代码如下(示例):

com.xjw.validation.listValue.message = 必须提交指定值

3.修改Dto

提示:文件名称ValidationMessages.properties ,路径resources下
代码如下(示例):

package com.xjw.mytest.control;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;

public class UserDto {

    @NotNull(message = "新增必须为空", groups = {AddGroup.class})
    @Null(message = "更新必须不为空", groups = {UpdateGroup.class})
    private String id;
    @NotNull(message = "名称不能为空", groups = {AddGroup.class, UpdateGroup.class})
    private String userName;
    @NotNull(message = "年龄不能为空",groups = {AddGroup.class, UpdateGroup.class})
    private Integer age;

    @ListValue(vals = {1,2}, groups = {AddGroup.class})
    private Integer status;
}


在这里插入图片描述
提示:如果ValidationMessages.properties 中的提示信息乱码,可以如下处理

在这里插入图片描述



总结

例如:以上三种校验规则基本满足日常开发中的各种表单校验规则

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值