validation校验
springboot的validation
校验实践,在实体类属性上添加validation
注解,并在controller中进行验证
实体类
partPostId、zymcId属性上添加了校验注解
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.train.config.JsonStringListTypeHandler;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.github.yulichang.annotation.EntityMapping;
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
import java.util.List;
@Data
@TableName(value = "ksgl_exam_info",autoResultMap = true)
@EqualsAndHashCode(callSuper = true)
@Schema(description = "组卷信息表")
public class KsglExamInfoEntity extends Model<KsglExamInfoEntity>{
/**
* 组卷名称
*/
@Schema(description="组卷名称")
private String examInfoName;
/**
* 参与组织id
*/
@Schema(description="参与组织id")
private String partOrgId;
/**
* 参与组织名称
*/
@Schema(description="参与组织名称")
private String partOrgName;
/**
* 参与岗位id
*/
@TableField(typeHandler = JsonStringListTypeHandler.class)
@Schema(description="参与岗位id")
@NotEmpty(message = "岗位id不能为空")
//@NotBlank限定了集合内的元素也不能为空
private List<@NotBlank(message = "岗位id不能为空") String> partPostId;
/**
* 参与岗位名称
*/
@TableField(typeHandler = JsonStringListTypeHandler.class)
@Schema(description="参与岗位名称")
private List<String> partPostName;
/**
* 专业名称业务id
*/
@Schema(description="专业名称业务id")
@TableField(typeHandler = JsonStringListTypeHandler.class)
@NotEmpty(message = "专业名称id不能为空")
//@NotBlank限定了集合内的元素也不能为空
private List<@NotBlank(message = "专业名称id不能为空")String> zymcId;
/**
* 专业名称
*/
@Schema(description="专业名称")
@TableField(typeHandler = JsonStringListTypeHandler.class)
private List<String> zymcName;
}
无注解使用校验
第一种,Controller不使用@Validated、@Valid等校验注解,直接在代码内使用
Validator
进行校验并将结果进行返回
import javax.validation.Validation;
import javax.validation.Validator;
@RestController
@RequestMapping("/ksglExamInfo" )
public class KsglExamInfoController {
@PostMapping
public R save(@RequestBody KsglExamInfoEntity ksglExamInfo) {
//通过工厂获取校验类,直接通过Validators进行校验
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Object>> violations = validator.validate(ksglExamInfo);
if (!violations.isEmpty()) {
Set<String> messageSet = violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());
return R.failed(String.join(",",messageSet));
}
return R.ok(ksglExamInfoService.saveDeep(ksglExamInfo));
}
}
当传入的json的岗位id、专业名称id为空时
{
"examInfoName": "心灵杀手2",
"partOrgId": "0001A110000000001JKL/1001A11000000000131I/1001A11000000000132Q/1001A110000000001GHF/1001A110000000001GS0/1001A110000000001JPW",
"partOrgName": "迁安市线材有限责任公司/炼铁厂/炼铁一车间/3#高炉/运转工段/运转班",
"partPostName": ["水泵工(女)"],
"partPostId": [""],
"zymcId": [""],
"zymcName": ["设备类"]
}
返回错误信息
{
"code": 1,
"msg": "岗位id不能为空,专业名称id不能为空",
"data": null,
"ok": false
}
有注解使用校验
第二种,Controller使用@Validated、@Valid等校验注解,加在方法参数上
使用注解时,确保pom中有如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
import com.pig4cloud.pigx.common.excel.kit.Validators;
@RestController
@RequestMapping("/ksglExamInfo" )
public class KsglExamInfoController {
@PostMapping
public R save(@RequestBody @Valid KsglExamInfoEntity ksglExamInfo) {
return R.ok(ksglExamInfoService.saveDeep(ksglExamInfo));
}
}
当传入的json的岗位id、专业名称id为空时
{
"examInfoName": "心灵杀手2",
"partOrgId": "0001A110000000001JKL/1001A11000000000131I/1001A11000000000132Q/1001A110000000001GHF/1001A110000000001GS0/1001A110000000001JPW",
"partOrgName": "迁安市线材有限责任公司/炼铁厂/炼铁一车间/3#高炉/运转工段/运转班",
"partPostName": ["水泵工(女)"],
"partPostId": [""],
"zymcId": [""],
"zymcName": ["设备类"]
}
返回错误信息
{
"code": 1,
"msg": "partPostId[0] 岗位id不能为空",
"data": null,
"ok": false
}
这里如果岗位id、专业名称id都为空,则只会随机返回一个校验出错的提示信息。但是,在自定义的message前,会带一个字段英文名提示且无法去掉
,如上面的partPostId[0]
注解加全局异常处理(推荐)
Controller方法参数添加校验注解,并结合ControllerAdvice全局异常处理
处理类Handler
import cn.hutool.core.collection.CollUtil;
import com.pig4cloud.pigx.common.core.util.R;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 处理整个web controller的参数校验
*
* */
@ControllerAdvice
public class ValidExceptionHandler {
//处理方法参数加 @Valid 或 @Validated 的
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public R handlerMethodArgumentNotValidException(MethodArgumentNotValidException e){
BindingResult bindingResult = e.getBindingResult();
if (bindingResult.hasErrors()){
return R.failed(
bindingResult.getAllErrors().stream()
.map(error ->error.getDefaultMessage()).collect(Collectors.joining(",")));
}
return null;
}
//处理方法参数加 @NotBlank、@NotNull 之类的
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public R handlerConstraintViolationException(ConstraintViolationException e){
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
if (CollUtil.isNotEmpty(constraintViolations)){
return R.failed(
constraintViolations.stream().map(violation -> violation.getMessage()).collect(Collectors.joining(","))
);
}
return null;
}
}
上面Handler的
handlerMethodArgumentNotValidException
方法,用于处理下面的Controller校验,参数要加@Valid
或者@Validated
@RestController
@RequestMapping("/ksglExamInfo" )
public class KsglExamInfoController {
@PostMapping
public R save(@RequestBody @Valid KsglExamInfoEntity ksglExamInfo) {
return R.ok(ksglExamInfoService.saveDeep(ksglExamInfo));
}
}
当传入的json的岗位id、专业名称id为空时
{
"examInfoName": "心灵杀手2",
"partOrgId": "0001A110000000001JKL/1001A11000000000131I/1001A11000000000132Q/1001A110000000001GHF/1001A110000000001GS0/1001A110000000001JPW",
"partOrgName": "迁安市线材有限责任公司/炼铁厂/炼铁一车间/3#高炉/运转工段/运转班",
"partPostName": ["水泵工(女)"],
"partPostId": [""],
"zymcId": [""],
"zymcName": ["设备类"]
}
返回错误信息
{
"code": 1,
"msg": "专业名称id不能为空,岗位id不能为空",
"data": null,
"ok": false
}
上面Handler的
handlerConstraintViolationException
方法,用于处理类似下面的Controller校验,参数加的是@NotBlank
或者@NotNull
,且Controller类上要加@Validated
@RestController
@RequestMapping("/ksglExamInfo" )
@Validated
public class KsglExamInfoController {
@GetMapping("/startExam")
public R startExam(@RequestParam @NotBlank(message = "考试id不能为空") String examId,@RequestParam @NotBlank(message = "工号不能为空") String userId){
if(examId.startsWith("XXEXAM")){
return examInfoByXxrw.getQuestionById(examId,userId);
}else{
return examInfoByNormal.getQuestionById(examId,userId);
}
}
}
如果不传任何参数,返回:
{
"code": 1,
"msg": "工号不能为空,考试id不能为空",
"data": null,
"ok": false
}