導讀
前后端分離項目中,前端往后端傳值時,后端都要做參數格式校驗,比如校驗數字最大值、最小值、是否允許為空、日期格式等等。
添加依賴
<!-- 參數校驗 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
自定義日期注解
作用
校驗日期格式,自定義校驗規格
DateTime.java
package net.ybclass.online_ybclass.utils; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = DateTimeValidator.class) public @interface DateTime { String message() default "日期格式錯誤"; String format() default "yyyyMM"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
約束自定義注解校驗器
作用
校驗自定義注解驗證格式
DateTimeValidator.java
package net.ybclass.online_ybclass.utils; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.text.SimpleDateFormat; /** * @ClassName:DateTimeValidator * @Description:日期校驗器 * @Author:chenyb * @Date:2020/11/17 10:13 上午 * @Versiion:1.0 */ public class DateTimeValidator implements ConstraintValidator<DateTime, String> { private DateTime dateTime; /** * 初始化 * @param dateTime */ @Override public void initialize(DateTime dateTime) { this.dateTime = dateTime; } /** * 驗證參數 * @param value * @param context * @return */ @Override public boolean isValid(String value, ConstraintValidatorContext context) { // 如果 value 為空則不進行格式驗證,為空驗證可以使用 @NotBlank @NotNull @NotEmpty 等注解來進行控制,職責分離 if (value == null) { return true; } String format = dateTime.format(); if (value.length() != format.length()) { return false; } SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); try { simpleDateFormat.parse(value); } catch (Exception e) { return false; } return true; } }
常用校驗注解標簽
- @AssertFalse 所注解的元素必須是Boolean類型,且值為false
- @AssertTrue 所注解的元素必須是Boolean類型,且值為true
- @DecimalMax 所注解的元素必須是數字,且值小於等於給定的值
- @DecimalMin 所注解的元素必須是數字,且值大於等於給定的值
- @Digits 所注解的元素必須是數字,且值必須是指定的位數
- @Future 所注解的元素必須是將來某個日期
- @Max 所注解的元素必須是數字,且值小於等於給定的值
- @Min 所注解的元素必須是數字,且值小於等於給定的值
- @Range 所注解的元素需在指定范圍區間內
- @NotNull 所注解的元素值不能為null
- @NotBlank 所注解的元素值有內容
- @Null 所注解的元素值為null
- @Past 所注解的元素必須是某個過去的日期
- @PastOrPresent 所注解的元素必須是過去某個或現在日期
- @Pattern 所注解的元素必須滿足給定的正則表達式
- @Size 所注解的元素必須是String、集合或數組,且長度大小需保證在給定范圍之內
- @Email 所注解的元素需滿足Email格式
demo
請求參數實體類
package net.ybclass.online_ybclass.model.request; import net.ybclass.online_ybclass.utils.DateTime; import javax.validation.constraints.*; public class ParamValidRequest { @Max(value = 100, message = "id=最大值不能超過100") @Min(value = 1, message = "id=最小不能小於1") private int id; @NotNull(message = "userName======》@NotNull") private String userName; @NotBlank(message = "salary======》@NotBlank") private String salary; @NotBlank @Pattern(regexp = "1234567890",message = "phone=手機號支持正則表達式,手機號必須:1234567890") private String phone; //刪除時間,當輸入的時間為2020-08-26或2020/08/26 11:22:33,時間格式不符合"yyyy-MM-dd HH:mm:ss" //@Pattern(regexp = "^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$") @NotNull @DateTime(format = "yyyy-MM-dd",message = "createDate=日期格式不正確,正確格式:yyyy-MM-dd") private String createDate; @AssertTrue(message = "flag=必須為true") private Boolean flag; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getSalary() { return salary; } public void setSalary(String salary) { this.salary = salary; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getCreateDate() { return createDate; } public void setCreateDate(String createDate) { this.createDate = createDate; } public Boolean getFlag() { return flag; } public void setFlag(Boolean flag) { this.flag = flag; } @Override public String toString() { return "TestRequest{" + "id=" + id + ", userName='" + userName + '\'' + ", salary='" + salary + '\'' + ", phone='" + phone + '\'' + ", createDate=" + createDate + ", flag=" + flag + '}'; } }
控制器
package net.ybclass.online_ybclass.controller; import net.ybclass.online_ybclass.model.request.ParamValidRequest; import net.ybclass.online_ybclass.utils.JsonData; import org.springframework.validation.BindingResult; 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.RestController; @RestController public class ParamController { @PostMapping("param") public JsonData param(@Validated @RequestBody ParamValidRequest request, BindingResult br) { //判斷參數是否校驗失敗,若校驗失敗,直接返回錯誤信息 if (br.hasErrors()) { return JsonData.buildError(br.getFieldError().getDefaultMessage()); } System.out.println(request); return JsonData.buildSuccess("ok"); } }
驗證
補充
我之前一家公司的,用這種方法不行,然后自己手動寫了個工具類,通過工具類校驗請求參數格式,如下
package com.zcsoft.rc.bms.utils; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import com.sharingif.cube.core.exception.validation.ValidationCubeException; import org.hibernate.validator.HibernateValidator; /** * @ClassName:ValidationUtils * @Description:請求參數驗證工具類 * @Author:chenyb * @Date:2020/8/14 9:50 上午 * @Versiion:1.0 */ public class ValidationUtils{ /** * 使用hibernate的注解來進行驗證 * */ private static Validator validator = Validation .byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator(); /** * 功能描述: <br> * 〈注解驗證參數〉 * * @param obj * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ public static <T> void validate(T obj) { Set<ConstraintViolation<T>> constraintViolations = validator.validate(obj); // 拋出檢驗異常 if (constraintViolations.size() > 0) { throw new ValidationCubeException(String.format("參數校驗失敗:%s", constraintViolations.iterator().next().getMessage())); } } }
控制層
@RequestMapping(value = "add", method= RequestMethod.POST) public SecurityRiskLibaryAddRsp add(SecurityRiskLibaryAddReq req){ ValidationUtils.validate(req); return securityRiskLibaryService.add(req); }